diff --git a/README.md b/README.md index b62e7965..90b86e69 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ Agent2API 把多家 AI 桌面客户端里已登录的账号接到一起,共用 | Command Code | ✓ | ✗ | ✓ | — | — | — | | Antigravity(Google,Gemini / Claude / GPT-OSS) | ✓ | ✓ | ✓ | — | — | — | | OfficeAce(华为云果办 / OfficeClaw) | ✓ | ✓ | ✓ | ✓ | ✓ | — | +| ModelScope(魔搭,国内版 / 国际版) | ✓ | ✗ 令牌长期有效 | ✓ 仅远程 | ✓ 魔粒余额 | ✓ 每日魔粒(调登录接口即触发) | — | | OrcaTerm(腾讯云遨驰终端) | ✓ | ✓ | ✓ | ✓ | — | — | | 智谱清言 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | 自定义提供商 | ✓ | — | ✓ | — | — | — | @@ -224,6 +225,8 @@ services: ### 签到中心 +后台任务统一在这一页(开关 / 间隔 / 上次结果 / 立即执行);清单存在 `~/.agent2api/config.json` 的 `scheduledTasks`,改动即时生效。 + ![签到中心页:签到总览与每日签到分组](./assets/screenshots/checkin-center.png) ## 🔧 开发与构建 @@ -252,7 +255,7 @@ macOS 的 `.dmg` **只能在 macOS 上构建**(`npm --prefix desktop-tauri run ### 仅供学习与交流 -本项目是一个用于学习 HTTP 反向代理、SSE 流式透传、多上游协议适配与桌面端打包(Tauri)等技术主题的实践项目,**仅供个人学习与研究使用**。它不是官方产品,与腾讯公司及 WorkBuddy / CodeBuddy、美团及 CatPaw、商汤及小浣熊、智谱及 AutoClaw / autoglm、阿里巴巴及 Qoder / Accio、华为云及 CodeArts / OfficeAce、字节跳动及 Trae、科大讯飞及 Loomy、百度文库及 KukuAI、长亭科技及 MonkeyCode、Command Code、Google 及 Antigravity 均无任何关联,未获得其授权、认可或赞助。 +本项目是一个用于学习 HTTP 反向代理、SSE 流式透传、多上游协议适配与桌面端打包(Tauri)等技术主题的实践项目,**仅供个人学习与研究使用**。它不是官方产品,与腾讯公司及 WorkBuddy / CodeBuddy、美团及 CatPaw、商汤及小浣熊、智谱及 AutoClaw / autoglm、阿里巴巴及 Qoder / Accio、华为云及 CodeArts / OfficeAce、字节跳动及 Trae、科大讯飞及 Loomy、百度文库及 KukuAI、长亭科技及 MonkeyCode、Command Code、Google 及 Antigravity、阿里巴巴及 ModelScope(魔搭)均无任何关联,未获得其授权、认可或赞助。 ### 关于反向代理行为 diff --git a/desktop-tauri/i18n/i18n-src/en/add-account.json b/desktop-tauri/i18n/i18n-src/en/add-account.json index aa41b503..38525346 100644 --- a/desktop-tauri/i18n/i18n-src/en/add-account.json +++ b/desktop-tauri/i18n/i18n-src/en/add-account.json @@ -20,6 +20,8 @@ "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT (three dot-separated parts; you can also paste a whole Bearer line or the data.bin content)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT (three dot-separated parts; a whole chatglm_token=… line works too)", + "ModelScope 国内版": "", + "ModelScope 国际版": "", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode International edition", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM managed endpoint; apply for the Key at integrate.api.nvidia.com", @@ -27,6 +29,7 @@ "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken is Accio's login credential (a long opaque token, not a JWT); refreshToken is optional and enables automatic renewal on expiry. Enter the credential of the {label} account — {siteNote} (the easiest way to get it: just use \"Web login\" above; no need to hunt for the token manually.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken is Trae's Cloud-IDE-JWT (three dot-separated segments), and refreshToken enables automatic renewal on expiry (this provider rotates refreshToken on every use: once exchanged, the old one is void, so do not refresh the same account from two programs at once).
When pasting manually, fill in machineId / deviceId as well: upstream ties them to the device public key uploaded at sign-in to identify the device, and swapping in a new pair from nowhere triggers the 2xxxx family of device-binding rejections.
Without these three, the proper route is \"Web login\" above; for container / remote deployments, paste the callback URL from the address bar as prompted.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "The value of monkeycode_ai_session (you can also paste the whole Cookie)", + "ms- 开头的 API 令牌": "API token starting with ms-", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken is optional and enables automatic renewal on expiry; both can be obtained from the Raccoon client login-state file.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken is optional and enables automatic renewal; both can be obtained from the client login-state file. The same Cline account works in both pools; here it is grouped under {label}.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token supports the enc: prefix (decrypted automatically on Windows). Without a refreshToken, automatic renewal is not possible.", @@ -102,6 +105,7 @@ "可选,留空使用账号昵称或邮箱": "Optional; defaults to the account nickname or email", "可选,留空则用 key 尾号": "Optional; defaults to the key suffix", "可选,留空则用 userId": "Optional; defaults to userId", + "可选,留空则用上游账号昵称": "Optional; if left blank, the upstream account's nickname is used", "可选,留空则用上游返回的账号名或账号 id": "Optional; defaults to the account name or account id returned by upstream", "可选,留空则用凭证里的账号名": "Optional; defaults to the account name in the credential", "可选,留空则用文件里的昵称": "Optional; leave empty to use the nickname from the file", @@ -293,11 +297,13 @@ "等待登录完成…": "Waiting for sign-in…", "等待网页登录…": "Waiting for web login…", "粘贴 API Key": "Paste API Key", + "粘贴 API 令牌": "Paste API token", "粘贴 Accio 的 accessToken": "Paste the Accio accessToken", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Paste Antigravity's Google refresh token (starts with 1//; pasting the whole line containing refresh_token= also works).
This is a manual entry besides web login (for example, exported from the official IDE you are already signed in to). The refresh token does not expire, and the gateway renews the access token automatically when it expires; if the token is lost, you can only go through Google authorization again, so keep it safe.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Paste the Command Code API Key (starts with user_; get it from the official CLI's ~/.commandcode/auth.json or the web studio). Pasting the whole line / with quotes / with the Bearer prefix all work; the gateway strips it down to the bare key itself. The key does not expire and there is no renewal API, so if it stops working just get a new one. When adding, the gateway runs a lightweight liveness check; a failure does not affect adding.", "粘贴 Cookie": "Paste Cookie", "粘贴 Google refresh token": "Paste Google refresh token", + "粘贴 ModelScope 的 API 令牌(ms- 开头,在 {site} 的「访问令牌」页获取)。
{siteNote}
这枚令牌两用:网关既用它调推理,也用它读账号身份、魔粒余额与每日签到。令牌长期有效、没有续期接口,失效后重新获取再粘一次即可。": "", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "Paste OrcaTerm's OAuth accessToken (a JWT with three dot-separated parts; available from the desktop client's data.bin or the web version's ot_session cookie). Pasting a whole line containing Bearer / ot_session= is fine too — the gateway strips it down to the bare token. After adding, the gateway renews it automatically (the upstream has a renewal API), so you do not need to follow the 2-hour expiry by hand.", "粘贴 Qoder 个人访问令牌(pt-…)": "Paste the Qoder personal access token (pt-…)", "粘贴 accessToken": "Paste accessToken", @@ -369,7 +375,9 @@ "这一家当前不支持网页登录,请改用填写凭证": "This provider does not support web login right now; use Enter credentials instead", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "This account has no campaigns that can be claimed automatically right now (only the daily login gift points are claimed automatically)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "This quota goes through the Start Plan channel: if forwarding reports that the Coding Plan has expired, ", + "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "This is for the China site (modelscope.cn) account: paste the China site's token. The international site (modelscope.ai) is another provider with its own account; tokens are not interchangeable between the two.", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "This is for the China site (monkeycode-ai.com) account: paste the China site's session. The international site (monkeycode-ai.net) is another provider with its own account; credentials are not interchangeable between the two.", + "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "This is for the international site (modelscope.ai) account: paste the international site's token. The China site (modelscope.cn) is another provider with its own account; tokens are not interchangeable between the two.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "This is for the international site (monkeycode-ai.net) account: paste the international site's session. The China site (monkeycode-ai.com) is another provider with its own account; credentials are not interchangeable between the two.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Select the CatPaw client's login-state file auth.json (Windows: C:\\Users\\\\.meituan-catpaw\\auth.json; macOS / Linux: ~/.meituan-catpaw/auth.json). After import the credentials live on the gateway and can be forwarded independently — no longer dependent on this machine's client.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Select the Cline client's login-state file providers.json (Windows: C:\\Users\\\\.cline\\data\\settings\\providers.json; macOS / Linux: ~/.cline/data/settings/providers.json). After import the credentials live on the gateway and can be forwarded independently — no longer dependent on this machine's client; this record goes into {label}.", diff --git a/desktop-tauri/i18n/i18n-src/en/checkin.json b/desktop-tauri/i18n/i18n-src/en/checkin.json index 6bd0db85..67023279 100644 --- a/desktop-tauri/i18n/i18n-src/en/checkin.json +++ b/desktop-tauri/i18n/i18n-src/en/checkin.json @@ -34,6 +34,7 @@ "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "Not in daily check-in: {list}. CodeArts one-time rewards are under \"Starter rewards\" below; its and ZCode's daily/plan benefits are claimed under \"Activity rewards\".", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "Not in daily check-in: {list}. CodeArts one-time rewards are under \"Starter rewards\" below, and its daily welfare is right above under \"Daily check-in\"; ZCode plan claims are under \"Activity rewards\".", "与国内版同一套任务接口 · 站点不同": "Same task API as the China edition · different site", + "与国内版同一套链路 · 站点不同、令牌不通用": "Same flow as the China edition · different site, tokens not interchangeable", "今天已领 {n} 份": "Claimed {n} today", "今天未领": "Not claimed today", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "Claimed today (Beijing time {day}) · {n} items confirmed received · can claim again tomorrow", @@ -55,10 +56,12 @@ "全部结果": "All outcomes", "全部账号均可签到": "All accounts can check in", "全部领取": "All claimed", + "关着:开机后等到窗口起点再签,随机窗口当天生效": "Off: wait for the window start after startup, so the random window applies today", "关着:所有条目都不执行": "Off: no schedule runs", + "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "minutes · accounts run at random moments inside the window; 0 = run immediately at the scheduled time", "删除失败:{error}": "Delete failed: {error}", "删除定时条目": "Delete schedule", - "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "At the scheduled time, automatically checks in the enabled accounts of the ticked providers (WorkBuddy CN uses the daily check-in API; the international version uses the daily-activity quest: probe the event, claim the daily-active reward, then keep alive with the free model and open a session over the web channel to light up the daily activity; Raccoon uses the desktop daily-points flow; AutoClaw uses the official client's daily check-in task; Qoder CN claims via the event, and accounts without an assigned event get a neutral notice; Qoder international needs a device risk-control identity (generated by the UMID component of the local Qoder client / qodercli) before the \"Daily 100 Credits\" event is even visible — without the component you get a clear explanation instead of an error; Trae claims SOLO's daily check-in points (reset at midnight), and when the upstream has no event for the account or the credentials lack a device ID you get \"not claimed + reason\" instead of an error; Loomy claims the first-login points once a day per account; KukuAI claims the \"Free points\" daily task; CodeArts claims the day's operational perks (claim → confirm → verify by re-reading; automatic runs are rate-limited to 6 write requests a day, 10 minutes apart); OfficeAce claims all of the day's rewards in one go (daily check-in + newcomer gift)). If the machine was off at the scheduled time, a catch-up check-in runs at boot, so nothing is missed. Every provider's check-in API is idempotent — running it again never claims twice.", + "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "Signs in the available accounts of the selected providers when due (WorkBuddy CN uses its daily check-in API; WorkBuddy Intl uses the daily activity task: probe activities, claim the daily reward, then keep a free model warm and open a web session to light up the streak; Raccoon uses its desktop daily points chain; AutoClaw uses the official client's daily sign-in task; Qoder CN claims campaign rewards and shows a neutral notice for accounts without campaigns; Qoder Intl needs a device risk identity (generated by the UMID component of the local Qoder client / qodercli) to see the 'daily 100 Credits' campaign and shows a clear explanation instead of an error when the component is missing; Trae claims the SOLO daily check-in credits (reset at local midnight) and reports 'not claimed + reason' instead of an error when the upstream has no campaign for the account or the credential has no device id; Loomy calls its first-login points endpoint once a day; KukuAI claims the 'free points' daily tasks; CodeArts claims the daily ops welfare (claim → confirm → read back, with automatic runs limited to 6 writes per day and 10 minutes apart); OfficeAce claims all of the day's rewards (daily check-in + newcomer gift) in one call). With 'random offset N minutes', the accounts of a round run spread across their own window (clamped to 0:00-23:59 of the same day) instead of all at the same minute; if the window has already passed they all run immediately. Missed runs are caught up after startup so nothing is lost when the machine was off (turn off 'Startup catch-up' to wait for the window start instead). Every provider's check-in API is idempotent, so repeated runs never double-claim.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "At the scheduled time, auto check-in runs for the available accounts of the selected providers (WorkBuddy China uses the daily check-in API; International uses daily activity tasks — detect the campaign, claim the daily-activity reward, then keep the account alive with free models; Raccoon uses the desktop daily points flow; AutoClaw uses the official client's daily check-in task; Qoder China uses campaign claims, and accounts with no campaign assigned get a neutral notice; Qoder International needs a device risk-control identity first (generated by the UMID component of the local Qoder client / qodercli) to see the \"Daily 100 Credits\" campaign, and a missing component yields a clear explanation instead of an error; Trae claims SOLO's daily check-in points (reset at midnight by calendar day), and when the upstream has no campaign for the account or the credential has no device ID the result is \"not claimed + the specific reason\" instead of an error; Loomy awards first-login points once a day per account; KukuAI claims the \"Free points\" daily tasks; CodeArts claims that day's campaign welfare (claim → confirm → read back to verify; automatic runs are limited to 6 write attempts per day with a 10-minute gap); OfficeAce claims all of that day's rewards in one action (daily check-in + newcomer gift)). If the machine was off at the scheduled time, the missed run is made up automatically after it starts — nothing is skipped just because the machine was off. Every provider's check-in API is idempotent, so running it again never claims twice.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "At the scheduled time, auto check-in runs for the available accounts of the selected providers (WorkBuddy China uses the daily check-in API; International uses daily activity tasks — detect the campaign, claim the daily-activity reward, then keep the account alive with free models; Raccoon uses the desktop daily points flow; AutoClaw uses the official client's daily check-in task; Qoder China uses campaign claims, and accounts with no campaign assigned get a neutral notice; Qoder International needs a device risk-control identity first (generated by the UMID component of the local Qoder client / qodercli) to see the \"Daily 100 Credits\" campaign, and a missing component yields a clear explanation instead of an error; Trae claims SOLO's daily check-in points (reset at midnight by calendar day), and when the upstream has no campaign for the account or the credential has no device ID the result is \"not claimed + the specific reason\" instead of an error; Loomy awards first-login points once a day per account; KukuAI claims the \"Free points\" daily tasks; OfficeAce claims all of that day's rewards in one action (daily check-in + newcomer gift)). If the machine was off at the scheduled time, the missed run is made up automatically after it starts — nothing is skipped just because the machine was off. Every provider's check-in API is idempotent, so running it again never claims twice.", "到点时逐个签到,已勾 {n} / {total} 家": "Checked {n} of {total} — each is checked in at the scheduled time", @@ -72,6 +75,9 @@ "可领奖": "Can claim", "后端未返回定时签到数据": "Backend returned no schedule data", "后端未返回签到中心数据": "The backend did not return check-in center data", + "启动补签": "Startup catch-up", + "启动补签已关闭": "Startup catch-up disabled", + "启动补签已开启": "Startup catch-up enabled", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "International check-in requires the UMID component to generate a device risk-control identity (not detected on this machine).", "在途": "Traveling", "填入缺省链": "Fill in default chain", @@ -102,6 +108,7 @@ "开学季执行完成:{message}": "School-season run completed: {message}", "开学季活动": "School-season event", "开着:启用的条目按各自时刻执行": "On: enabled schedules run at their own times", + "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "On: schedules not yet run today catch up right after startup, ignoring the random window", "待签": "Not checked in", "待领新手福利": "Starter rewards to claim", "总开关": "Master switch", @@ -128,6 +135,7 @@ "新手福利": "Starter rewards", "新手福利有 {n} 项领取失败,可重试": "{n} starter reward(s) failed to claim — you can retry", "无": "None", + "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "No dedicated check-in API · hits the login-info endpoint once a day per account (which grants the daily Magicubes)", "无独立签到接口 · 每天替账号打一次首次登录积分": "No dedicated check-in API · awards first-login points once a day per account", "无账号": "No accounts", "暂不可领": "Not claimable yet", @@ -151,6 +159,7 @@ "正在读取签到数据…": "Loading check-in data…", "每天 {time}": "Daily at {time}", "每天 {time} · {scope}": "Daily {time} · {scope}", + "每天 {time} · 随机前后 {n} 分钟 · {scope}": "Daily {time} ± {n} min · {scope}", "每天时刻": "Daily time", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "One row per account per check-in run · outcomes and gains as recorded by the backend", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "Daily activity tasks · a web-app conversation lights up the daily activity, only claims add points · the two can run separately", @@ -226,6 +235,7 @@ "重试": "Retry", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "Limited-time trial plan · claim requires a slider CAPTCHA · view and claim one by one", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "Limited-time trial plan (start-plan), one per day during the campaign · claim requires a slider CAPTCHA", + "随机前后": "Random offset", "需真实操作": "Requires real action", "非活动期": "Event inactive", "项": "items", diff --git a/desktop-tauri/i18n/i18n-src/ja/add-account.json b/desktop-tauri/i18n/i18n-src/ja/add-account.json index 09069fed..f2d7d5d0 100644 --- a/desktop-tauri/i18n/i18n-src/ja/add-account.json +++ b/desktop-tauri/i18n/i18n-src/ja/add-account.json @@ -20,6 +20,8 @@ "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT(ドット区切り 3 パート。Bearer 行全体や data.bin の中身を貼っても可)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT(3 つのドット区切り部分。chatglm_token=… の行をそのまま貼っても可)", + "ModelScope 国内版": "", + "ModelScope 国际版": "", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode 国際版", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM のマネージドエンドポイント。Key は integrate.api.nvidia.com で申請します", @@ -27,6 +29,7 @@ "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken は Accio のログイン認証情報です(長い不透明な token 文字列で、JWT ではありません);refreshToken は任意で、入力すると期限切れ時に自動更新できます。{label}アカウントの認証情報を入力してください —— {siteNote}(最も簡単な方法:上の「ウェブログイン」を使えば token を手動で探す必要はありません。)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken は Trae の Cloud-IDE-JWT(3 段のドット区切り)です。refreshToken は期限切れ時の自動更新に使用します(本家の refreshToken は 1 回ごとに交換され、一度更新すると古いものは無効になります。そのため 2 つのプログラムで同じアカウントを同時に更新しないでください)。
手動で貼り付ける場合は machineId / deviceId も一緒に入力してください:アップストリームはこれらをログイン時にアップロードされたデバイス公開鍵と紐付けてデバイスを判定するため、根拠なく別のペアにすると 2xxxx 系のデバイスバインディング拒否に当たります。
この 3 つがない場合の正道は上の「ウェブログイン」を使うことです;コンテナ / リモートデプロイ形態では案内に従ってアドレスバーのコールバックアドレスを貼り付けてください。", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "monkeycode_ai_session の値(Cookie 全体をそのまま貼り付けても可)", + "ms- 开头的 API 令牌": "ms- で始まる API トークン", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken は任意で、入力すると期限切れ時に自動更新できます;どちらも小浣熊クライアントのログイン状態ファイルから取得できます。", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken は任意で、入力すると自動更新できます;どちらもクライアントのログイン状態ファイルから取得できます。同じ Cline アカウントはどちらのプールでも使え、ここでは {label} に分類されます。", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token は enc: プレフィックスに対応しています(Windows では自動復号)。refreshToken を入力しないと自動更新できません。", @@ -102,6 +105,7 @@ "可选,留空使用账号昵称或邮箱": "任意、空欄の場合はアカウントのニックネームまたはメールアドレスを使用", "可选,留空则用 key 尾号": "任意、空欄の場合は key の末尾を使用", "可选,留空则用 userId": "任意、空欄の場合は userId を使用", + "可选,留空则用上游账号昵称": "任意。空欄の場合は上流アカウントのニックネームを使用", "可选,留空则用上游返回的账号名或账号 id": "任意、空欄の場合はアップストリームが返したアカウント名またはアカウント id を使用", "可选,留空则用凭证里的账号名": "任意、空欄の場合は認証情報のアカウント名を使用", "可选,留空则用文件里的昵称": "任意。空欄の場合はファイル内のニックネームを使用", @@ -293,11 +297,13 @@ "等待登录完成…": "ログインの完了を待っています…", "等待网页登录…": "ウェブログインを待っています…", "粘贴 API Key": "API Key を貼り付け", + "粘贴 API 令牌": "API トークンを貼り付け", "粘贴 Accio 的 accessToken": "Accio の accessToken を貼り付け", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Antigravity の Google refresh token を貼り付け(1// で始まる;refresh_token= を含む行全体をそのまま貼り付けても可)。
これはウェブログイン以外の手動入り口です(例:ログイン済みの公式 IDE からエクスポート)。refresh token は期限切れにならず、access token の期限切れはゲートウェイが自動で更新します;トークンを紛失すると Google の認可をやり直すしかないため、大切に保管してください。", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Command Code の API Key を貼り付け(user_ で始まる;公式 CLI の ~/.commandcode/auth.json またはウェブの studio から取得)。行全体 / 引用符付き / Bearer プレフィックス付きのまま貼り付けても構いません。ゲートウェイが自動で裸の key に剥がします。key は期限切れにならず、更新用 API もありません。無効になったら取得し直してください;追加時にゲートウェイが軽量な死活確認を 1 回行いますが、失敗しても追加には影響しません。", "粘贴 Cookie": "Cookie を貼り付け", "粘贴 Google refresh token": "Google refresh token を貼り付け", + "粘贴 ModelScope 的 API 令牌(ms- 开头,在 {site} 的「访问令牌」页获取)。
{siteNote}
这枚令牌两用:网关既用它调推理,也用它读账号身份、魔粒余额与每日签到。令牌长期有效、没有续期接口,失效后重新获取再粘一次即可。": "", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "OrcaTerm の OAuth accessToken(ドット区切り 3 パートの JWT。デスクトップクライアントの data.bin か Web 版の Cookie ot_session から取得)を貼り付けます。Bearer / ot_session= を含む行をそのまま貼ってもよく、ゲートウェイが裸のトークンに剥がします。追加後はゲートウェイが自動で更新するため(上流に更新 API があります)、2 時間の有効期限を手動で追う必要はありません。", "粘贴 Qoder 个人访问令牌(pt-…)": "Qoder の個人アクセストークン(pt-…)を貼り付け", "粘贴 accessToken": "accessToken を貼り付け", @@ -369,7 +375,9 @@ "这一家当前不支持网页登录,请改用填写凭证": "このプロバイダーは現在ウェブログインに対応していません。認証情報の入力に切り替えてください", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "このアカウントには現在自動で受け取れるイベントがありません(自動で受け取るのは毎日ログインで付与されるポイントのみです)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "このクォータは「イベントプラン」の経路を使用します:転送時にコーディングプランの期限切れが表示された場合は、", + "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "ここには中国サイト(modelscope.cn)のアカウントを入力します。中国サイトのトークンを貼り付けてください。国際サイト(modelscope.ai)は別の provider・別のアカウントで、両者のトークンに互換性はありません。", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "ここには中国サイト(monkeycode-ai.com)のアカウントを入力します:中国サイトの session を貼り付けてください。国際サイト(monkeycode-ai.net)は別のプロバイダーで、アカウントも別です。両者の認証情報は共用できません。", + "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "ここには国際サイト(modelscope.ai)のアカウントを入力します。国際サイトのトークンを貼り付けてください。中国サイト(modelscope.cn)は別の provider・別のアカウントで、両者のトークンに互換性はありません。", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "ここには国際サイト(monkeycode-ai.net)のアカウントを入力します:国際サイトの session を貼り付けてください。中国サイト(monkeycode-ai.com)は別のプロバイダーで、アカウントも別です。両者の認証情報は共用できません。", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "CatPaw クライアントのログイン状態ファイル auth.json を選択します(Windows:C:\\Users\\<ユーザー名>\\.meituan-catpaw\\auth.json、macOS / Linux:~/.meituan-catpaw/auth.json)。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります(本機クライアントに依存しません)。", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Cline クライアントのログイン状態ファイル providers.json を選択します(Windows:C:\\Users\\<ユーザー名>\\.cline\\data\\settings\\providers.json、macOS / Linux:~/.cline/data/settings/providers.json)。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります(本機クライアントに依存しません)。この項目は {label} に登録されます。", diff --git a/desktop-tauri/i18n/i18n-src/ja/checkin.json b/desktop-tauri/i18n/i18n-src/ja/checkin.json index f52646fc..a5a37c51 100644 --- a/desktop-tauri/i18n/i18n-src/ja/checkin.json +++ b/desktop-tauri/i18n/i18n-src/ja/checkin.json @@ -34,6 +34,7 @@ "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "デイリーチェックインの対象外:{list}。CodeArts の一度きりの特典は下の「初心者ボーナス」に、CodeArts と ZCode の日次/プラン特典の受け取りは「アクティビティ特典」にあります。", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "デイリーチェックインの対象外:{list}。CodeArts の一度きりの特典は下の「初心者ボーナス」、CodeArts のデイリー特典はすぐ上の「デイリーチェックイン」にあります。ZCode のプラン受け取りは「アクティビティ特典」です。", "与国内版同一套任务接口 · 站点不同": "中国版と同じタスク API · サイトが異なる", + "与国内版同一套链路 · 站点不同、令牌不通用": "中国版と同じフロー · サイトが異なり、トークンに互換性なし", "今天已领 {n} 份": "本日 {n} 件受け取り済み", "今天未领": "本日は未受取", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "本日(北京時間 {day})受け取り済み · 公式に {n} 件の到着を確認 · 明日また受け取れます", @@ -55,10 +56,12 @@ "全部结果": "すべての結果", "全部账号均可签到": "すべてのアカウントがチェックイン可能", "全部领取": "すべて受け取り済み", + "关着:开机后等到窗口起点再签,随机窗口当天生效": "オフ:起動後はウィンドウ開始まで待ち、当日からランダムウィンドウを適用", "关着:所有条目都不执行": "オフ:どのスケジュールも実行されません", + "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "分 · ウィンドウ内で各アカウントをランダムな時刻に実行、0 = 定刻に即実行", "删除失败:{error}": "削除に失敗しました:{error}", "删除定时条目": "スケジュールを削除", - "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると、チェックを入れたプロバイダーの利用可能なアカウントを自動でチェックインします(WorkBuddy 国内版は毎日チェックイン API、国際版はデイリーアクティブクエスト:イベントを探し、デイリーアクティブ報酬を受け取り、無料モデルでキープアライブし、Web チャネルでセッションを張って日次アクティブを点灯。小浣熊はデスクトップの日次ポイント経路。AutoClaw は公式クライアントの毎日チェックインタスク。Qoder 中国版はイベント受領で、イベントを付与されていないアカウントは中立的な通知を受け取ります。Qoder 国際版はデバイスのリスク管理 ID(ローカル Qoder クライアント / qodercli の UMID コンポーネントが生成)を持たないと「毎日 100 Credits」イベントが表示されず、コンポーネントがなければエラーではなく明確な説明が返ります。Trae は SOLO の毎日チェックインポイントを受け取り(0 時リセット)、上流がイベントを用意していない、または認証情報にデバイス ID がない場合は「未受領 + 理由」が返ります。Loomy は毎日 1 回初回ログインポイントを付け、KukuAI は「無料ポイント」の日次タスクを受け取り、CodeArts は当日の運営特典を受け取ります(受領 → 確認 → 再読で検証。自動実行は 1 日 6 回 / 10 分間隔の書き込みレート制限内)。OfficeAce はその日の特典を一括で受け取ります(毎日チェックイン + 新規特典))。時刻を逃しても起動時に自動で追補するため、電源が入っていなくても取りこぼしません。各社のチェックイン API は冪等で、繰り返しても二重受け取りにはなりません。", + "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると選択プロバイダーの利用可能なアカウントをサインインします(WorkBuddy 中国版は毎日チェックイン API、国際版はデイリーアクティブタスク:アクティビティ検出・日次報酬受取・無料モデルでキープアライブと Web セッションで連続日数を点灯。小浣熊はデスクトップの毎日ポイント経路、AutoClaw は公式クライアントの毎日サインインタスク、Qoder 中国版はキャンペーン受取でキャンペーン未配信のアカウントには中立の案内を表示、Qoder 国際版はデバイス風控身分(ローカルの Qoder クライアント / qodercli の UMID コンポーネントが生成)が必要で、コンポーネント欠如時はエラーではなく明確な説明を表示。Trae は SOLO の毎日チェックインクレジット(現地 0 時リセット)を受け取り、上流がアカウントにキャンペーンを出していない場合や資格情報にデバイス ID がない場合はエラーではなく「未受取 + 理由」を返します。Loomy は毎日初回ログインポイントを 1 回呼び、KukuAI は「無料ポイント」の毎日タスクを受け取り、CodeArts は当日の運営特典(受取 → 確認 → 読み戻し、自動実行は 1 日 6 回・10 分間隔の書き込み制限あり)を受け取り、OfficeAce はその日の全報酬(毎日チェックイン + 新規特典)を 1 回で受け取ります)。「ランダム幅 N 分」を設定すると、その回のアカウントは各自のウィンドウ内(当日 0:00〜23:59 にクランプ)に分散して実行され、同じ 1 分に集中しません。ウィンドウを過ぎている場合は全員すぐに実行します。逃した回は起動後にキャッチアップするので、電源が入っていなかったことで失われることはありません(「起動時キャッチアップ」をオフにするとウィンドウ開始まで待つ動作になります)。各プロバイダーのチェックイン API は冪等で、繰り返し実行しても二重取得にはなりません。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると、チェックしたプロバイダーの利用可能なアカウントを自動でチェックインします(WorkBuddy 中国版はデイリーチェックイン API、国際版はデイリーアクティブタスク:イベントを検出して日活報酬を受け取り、無料モデルでキープアライブ。小浣熊はデスクトップ版のデイリー積分経路。AutoClaw は公式クライアントのデイリーチェックインタスク。Qoder 中国版はイベント受け取りで、イベントが配信されていないアカウントには中立的な案内が出ます。Qoder 国際版はデバイスリスク制御 ID(本機の Qoder クライアント / qodercli の UMID コンポーネントで生成)を付けて初めて「毎日 100 Credits」イベントが見えるようになり、コンポーネントが欠けている場合はエラーではなく明確な説明が出ます。Trae は SOLO のデイリーチェックイン積分を受け取り(自然日 0 時にリセット)、アップストリームがそのアカウントにイベントを開いていない場合や認証情報にデバイス ID がない場合は、エラーではなく「未受け取り + 具体的な理由」が返ります。Loomy は毎日アカウントの初回ログイン積分を 1 回付与します。KukuAI は「無料積分受け取り」のデイリータスクを消化します;CodeArts はその日の運営特典を受け取ります(受け取り → 確認 → 読み戻し検証。自動実行は 1 日 6 回・間隔 10 分の書き込み制限を受けます);OfficeAce はその日の報酬を一度の操作でまとめて受け取ります(毎日チェックイン+新規特典))。時刻を逃しても、起動後に自動で補完チェックインされ、当時電源が入っていなかったことを理由に漏れることはありません。各社のチェックイン API はすべて冪等なので、繰り返し実行しても二重に受け取ることはありません。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると、チェックしたプロバイダーの利用可能なアカウントを自動でチェックインします(WorkBuddy 中国版はデイリーチェックイン API、国際版はデイリーアクティブタスク:イベントを検出して日活報酬を受け取り、無料モデルでキープアライブ。小浣熊はデスクトップ版のデイリー積分経路。AutoClaw は公式クライアントのデイリーチェックインタスク。Qoder 中国版はイベント受け取りで、イベントが配信されていないアカウントには中立的な案内が出ます。Qoder 国際版はデバイスリスク制御 ID(本機の Qoder クライアント / qodercli の UMID コンポーネントで生成)を付けて初めて「毎日 100 Credits」イベントが見えるようになり、コンポーネントが欠けている場合はエラーではなく明確な説明が出ます。Trae は SOLO のデイリーチェックイン積分を受け取り(自然日 0 時にリセット)、アップストリームがそのアカウントにイベントを開いていない場合や認証情報にデバイス ID がない場合は、エラーではなく「未受け取り + 具体的な理由」が返ります。Loomy は毎日アカウントの初回ログイン積分を 1 回付与します。KukuAI は「無料積分受け取り」のデイリータスクを消化します;OfficeAce はその日の報酬を一度の操作でまとめて受け取ります(毎日チェックイン+新規特典))。時刻を逃しても、起動後に自動で補完チェックインされ、当時電源が入っていなかったことを理由に漏れることはありません。各社のチェックイン API はすべて冪等なので、繰り返し実行しても二重に受け取ることはありません。", "到点时逐个签到,已勾 {n} / {total} 家": "定刻に 1 社ずつチェックインします。選択 {n} / {total} 社", @@ -72,6 +75,9 @@ "可领奖": "受け取り可能", "后端未返回定时签到数据": "バックエンドがスケジュールデータを返しませんでした", "后端未返回签到中心数据": "バックエンドがチェックインセンターのデータを返しませんでした", + "启动补签": "起動時キャッチアップ", + "启动补签已关闭": "起動時キャッチアップを無効にしました", + "启动补签已开启": "起動時キャッチアップを有効にしました", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "国際版のチェックインには、UMID コンポーネントで生成するデバイスリスク制御 ID が必要です(本機では検出されませんでした)。", "在途": "旅行中", "填入缺省链": "既定のチェーンを入力", @@ -102,6 +108,7 @@ "开学季执行完成:{message}": "新学期の実行が完了:{message}", "开学季活动": "新学期イベント", "开着:启用的条目按各自时刻执行": "オン:有効なスケジュールがそれぞれの時刻に実行されます", + "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "オン:起動後、本日未実行のスケジュールをランダムウィンドウを無視して即補完", "待签": "未チェックイン", "待领新手福利": "受け取り待ちの初心者ボーナス", "总开关": "マスタースイッチ", @@ -128,6 +135,7 @@ "新手福利": "初心者ボーナス", "新手福利有 {n} 项领取失败,可重试": "初心者ボーナスで {n} 件の受け取りに失敗しました。再試行できます", "无": "なし", + "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "専用のチェックイン API なし · 1 日 1 回アカウントの代わりにログイン情報エンドポイントを叩く(それが当日の魔粒)", "无独立签到接口 · 每天替账号打一次首次登录积分": "専用のチェックイン API なし · 毎日アカウントの初回ログイン積分を 1 回付与", "无账号": "アカウントなし", "暂不可领": "受け取り不可", @@ -151,6 +159,7 @@ "正在读取签到数据…": "チェックインデータを読み込み中…", "每天 {time}": "毎日 {time}", "每天 {time} · {scope}": "毎日 {time} · {scope}", + "每天 {time} · 随机前后 {n} 分钟 · {scope}": "毎日 {time} 前後 {n} 分 · {scope}", "每天时刻": "毎日の時刻", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "チェックイン1回ごとに · アカウントごとに1行 · 結果と収益はバックエンドの記録が正", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "毎日のアクティブタスク · Webチャネルの会話で日活を達成、ポイントは受け取りで加算 · 両方は別々に実行可能", @@ -226,6 +235,7 @@ "重试": "再試行", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "期間限定お試しプラン · 受け取りにはスライダー認証が必要 · 1 件ずつ確認して受け取り", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "期間限定体験プラン(start-plan)。開催期間中は毎日 1 件 · 受け取りにはスライダー認証が必要", + "随机前后": "ランダム幅", "需真实操作": "実際の操作が必要", "非活动期": "イベント期間外", "项": "件", diff --git a/desktop-tauri/i18n/i18n-src/ko/add-account.json b/desktop-tauri/i18n/i18n-src/ko/add-account.json index 8136ce9e..6da17b9c 100644 --- a/desktop-tauri/i18n/i18n-src/ko/add-account.json +++ b/desktop-tauri/i18n/i18n-src/ko/add-account.json @@ -20,6 +20,8 @@ "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT(점 3개 구분. Bearer 전체 줄 또는 data.bin 내용을 붙여넣어도 됨)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT(점 3개로 구분된 형식. chatglm_token=… 줄을 그대로 붙여도 됩니다)", + "ModelScope 国内版": "", + "ModelScope 国际版": "", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode 국제판", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM 관리형 엔드포인트, Key는 integrate.api.nvidia.com에서 신청합니다", @@ -27,6 +29,7 @@ "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken은 Accio의 로그인 자격 증명입니다 (길고 불투명한 token 문자열이며 JWT가 아닙니다); refreshToken은 선택이며, 입력하면 만료 시 자동 갱신됩니다. {label} 계정의 자격 증명을 입력하세요 — {siteNote} (가장 쉽게 얻는 방법: 위의 「웹 로그인」을 바로 사용하세요. token을 직접 찾을 필요가 없습니다.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken은 Trae의 Cloud-IDE-JWT이며(3단 점 구분), refreshToken은 만료 시 자동 갱신에 사용됩니다 (이 제공자는 refreshToken이 교환할 때마다 바뀝니다: 한 번 교환하면 이전 것은 무효가 되므로 두 프로그램에서 같은 계정을 동시에 갱신하지 마세요).
수동으로 붙여넣을 때는 machineId / deviceId도 함께 입력하세요: 업스트림은 이를 로그인 시 업로드한 기기 공개 키와 묶어 기기를 판별하므로, 갑자기 새로운 값을 넣으면 2xxxx 계열 기기 바인딩 거부가 발생합니다.
이 세 가지가 없을 때의 올바른 방법은 위의 「웹 로그인」이며, 컨테이너 / 원격 배포 환경에서는 안내에 따라 주소 표시줄의 콜백 주소를 붙여넣으면 됩니다.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "monkeycode_ai_session의 값 (전체 Cookie를 붙여넣어도 됨)", + "ms- 开头的 API 令牌": "ms- 로 시작하는 API 토큰", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken은 선택이며, 입력하면 만료 시 자동 갱신됩니다; 둘 다 小浣熊 클라이언트 로그인 상태 파일에서 얻을 수 있습니다.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken은 선택이며, 입력하면 자동 갱신됩니다; 둘 다 클라이언트 로그인 상태 파일에서 얻을 수 있습니다. 같은 Cline 계정은 두 풀 모두에서 사용할 수 있으며, 여기서는 {label}로 분류됩니다.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token은 enc: 접두사를 지원합니다 (Windows에서는 자동 복호화). refreshToken을 입력하지 않으면 자동 갱신할 수 없습니다.", @@ -102,6 +105,7 @@ "可选,留空使用账号昵称或邮箱": "선택, 비워 두면 계정 닉네임 또는 이메일 사용", "可选,留空则用 key 尾号": "선택, 비워 두면 key 끝자리 사용", "可选,留空则用 userId": "선택, 비워 두면 userId 사용", + "可选,留空则用上游账号昵称": "선택 사항. 비워 두면 업스트림 계정 닉네임을 사용합니다", "可选,留空则用上游返回的账号名或账号 id": "선택, 비워 두면 업스트림이 반환한 계정 이름 또는 계정 id 사용", "可选,留空则用凭证里的账号名": "선택, 비워 두면 자격 증명의 계정 이름 사용", "可选,留空则用文件里的昵称": "선택 사항, 비워 두면 파일의 닉네임 사용", @@ -293,11 +297,13 @@ "等待登录完成…": "로그인 완료 대기 중…", "等待网页登录…": "웹 로그인 대기 중…", "粘贴 API Key": "API Key 붙여넣기", + "粘贴 API 令牌": "API 토큰 붙여넣기", "粘贴 Accio 的 accessToken": "Accio의 accessToken 붙여넣기", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Antigravity의 Google refresh token을 붙여넣으세요 (1//로 시작; refresh_token=이 포함된 줄 전체를 붙여넣어도 됨).
웹 로그인 외의 수동 입구입니다(예: 로그인된 공식 IDE에서 내보내기). refresh token은 만료되지 않으며, access token 만료 시 게이트웨이가 자동으로 갱신합니다; 토큰을 잃어버리면 Google 인가를 다시 받아야 하므로 잘 보관하세요.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Command Code의 API Key를 붙여넣으세요 (user_로 시작; 공식 CLI의 ~/.commandcode/auth.json 또는 웹 studio에서 획득). 줄 전체 / 따옴표 포함 / Bearer 접두사 포함 그대로 붙여넣어도 됩니다. 게이트웨이가 알아서 순수한 key만 추출합니다. key는 만료되지 않고 갱신 인터페이스도 없으므로, 무효가 되면 다시 받으면 됩니다; 추가 시 게이트웨이가 가벼운 활성 확인을 한 번 수행하며, 실패해도 추가에는 영향을 주지 않습니다.", "粘贴 Cookie": "Cookie 붙여넣기", "粘贴 Google refresh token": "Google refresh token 붙여넣기", + "粘贴 ModelScope 的 API 令牌(ms- 开头,在 {site} 的「访问令牌」页获取)。
{siteNote}
这枚令牌两用:网关既用它调推理,也用它读账号身份、魔粒余额与每日签到。令牌长期有效、没有续期接口,失效后重新获取再粘一次即可。": "", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "OrcaTerm의 OAuth accessToken(점 3개로 구분된 JWT. 데스크톱 클라이언트의 data.bin 또는 웹 버전 Cookie ot_session에서 확인)을 붙여넣으세요. Bearer / ot_session=이 포함된 줄을 그대로 붙여넣어도 되며, 게이트웨이가 토큰만 추출합니다. 추가 후에는 게이트웨이가 자동으로 갱신하므로(업스트림에 갱신 API가 있음) 2시간 만료를 직접 따라갈 필요가 없습니다.", "粘贴 Qoder 个人访问令牌(pt-…)": "Qoder 개인 액세스 토큰(pt-…) 붙여넣기", "粘贴 accessToken": "accessToken 붙여넣기", @@ -369,7 +375,9 @@ "这一家当前不支持网页登录,请改用填写凭证": "이 제공자는 현재 웹 로그인을 지원하지 않습니다. 대신 자격 증명 입력을 사용하세요", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "이 계정에는 현재 자동으로 수령할 수 있는 이벤트가 없습니다 (매일 로그인 보너스 포인트만 자동 수령합니다)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "이 할당량은 「이벤트 플랜」 채널을 사용합니다: 포워딩 시 코딩 플랜이 만료되었다는 안내가 나오면, ", + "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "여기에는 중국 사이트(modelscope.cn) 계정을 입력합니다. 중국 사이트의 토큰을 붙여넣으세요. 인터내셔널 사이트(modelscope.ai)는 다른 provider·다른 계정이며, 양쪽 토큰은 호환되지 않습니다.", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "여기에는 중국 사이트(monkeycode-ai.com)의 계정을 입력합니다: 중국 사이트의 session을 붙여넣으세요. 국제 사이트(monkeycode-ai.net)는 다른 제공자이며 별도의 계정입니다. 양쪽 자격 증명은 호환되지 않습니다.", + "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "여기에는 인터내셔널 사이트(modelscope.ai) 계정을 입력합니다. 인터내셔널 사이트의 토큰을 붙여넣으세요. 중국 사이트(modelscope.cn)는 다른 provider·다른 계정이며, 양쪽 토큰은 호환되지 않습니다.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "여기에는 국제 사이트(monkeycode-ai.net)의 계정을 입력합니다: 국제 사이트의 session을 붙여넣으세요. 중국 사이트(monkeycode-ai.com)는 다른 제공자이며 별도의 계정입니다. 양쪽 자격 증명은 호환되지 않습니다.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "CatPaw 클라이언트의 로그인 상태 파일 auth.json을 선택하세요 (Windows: C:\\Users\\<사용자 이름>\\.meituan-catpaw\\auth.json, macOS / Linux: ~/.meituan-catpaw/auth.json). 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다 — 더 이상 이 컴퓨터의 클라이언트에 의존하지 않습니다.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Cline 클라이언트의 로그인 상태 파일 providers.json을 선택하세요 (Windows: C:\\Users\\<사용자 이름>\\.cline\\data\\settings\\providers.json, macOS / Linux: ~/.cline/data/settings/providers.json). 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다 — 더 이상 이 컴퓨터의 클라이언트에 의존하지 않습니다. 이 항목은 {label}에 등록됩니다.", diff --git a/desktop-tauri/i18n/i18n-src/ko/checkin.json b/desktop-tauri/i18n/i18n-src/ko/checkin.json index 8a2bd96a..fb824c34 100644 --- a/desktop-tauri/i18n/i18n-src/ko/checkin.json +++ b/desktop-tauri/i18n/i18n-src/ko/checkin.json @@ -34,6 +34,7 @@ "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "일일 출석 제외: {list}. CodeArts의 일회성 보상은 아래 \"입문 혜택\"에 있으며, CodeArts와 ZCode의 일일/플랜 혜택 수령은 \"활동 혜택\"에서 볼 수 있습니다.", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "일일 출석 제외: {list}. CodeArts의 일회성 보상은 아래 \"입문 혜택\"에, CodeArts의 일일 혜택은 바로 위 \"일일 출석\"에 있습니다. ZCode의 플랜 수령은 \"활동 혜택\"에서 볼 수 있습니다.", "与国内版同一套任务接口 · 站点不同": "중국판과 동일한 작업 인터페이스 · 사이트만 다름", + "与国内版同一套链路 · 站点不同、令牌不通用": "중국판과 동일한 흐름 · 사이트가 다르고 토큰은 호환되지 않음", "今天已领 {n} 份": "오늘 {n}건 받음", "今天未领": "오늘 미수령", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "오늘(베이징 시간 {day}) 수령 완료 · 공식 확인 반영 {n}건 · 내일 다시 수령 가능", @@ -55,10 +56,12 @@ "全部结果": "모든 결과", "全部账号均可签到": "모든 계정이 출석할 수 있습니다", "全部领取": "전체 수령 완료", + "关着:开机后等到窗口起点再签,随机窗口当天生效": "꺼짐: 시작 후 윈도 시작까지 기다리며, 당일부터 랜덤 윈도가 적용", "关着:所有条目都不执行": "꺼짐: 어떤 항목도 실행되지 않습니다", + "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "분 · 윈도 내에서 계정별로 무작위 시각에 실행, 0 = 정시에 즉시 실행", "删除失败:{error}": "삭제 실패: {error}", "删除定时条目": "예약 항목 삭제", - "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "예정 시각에 체크한 제공자의 사용 가능한 계정을 자동으로 출석 체크합니다 (WorkBuddy 국내판은 매일 출석 API, 국제판은 데일리 액티비티 퀘스트: 이벤트 탐색 → 데일리 액티브 보상 수령 → 무료 모델로 킵얼라이브하고 웹 채널로 세션을 열어 일일 활성 점등. 소浣熊(샤오환슝)은 데스크톱 일일 포인트 경로, AutoClaw 는 공식 클라이언트의 매일 출석 작업. Qoder 중국판은 이벤트 수령 방식이며 이벤트를 배정받지 못한 계정은 중립적 안내를 받습니다. Qoder 국제판은 기기 리스크 관리 신원(로컬 Qoder 클라이언트 / qodercli 의 UMID 컴포넌트가 생성)을 먼저 갖춰야 \"매일 100 Credits\" 이벤트가 보이며, 컴포넌트가 없으면 오류 대신 명확한 설명을 받습니다. Trae 는 SOLO 의 매일 출석 포인트를 수령하고(자정 리셋), 업스트림이 이벤트를 열지 않았거나 자격 증명에 기기 번호가 없으면 오류 대신 \"미수령 + 사유\"를 받습니다. Loomy 는 매일 계정별 첫 로그인 포인트를 한 번 채우고, KukuAI 는 \"무료 포인트\" 일일 작업을 수령하며, CodeArts 는 당일 운영 혜택을 수령합니다(수령 → 확인 → 재조회 검증. 자동 실행은 하루 6 회 / 10 분 간격 쓰기 요청 제한 내). OfficeAce 는 당일 모든 보상을 한 번에 수령합니다 (매일 출석 + 신규 혜택)). 예정 시각을 놓쳐도 부팅 후 자동으로 보충하므로 전원이 꺼져 있어도 누락되지 않습니다. 각사 출석 API 는 멱등하여 반복 실행해도 중복 수령되지 않습니다.", + "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "시간이 되면 선택한 제공자의 사용 가능한 계정으로 출석합니다(WorkBuddy 중국판은 일일 출석 API, 국제판은 데일리 액티브 작업: 액티비티 탐지·일일 보상 수령·무료 모델로 키프얼라이브와 웹 세션으로 연속일 점등. 라쿤은 데스크톱 일일 포인트 경로, AutoClaw는 공식 클라이언트의 일일 출석 작업, Qoder 중국판은 캠페인 수령이며 캠페인이 없는 계정에는 중립 안내를 표시, Qoder 국제판은 기기 리스크 신원(로컬 Qoder 클라이언트 / qodercli의 UMID 컴포넌트 생성)이 필요하며 컴포넌트가 없으면 오류 대신 명확한 설명을 표시합니다. Trae는 SOLO의 일일 출석 크레딧(현지 0시 리셋)을 받고, 업스트림이 계정에 캠페인을 내려주지 않았거나 자격 증명에 기기 ID가 없으면 오류 대신 \"미수령 + 사유\"를 반환합니다. Loomy는 매일 최초 로그인 포인트를 한 번 호출하고, KukuAI는 \"무료 포인트\" 일일 작업을 받고, CodeArts는 당일 운영 혜택(수령 → 확인 → 재조회, 자동 실행은 하루 6회·10분 간격 쓰기 제한)을 받고, OfficeAce는 그날의 모든 보상(일일 출석 + 신규 혜택)을 한 번에 받습니다). \"랜덤 폭 N분\"을 설정하면 해당 회차의 계정은 각자의 윈도 내(당일 0:00-23:59로 클램프)에 분산 실행되어 같은 1분에 몰리지 않습니다. 윈도가 이미 지났다면 전부 즉시 실행합니다. 놓친 회차는 시작 후 보충되므로 전원이 꺼져 있었다고 해서 사라지지 않습니다(\"시작 시 보충\"을 끄면 윈도 시작까지 기다립니다). 각 제공자의 출석 API는 멱등이며 반복 실행해도 이중 수령되지 않습니다.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "정해진 시각이 되면 선택한 제공자의 사용 가능한 계정으로 자동 출석합니다 (WorkBuddy 중국판은 매일 출석 체크 인터페이스, 국제판은 일일 활성 작업으로 진행합니다: 이벤트 탐지, 일일 활성 보상 수령, 무료 모델로 키핑; 小浣熊은 데스크톱 앱 일일 포인트 경로를 사용하고; AutoClaw는 공식 클라이언트의 매일 출석 작업을 사용합니다; Qoder 중국판은 이벤트 수령으로 진행하며, 이벤트가 배정되지 않은 계정은 중립적인 안내를 받습니다; Qoder 국제판은 기기 리스크 관리 신원(로컬 Qoder 클라이언트 / qodercli의 UMID 컴포넌트로 생성)을 먼저 갖춰야 「매일 100 Credits」 이벤트가 보이며, 컴포넌트가 없으면 오류 대신 명확한 설명이 표시됩니다; Trae는 SOLO의 매일 출석 포인트를 수령하며(자연일 0시 기준 초기화), 업스트림이 해당 계정에 이벤트를 열지 않았거나 자격 증명에 기기 번호가 없으면 오류 대신 「미수령 + 구체적 사유」가 표시됩니다; Loomy는 매일 계정당 최초 로그인 포인트를 한 번 적립합니다; KukuAI는 「무료 포인트 받기」 일일 작업을 수령합니다; CodeArts는 당일 운영 혜택을 수령합니다(수령 → 확인 → 재조회 검증, 자동 실행은 하루 6회 / 간격 10분의 쓰기 요청 제한이 적용됩니다); OfficeAce 는 그날의 보상을 한 번의 동작으로 일괄 수령합니다(매일 출석 + 신규 혜택)). 시각을 놓치면 부팅 후 자동으로 보충 출석하며, 당시 컴퓨터가 꺼져 있었다고 해서 빠지지 않습니다. 각 사의 출석 인터페이스는 멱등이므로 반복 실행해도 중복 수령되지 않습니다.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "정해진 시각이 되면 선택한 제공자의 사용 가능한 계정으로 자동 출석합니다 (WorkBuddy 중국판은 매일 출석 체크 인터페이스, 국제판은 일일 활성 작업으로 진행합니다: 이벤트 탐지, 일일 활성 보상 수령, 무료 모델로 키핑; 小浣熊은 데스크톱 앱 일일 포인트 경로를 사용하고; AutoClaw는 공식 클라이언트의 매일 출석 작업을 사용합니다; Qoder 중국판은 이벤트 수령으로 진행하며, 이벤트가 배정되지 않은 계정은 중립적인 안내를 받습니다; Qoder 국제판은 기기 리스크 관리 신원(로컬 Qoder 클라이언트 / qodercli의 UMID 컴포넌트로 생성)을 먼저 갖춰야 「매일 100 Credits」 이벤트가 보이며, 컴포넌트가 없으면 오류 대신 명확한 설명이 표시됩니다; Trae는 SOLO의 매일 출석 포인트를 수령하며(자연일 0시 기준 초기화), 업스트림이 해당 계정에 이벤트를 열지 않았거나 자격 증명에 기기 번호가 없으면 오류 대신 「미수령 + 구체적 사유」가 표시됩니다; Loomy는 매일 계정당 최초 로그인 포인트를 한 번 적립합니다; KukuAI는 「무료 포인트 받기」 일일 작업을 수령합니다; OfficeAce 는 그날의 보상을 한 번의 동작으로 일괄 수령합니다(매일 출석 + 신규 혜택)). 시각을 놓치면 부팅 후 자동으로 보충 출석하며, 당시 컴퓨터가 꺼져 있었다고 해서 빠지지 않습니다. 각 사의 출석 인터페이스는 멱등이므로 반복 실행해도 중복 수령되지 않습니다.", "到点时逐个签到,已勾 {n} / {total} 家": "정해진 시각에 하나씩 출석합니다. 선택 {n} / {total}개", @@ -72,6 +75,9 @@ "可领奖": "수령 가능", "后端未返回定时签到数据": "백엔드가 예약 데이터를 반환하지 않았습니다", "后端未返回签到中心数据": "백엔드가 출석 체크 센터 데이터를 반환하지 않았습니다", + "启动补签": "시작 시 보충", + "启动补签已关闭": "시작 시 보충을 껐습니다", + "启动补签已开启": "시작 시 보충을 켰습니다", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "국제판 출석에는 기기 리스크 관리 신원을 생성할 UMID 컴포넌트가 필요합니다 (이 기기에서 감지되지 않음).", "在途": "여행 중", "填入缺省链": "기본 체인 채우기", @@ -102,6 +108,7 @@ "开学季执行完成:{message}": "개학 시즌 실행 완료: {message}", "开学季活动": "개학 시즌 이벤트", "开着:启用的条目按各自时刻执行": "켜짐: 활성화된 항목이 각자의 시간에 실행됩니다", + "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "켜짐: 시작 직후 오늘 아직 실행하지 않은 스케줄을 랜덤 윈도를 무시하고 즉시 보충", "待签": "출석 대기", "待领新手福利": "수령 대기 입문 혜택", "总开关": "메인 스위치", @@ -128,6 +135,7 @@ "新手福利": "입문 혜택", "新手福利有 {n} 项领取失败,可重试": "입문 혜택 {n}건의 수령에 실패했습니다. 재시도할 수 있습니다", "无": "없음", + "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "전용 체크인 API 없음 · 하루에 한 번 계정 대신 로그인 정보 엔드포인트를 호출(그것이 당일 마립)", "无独立签到接口 · 每天替账号打一次首次登录积分": "독립 출석 인터페이스 없음 · 매일 계정당 최초 로그인 포인트를 한 번 적립", "无账号": "계정 없음", "暂不可领": "지금은 수령 불가", @@ -151,6 +159,7 @@ "正在读取签到数据…": "출석 데이터를 읽는 중…", "每天 {time}": "매일 {time}", "每天 {time} · {scope}": "매일 {time} · {scope}", + "每天 {time} · 随机前后 {n} 分钟 · {scope}": "매일 {time} ± {n}분 · {scope}", "每天时刻": "매일 시각", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "출석 실행마다 · 계정별 한 행 · 결과와 수익은 백엔드 기록 기준", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "매일 활성 작업 · 웹 채널 세션으로 일일 활성 달성, 포인트는 수령 시 적립 · 두 가지는 따로 실행 가능", @@ -226,6 +235,7 @@ "重试": "다시 시도", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "기간 한정 체험 플랜 · 수령 시 슬라이더 인증 필요 · 항목별로 확인하고 수령", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "기간 한정 체험 플랜(start-plan), 이벤트 기간 내 매일 1회 · 수령 시 슬라이더 캡차 필요", + "随机前后": "랜덤 폭", "需真实操作": "실제 조작 필요", "非活动期": "이벤트 기간 아님", "项": "건", diff --git a/desktop-tauri/i18n/i18n-src/pt-BR/add-account.json b/desktop-tauri/i18n/i18n-src/pt-BR/add-account.json index 0c3064b4..a2728d35 100644 --- a/desktop-tauri/i18n/i18n-src/pt-BR/add-account.json +++ b/desktop-tauri/i18n/i18n-src/pt-BR/add-account.json @@ -20,6 +20,8 @@ "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT (três partes separadas por pontos; também pode colar a linha Bearer inteira ou o conteúdo do data.bin)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT (três partes separadas por ponto; colar a linha chatglm_token=… inteira também funciona)", + "ModelScope 国内版": "", + "ModelScope 国际版": "", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode edição internacional", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "Endpoint gerenciado do NVIDIA NIM; solicite a Key em integrate.api.nvidia.com", @@ -27,6 +29,7 @@ "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken é a credencial de login do Accio (um token opaco bem longo, não é JWT); refreshToken é opcional e, se preenchido, permite renovação automática ao expirar. Preencha a credencial da conta {label} — {siteNote} (a forma mais fácil de obter: use o \"Login web\" acima; não é preciso procurar o token manualmente.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken é o Cloud-IDE-JWT do Trae (três segmentos separados por ponto) e o refreshToken serve para renovação automática ao expirar (este provedor troca o refreshToken a cada uso: assim que é trocado, o antigo é invalidado, então não atualize a mesma conta em dois programas ao mesmo tempo).
Ao colar manualmente, preencha também machineId / deviceId: o upstream os vincula à chave pública do dispositivo enviada no login para identificar o dispositivo, e inventar um novo par dispara a família de rejeições de vínculo de dispositivo 2xxxx.
Sem esses três itens, o caminho correto é o \"Login web\" acima; em contêiner / implantação remota, basta colar o endereço de callback da barra de endereços conforme as instruções.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "O valor de monkeycode_ai_session (também pode colar o Cookie inteiro)", + "ms- 开头的 API 令牌": "Token de API começando com ms-", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken é opcional e, se preenchido, permite renovação automática ao expirar; ambos podem ser obtidos do arquivo de sessão de login do cliente Raccoon.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken é opcional e, se preenchido, permite renovação automática; ambos podem ser obtidos do arquivo de sessão de login do cliente. A mesma conta Cline funciona nos dois pools; aqui ela entra em {label}.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "O token aceita o prefixo enc: (descriptografado automaticamente no Windows). Sem preencher o refreshToken, não é possível renovar automaticamente.", @@ -102,6 +105,7 @@ "可选,留空使用账号昵称或邮箱": "Opcional; se vazio, usa o apelido ou o e-mail da conta", "可选,留空则用 key 尾号": "Opcional; se vazio, usa o final da key", "可选,留空则用 userId": "Opcional; se vazio, usa o userId", + "可选,留空则用上游账号昵称": "Opcional; se deixado em branco, o apelido da conta upstream é usado", "可选,留空则用上游返回的账号名或账号 id": "Opcional; se vazio, usa o nome ou o id da conta retornados pelo upstream", "可选,留空则用凭证里的账号名": "Opcional; se vazio, usa o nome da conta na credencial", "可选,留空则用文件里的昵称": "Opcional; deixe vazio para usar o apelido do arquivo", @@ -293,11 +297,13 @@ "等待登录完成…": "Aguardando a conclusão do login…", "等待网页登录…": "Aguardando o login web…", "粘贴 API Key": "Colar API Key", + "粘贴 API 令牌": "Colar token de API", "粘贴 Accio 的 accessToken": "Colar o accessToken do Accio", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Cole o Google refresh token do Antigravity (começa com 1//; também pode colar a linha inteira que contém refresh_token=).
Esta é uma entrada manual além do login web (por exemplo, exportada do IDE oficial em que você já está conectado). O refresh token não expira, e o gateway renova o access token automaticamente ao expirar; se o token for perdido, só resta refazer a autorização do Google, então guarde-o bem.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Cole a API Key do Command Code (começa com user_; obtenha no ~/.commandcode/auth.json do CLI oficial ou no studio web). Colar a linha inteira / com aspas / com o prefixo Bearer funciona; o gateway extrai a key pura sozinho. A key não expira e não há API de renovação, então basta obter uma nova se ela deixar de funcionar. Ao adicionar, o gateway faz uma verificação leve de atividade; uma falha não impede a adição.", "粘贴 Cookie": "Colar Cookie", "粘贴 Google refresh token": "Colar Google refresh token", + "粘贴 ModelScope 的 API 令牌(ms- 开头,在 {site} 的「访问令牌」页获取)。
{siteNote}
这枚令牌两用:网关既用它调推理,也用它读账号身份、魔粒余额与每日签到。令牌长期有效、没有续期接口,失效后重新获取再粘一次即可。": "", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "Cole o accessToken OAuth do OrcaTerm (um JWT com três partes separadas por pontos; obtido do data.bin do cliente desktop ou do cookie ot_session da versão web). Também pode colar a linha inteira contendo Bearer / ot_session= — o gateway extrai apenas o token. Após adicionar, o gateway renova automaticamente (o upstream tem API de renovação), sem precisar acompanhar a expiração de 2 horas manualmente.", "粘贴 Qoder 个人访问令牌(pt-…)": "Colar o token de acesso pessoal do Qoder (pt-…)", "粘贴 accessToken": "Colar accessToken", @@ -369,7 +375,9 @@ "这一家当前不支持网页登录,请改用填写凭证": "Este provedor não suporta login web no momento; use \"Preencher credenciais\"", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "Esta conta não tem campanhas com resgate automático no momento (apenas os pontos de brinde do login diário são resgatados automaticamente)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "Esta cota passa pelo canal \"Start Plan\": se o encaminhamento avisar que o Coding Plan expirou, ", + "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "Aqui é a conta do site da China (modelscope.cn): cole o token do site da China. O site internacional (modelscope.ai) é outro provider com outra conta; os tokens não são intercambiáveis entre os dois.", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "Aqui é a conta do site da China (monkeycode-ai.com): cole a sessão do site da China. O site internacional (monkeycode-ai.net) é outro provedor, com conta própria; as credenciais não são compartilhadas entre os dois.", + "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "Aqui é a conta do site internacional (modelscope.ai): cole o token do site internacional. O site da China (modelscope.cn) é outro provider com outra conta; os tokens não são intercambiáveis entre os dois.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "Aqui é a conta do site internacional (monkeycode-ai.net): cole a sessão do site internacional. O site da China (monkeycode-ai.com) é outro provedor, com conta própria; as credenciais não são compartilhadas entre os dois.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Selecione o arquivo de sessão de login auth.json do cliente CatPaw (Windows: C:\\Users\\\\.meituan-catpaw\\auth.json; macOS / Linux: ~/.meituan-catpaw/auth.json). Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente — sem depender mais do cliente desta máquina.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Selecione o arquivo de sessão de login providers.json do cliente Cline (Windows: C:\\Users\\\\.cline\\data\\settings\\providers.json; macOS / Linux: ~/.cline/data/settings/providers.json). Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente — sem depender mais do cliente desta máquina; este registro entra em {label}.", diff --git a/desktop-tauri/i18n/i18n-src/pt-BR/checkin.json b/desktop-tauri/i18n/i18n-src/pt-BR/checkin.json index f46a9c8a..26139e58 100644 --- a/desktop-tauri/i18n/i18n-src/pt-BR/checkin.json +++ b/desktop-tauri/i18n/i18n-src/pt-BR/checkin.json @@ -34,6 +34,7 @@ "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "Fora do check-in diário: {list}. As recompensas únicas do CodeArts ficam em \"Benefícios iniciais\" abaixo; o resgate diário/de planos dele e do ZCode fica em \"Benefícios de atividade\".", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "Fora do check-in diário: {list}. As recompensas únicas do CodeArts ficam em \"Benefícios iniciais\" abaixo, e o benefício diário dele fica logo acima em \"Check-in diário\"; o resgate de planos do ZCode fica em \"Benefícios de atividade\".", "与国内版同一套任务接口 · 站点不同": "Mesma interface de tarefas da edição da China · site diferente", + "与国内版同一套链路 · 站点不同、令牌不通用": "Mesmo fluxo da edição China · site diferente, tokens não intercambiáveis", "今天已领 {n} 份": "{n} resgatado(s) hoje", "今天未领": "Não resgatado hoje", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "Resgatado hoje (horário de Pequim, {day}) · {n} itens confirmados oficialmente · amanhã é possível resgatar novamente", @@ -55,10 +56,12 @@ "全部结果": "Todos os resultados", "全部账号均可签到": "Todas as contas podem fazer check-in", "全部领取": "Resgatar todos", + "关着:开机后等到窗口起点再签,随机窗口当天生效": "Desligado: após iniciar, esperar o início da janela para que a janela aleatória valha hoje", "关着:所有条目都不执行": "Desligado: nenhum agendamento é executado", + "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "minutos · contas executam em momentos aleatórios dentro da janela; 0 = executar imediatamente no horário", "删除失败:{error}": "Falha ao excluir: {error}", "删除定时条目": "Excluir agendamento", - "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "No horário marcado, faz o check-in automático das contas habilitadas dos provedores marcados (WorkBuddy CN usa a API de check-in diário; a versão internacional usa a tarefa de atividade diária: detecta o evento, recebe a recompensa de atividade diária, mantém-se ativo com o modelo gratuito e abre uma sessão pelo canal web para acender a atividade do dia; o Raccoon usa o fluxo de pontos diários do desktop; o AutoClaw usa a tarefa de check-in diário do cliente oficial; o Qoder CN reivindica via evento, e contas sem evento atribuído recebem um aviso neutro; o Qoder internacional precisa primeiro de uma identidade de risco do dispositivo (gerada pelo componente UMID do cliente Qoder local / qodercli) para sequer ver o evento \"100 Credits diários\" — sem o componente, chega uma explicação clara em vez de um erro; o Trae recebe os pontos de check-in diário do SOLO (reiniciam à meia-noite), e quando o upstream não tem evento para a conta ou as credenciais não têm ID de dispositivo, chega \"não recebido + motivo\" em vez de erro; o Loomy credita os pontos de primeiro login uma vez por dia para a conta; o KukuAI recebe a tarefa diária \"Pontos grátis\"; o CodeArts recebe as vantagens operacionais do dia (receber → confirmar → verificar relendo; execuções automáticas limitadas a 6 requisições de escrita por dia, com 10 minutos de intervalo); o OfficeAce recebe todas as recompensas do dia de uma vez (check-in diário + brinde de novato)). Se a máquina estava desligada no horário, um check-in de reposição roda ao ligar — nada fica para trás. A API de check-in de cada provedor é idempotente: repetir nunca recebe duas vezes.", + "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "Faz check-in nas contas disponíveis dos provedores marcados quando chega a hora (WorkBuddy CN usa a API de check-in diário; WorkBuddy Intl usa a tarefa de atividade diária: sondar atividades, resgatar a recompensa diária, manter um modelo gratuito ativo e abrir uma sessão web para acender a sequência; Raccoon usa a cadeia diária de pontos do desktop; AutoClaw usa a tarefa diária de sign-in do cliente oficial; Qoder CN resgata campanhas e mostra um aviso neutro para contas sem campanha; Qoder Intl precisa de uma identidade de risco do dispositivo (gerada pelo componente UMID do cliente Qoder / qodercli local) para ver a campanha de '100 Credits diários' e mostra uma explicação clara em vez de erro quando o componente falta; Trae resgata os créditos de check-in diário do SOLO (reset à meia-noite local) e informa 'não resgatado + motivo' em vez de erro quando o upstream não tem campanha para a conta ou a credencial não tem device id; Loomy chama o endpoint de pontos do primeiro login uma vez por dia; KukuAI resgata as tarefas diárias de 'pontos grátis'; CodeArts resgata o benefício diário de operações (resgatar → confirmar → reler, com execuções automáticas limitadas a 6 escritas por dia e 10 minutos de intervalo; OfficeAce resgata todas as recompensas do dia (check-in diário + presente de novato) em uma chamada). Com 'margem aleatória de N minutos', as contas de uma rodada executam espalhadas dentro da própria janela (limitada a 0:00-23:59 do mesmo dia) em vez de todas no mesmo minuto; se a janela já passou, todas executam imediatamente. Execuções perdidas são recuperadas após iniciar, então nada se perde quando a máquina estava desligada (desligue 'Recuperação na inicialização' para esperar o início da janela). A API de check-in de cada provedor é idempotente, então execuções repetidas nunca resgatam duas vezes.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "No horário definido, o check-in automático é feito nas contas disponíveis dos provedores marcados (o WorkBuddy edição da China usa a interface de check-in diário; a edição internacional usa as tarefas de atividade diária: detectar o evento, resgatar a recompensa de atividade diária e então manter a conta ativa com modelos gratuitos; o Raccoon usa o fluxo diário de pontos do aplicativo desktop; o AutoClaw usa a tarefa de check-in diário do cliente oficial; o Qoder China usa o resgate de evento, e contas sem evento distribuído recebem um aviso neutro; o Qoder internacional precisa primeiro da identidade de controle de risco do dispositivo (gerada pelo componente UMID do cliente Qoder / qodercli local) para enxergar o evento “100 Credits diários”, e sem o componente recebe uma explicação clara em vez de um erro; o Trae resgata os pontos de check-in diário do SOLO (redefinidos às 0h do dia natural), e quando o upstream não abriu o evento para a conta ou a credencial não tem o ID do dispositivo, o resultado é “não resgatado + motivo específico” em vez de um erro; o Loomy credita uma vez por dia os pontos de primeiro login da conta; o KukuAI resgata a tarefa diária do “Ganhe pontos grátis”); o CodeArts resgata o benefício de campanha do dia (resgatar → confirmar → reler para verificar; execuções automáticas têm limite de 6 gravações por dia com intervalo de 10 minutos); o OfficeAce resgata todas as recompensas do dia em uma única ação (check-in diário + presente de novos usuários)). Se o horário for perdido, o check-in é compensado automaticamente após o computador ser ligado, sem que nada se perca por o computador estar desligado no horário. As interfaces de check-in de cada provedor são idempotentes; execuções repetidas não resgatam duas vezes.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "No horário definido, o check-in automático é feito nas contas disponíveis dos provedores marcados (o WorkBuddy edição da China usa a interface de check-in diário; a edição internacional usa as tarefas de atividade diária: detectar o evento, resgatar a recompensa de atividade diária e então manter a conta ativa com modelos gratuitos; o Raccoon usa o fluxo diário de pontos do aplicativo desktop; o AutoClaw usa a tarefa de check-in diário do cliente oficial; o Qoder China usa o resgate de evento, e contas sem evento distribuído recebem um aviso neutro; o Qoder internacional precisa primeiro da identidade de controle de risco do dispositivo (gerada pelo componente UMID do cliente Qoder / qodercli local) para enxergar o evento “100 Credits diários”, e sem o componente recebe uma explicação clara em vez de um erro; o Trae resgata os pontos de check-in diário do SOLO (redefinidos às 0h do dia natural), e quando o upstream não abriu o evento para a conta ou a credencial não tem o ID do dispositivo, o resultado é “não resgatado + motivo específico” em vez de um erro; o Loomy credita uma vez por dia os pontos de primeiro login da conta; o KukuAI resgata a tarefa diária do “Ganhe pontos grátis”); o OfficeAce resgata todas as recompensas do dia em uma única ação (check-in diário + presente de novos usuários)). Se o horário for perdido, o check-in é compensado automaticamente após o computador ser ligado, sem que nada se perca por o computador estar desligado no horário. As interfaces de check-in de cada provedor são idempotentes; execuções repetidas não resgatam duas vezes.", "到点时逐个签到,已勾 {n} / {total} 家": "{n} de {total} marcados — o check-in é feito um por um no horário", @@ -72,6 +75,9 @@ "可领奖": "Pode resgatar", "后端未返回定时签到数据": "O backend não retornou dados de agendamento", "后端未返回签到中心数据": "O backend não retornou os dados da central de check-in", + "启动补签": "Recuperação na inicialização", + "启动补签已关闭": "Recuperação na inicialização desativada", + "启动补签已开启": "Recuperação na inicialização ativada", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "O check-in da edição internacional exige o componente UMID para gerar a identidade de controle de risco do dispositivo (não detectado nesta máquina).", "在途": "Em viagem", "填入缺省链": "Preencher cadeia padrão", @@ -102,6 +108,7 @@ "开学季执行完成:{message}": "Execução de volta às aulas concluída: {message}", "开学季活动": "Evento de volta às aulas", "开着:启用的条目按各自时刻执行": "Ligado: agendamentos habilitados rodam em seus próprios horários", + "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "Ligado: agendamentos ainda não executados hoje são recuperados logo após iniciar, ignorando a janela aleatória", "待签": "Pendente", "待领新手福利": "Benefícios iniciais pendentes", "总开关": "Interruptor principal", @@ -128,6 +135,7 @@ "新手福利": "Benefícios iniciais", "新手福利有 {n} 项领取失败,可重试": "{n} item(ns) dos benefícios iniciais falharam no resgate — é possível tentar novamente", "无": "Nenhum", + "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "Sem API de check-in dedicada · acessa o endpoint de informações de login uma vez por dia por conta (o que concede os Magicubes diários)", "无独立签到接口 · 每天替账号打一次首次登录积分": "Sem interface de check-in própria · credita uma vez por dia os pontos de primeiro login da conta", "无账号": "Sem contas", "暂不可领": "Indisponível", @@ -151,6 +159,7 @@ "正在读取签到数据…": "Lendo os dados de check-in…", "每天 {time}": "Todos os dias às {time}", "每天 {time} · {scope}": "Diário {time} · {scope}", + "每天 {time} · 随机前后 {n} 分钟 · {scope}": "Diariamente {time} ± {n} min · {scope}", "每天时刻": "Horário diário", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "Uma linha por conta a cada execução · resultados e ganhos conforme registrado pelo backend", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "Tarefas de atividade diária · uma conversa no canal web acende a atividade diária, só o resgate adiciona pontos · os dois podem ser executados separadamente", @@ -226,6 +235,7 @@ "重试": "Tentar de novo", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "Plano de teste por tempo limitado · o resgate exige CAPTCHA de arrastar · veja e resgate um a um", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "Plano de teste por tempo limitado (start-plan), um por dia durante o evento · o resgate exige captcha deslizante", + "随机前后": "Margem aleatória", "需真实操作": "Requer ação real", "非活动期": "Evento inativo", "项": "itens", diff --git a/desktop-tauri/i18n/i18n-src/zh-Hant/add-account.json b/desktop-tauri/i18n/i18n-src/zh-Hant/add-account.json index 5a2b843a..c09ab33c 100644 --- a/desktop-tauri/i18n/i18n-src/zh-Hant/add-account.json +++ b/desktop-tauri/i18n/i18n-src/zh-Hant/add-account.json @@ -20,6 +20,8 @@ "Command Code": "", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "", + "ModelScope 国内版": "", + "ModelScope 国际版": "", "MonkeyCode": "", "MonkeyCode 国际版": "", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "", @@ -27,6 +29,7 @@ "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "", + "ms- 开头的 API 令牌": "", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "", @@ -102,6 +105,7 @@ "可选,留空使用账号昵称或邮箱": "", "可选,留空则用 key 尾号": "", "可选,留空则用 userId": "", + "可选,留空则用上游账号昵称": "", "可选,留空则用上游返回的账号名或账号 id": "", "可选,留空则用凭证里的账号名": "", "可选,留空则用文件里的昵称": "", @@ -293,11 +297,13 @@ "等待登录完成…": "", "等待网页登录…": "", "粘贴 API Key": "", + "粘贴 API 令牌": "", "粘贴 Accio 的 accessToken": "", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "", "粘贴 Cookie": "", "粘贴 Google refresh token": "", + "粘贴 ModelScope 的 API 令牌(ms- 开头,在 {site} 的「访问令牌」页获取)。
{siteNote}
这枚令牌两用:网关既用它调推理,也用它读账号身份、魔粒余额与每日签到。令牌长期有效、没有续期接口,失效后重新获取再粘一次即可。": "", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "", "粘贴 Qoder 个人访问令牌(pt-…)": "", "粘贴 accessToken": "", @@ -369,7 +375,9 @@ "这一家当前不支持网页登录,请改用填写凭证": "", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "", + "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "", + "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "", diff --git a/desktop-tauri/i18n/i18n-src/zh-Hant/checkin.json b/desktop-tauri/i18n/i18n-src/zh-Hant/checkin.json index 70f49f57..f0a19829 100644 --- a/desktop-tauri/i18n/i18n-src/zh-Hant/checkin.json +++ b/desktop-tauri/i18n/i18n-src/zh-Hant/checkin.json @@ -34,6 +34,7 @@ "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "", "与国内版同一套任务接口 · 站点不同": "", + "与国内版同一套链路 · 站点不同、令牌不通用": "", "今天已领 {n} 份": "", "今天未领": "", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "", @@ -55,10 +56,12 @@ "全部结果": "", "全部账号均可签到": "", "全部领取": "", + "关着:开机后等到窗口起点再签,随机窗口当天生效": "", "关着:所有条目都不执行": "", + "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "", "删除失败:{error}": "", "删除定时条目": "", - "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "", + "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "", "到点时逐个签到,已勾 {n} / {total} 家": "", @@ -72,6 +75,9 @@ "可领奖": "可領獎", "后端未返回定时签到数据": "", "后端未返回签到中心数据": "", + "启动补签": "", + "启动补签已关闭": "", + "启动补签已开启": "", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "", "在途": "在途", "填入缺省链": "", @@ -101,6 +107,7 @@ "开学季执行完成:{message}": "開學季執行完成:{message}", "开学季活动": "開學季活動", "开着:启用的条目按各自时刻执行": "", + "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "", "待签": "", "待领新手福利": "", "总开关": "", @@ -127,6 +134,7 @@ "新手福利": "", "新手福利有 {n} 项领取失败,可重试": "", "无": "", + "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "", "无独立签到接口 · 每天替账号打一次首次登录积分": "", "无账号": "", "暂不可领": "", @@ -150,6 +158,7 @@ "正在读取签到数据…": "", "每天 {time}": "", "每天 {time} · {scope}": "", + "每天 {time} · 随机前后 {n} 分钟 · {scope}": "", "每天时刻": "", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "", @@ -221,6 +230,7 @@ "重试": "", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "", + "随机前后": "", "需真实操作": "需真實操作", "非活动期": "非活動期", "项": "", diff --git a/desktop-tauri/src-tauri/server/src/server/api/accounts.rs b/desktop-tauri/src-tauri/server/src/server/api/accounts.rs index 02e88742..74b75e64 100644 --- a/desktop-tauri/src-tauri/server/src/server/api/accounts.rs +++ b/desktop-tauri/src-tauri/server/src/server/api/accounts.rs @@ -1286,6 +1286,36 @@ pub async fn add_account(state: &ServerState, body: &Bytes) -> Response { }, ) } + // ModelScope(魔搭)的两个站点:粘贴 `ms-` 令牌 + **先探活换身份**。 + // + // 为什么本家要出网(不是「粘贴即落盘」):那枚令牌是不透明的, + // 解不出身份 —— 不出网就只能拿令牌尾号当账号 id,同一个账号换一次令牌 + // 就会变成两条记录。所以照 Qoder / OfficeAce 的既有分工:**网络在锁外** + // (这里 await 一次探活),把结果作为参数交给同步的落账号入口 + // (`add_modelscope_account` 只在锁内做读-改-写)。 + // + // 探活顺带触发当日签到(见 `modelscope::probe` 的模块头)—— + // 添加账号的人当天就把魔粒拿到手,这是上游的接口语义决定的, + // 不是这里额外做了一件事。 + // + // 地区由 kind 反查(provider 身份是权威,payload 里没有地区字段)。 + Some(kind @ (crate::server::core::providers::ProviderKind::Modelscope + | crate::server::core::providers::ProviderKind::ModelscopeIntl)) => { + let region = crate::server::core::providers::modelscope::Region::from_kind(kind) + .unwrap_or(crate::server::core::providers::modelscope::Region::Cn); + let token = crate::server::core::providers::modelscope::credentials::token_from_payload(&payload); + if token.is_empty() { + Err(AccountStoreError::new( + "缺少令牌(accessToken / apiKey / token / session)", + 400, + )) + } else { + match crate::server::core::providers::modelscope::probe::identify(region, &token).await { + Ok(identity) => store.add_modelscope_account(region, &payload, &identity, import_name), + Err(error) => Err(AccountStoreError::new(error.message, error.status_code)), + } + } + } // WorkBuddy 系的两家(国内版 / 国际版):同一套凭证形态与落账号路径, // 差别只有归属 —— provider id 自己就是归属(拆家后不再从 payload 里的 // `edition` 反推:那是账号的属性,而落哪一家是身份问题)。 diff --git a/desktop-tauri/src-tauri/server/src/server/api/auto_checkin.rs b/desktop-tauri/src-tauri/server/src/server/api/auto_checkin.rs index fe7c5f41..e9fe0259 100644 --- a/desktop-tauri/src-tauri/server/src/server/api/auto_checkin.rs +++ b/desktop-tauri/src-tauri/server/src/server/api/auto_checkin.rs @@ -1,7 +1,7 @@ //! 定时签到路由(对照 server.mjs 726-746 行)。 //! //! GET /api/auto-checkin 读取开关、触发时刻、上次结果 -//! POST /api/auto-checkin 修改设置 { enabled?, time? } +//! POST /api/auto-checkin 修改设置 { enabled?, time?, startupCatchUp? } //! POST /api/auto-checkin/run 立即执行一次 //! //! ── 错误信封(照抄 Node 的落点)──────────────────────────── @@ -43,7 +43,7 @@ pub async fn get_state(State(state): State) -> Response { ok_json(state.auto_checkin().state()) } -/// POST /api/auto-checkin —— 修改设置({ enabled?, time? }) +/// POST /api/auto-checkin —— 修改设置({ enabled?, time?, startupCatchUp? }) pub async fn configure(State(state): State, body: Bytes) -> Response { // 空 body 视为 {}(Node 的 `|| '{}'`);非法 JSON 在 Node 里由 JSON.parse // 抛出的 SyntaxError 走到 errorPayload → 500 proxy_error(实测如此), diff --git a/desktop-tauri/src-tauri/server/src/server/api/checkin_schedules.rs b/desktop-tauri/src-tauri/server/src/server/api/checkin_schedules.rs index 7fcbe66b..d361a272 100644 --- a/desktop-tauri/src-tauri/server/src/server/api/checkin_schedules.rs +++ b/desktop-tauri/src-tauri/server/src/server/api/checkin_schedules.rs @@ -2,7 +2,7 @@ //! //! ```text //! GET /api/checkin-schedules 状态(总开关 + 条目数组 + 提供商清单) -//! POST /api/checkin-schedules 保存一条(按 id upsert,{id?, label?, enabled?, time?, providers?}) +//! POST /api/checkin-schedules 保存一条(按 id upsert,{id?, label?, enabled?, time?, jitterMinutes?, providers?}) //! POST /api/checkin-schedules/{id}/delete 删除一条(DELETE 方法同受理) //! POST /api/checkin-schedules/{id}/run 立即执行这一条 //! ``` diff --git a/desktop-tauri/src-tauri/server/src/server/core/account_store/mod.rs b/desktop-tauri/src-tauri/server/src/server/core/account_store/mod.rs index 1a5ae223..9a30d15c 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/account_store/mod.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/account_store/mod.rs @@ -110,6 +110,7 @@ pub mod commandcode_accounts; pub mod custom_accounts; pub mod kuku_accounts; pub mod loomy_accounts; +pub mod modelscope_accounts; pub mod monkeycode_accounts; pub mod officeace_accounts; pub mod orcaterm_accounts; @@ -211,6 +212,20 @@ pub(crate) fn is_monkeycode_family(provider_id: &str) -> bool { provider_id == MONKEYCODE_PROVIDER_ID || provider_id == MONKEYCODE_INTL_PROVIDER_ID } +/// 这个 provider 是不是 **ModelScope 系**(两个站点之一)。 +/// +/// 与 [`is_autoclaw_family`] / [`is_monkeycode_family`] 同一形态、同一理由: +/// 账号层有几处判断只关心「是不是 ModelScope」(公开形态、令牌长度校验), +/// 不关心哪个站点 —— 那些分支走本函数,于是加站点或改名时只改这里一处, +/// 而不是散在各文件里的 `id == "modelscope"`(那种写法对国际版恒为假, +/// 是个不会报错的静默失配)。 +/// +/// 判据从 `Region` 互查推导(同 [`is_accio_family`] / [`is_zcode_family`]), +/// **不要**用 `starts_with("modelscope-")` —— 国际版的 id 也以它开头。 +pub(crate) fn is_modelscope_family(provider_id: &str) -> bool { + crate::server::core::providers::modelscope::Region::from_provider_id(provider_id).is_some() +} + /// Command Code provider id(账号存储内部多处要用;**从注册表推导**)。 /// 账号形态见 `commandcode_accounts.rs`(单一 provider、没有地区之分)。 pub(crate) const COMMANDCODE_PROVIDER_ID: &str = crate::server::core::providers::kind_id( diff --git a/desktop-tauri/src-tauri/server/src/server/core/account_store/modelscope_accounts.rs b/desktop-tauri/src-tauri/server/src/server/core/account_store/modelscope_accounts.rs new file mode 100644 index 00000000..70558daf --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/account_store/modelscope_accounts.rs @@ -0,0 +1,259 @@ +//! ModelScope(魔搭)账号:粘贴 `ms-` 令牌落账号、公开形态。 +//! +//! ── 账号字段 ──────────────────────────────────────────────── +//! ```text +//! 本项目记录:{ id, provider:"modelscope"|"modelscope-intl", name, userId(=HavanaId), +//! accessToken(=ms-令牌), tokenTail, source, priority, enabled, +//! addedAt, updatedAt } +//! 上游身份响应:{ HavanaId, Name, NickName, Email }(见 providers/providerscope/probe.rs) +//! ``` +//! `accessToken` 落盘存的就是那枚 `ms-` 令牌 —— 键名与别家统一 +//! (`has_token()` / `access_token()` 一族认这个键)。 +//! +//! ── 为什么添加要走一次探活(本文件只落盘、不出网)──────────────── +//! 令牌不透明(不是 JWT,解不出身份),所以身份由 `probe::identify` 出网换来、 +//! **作为参数**传进来(qoder 的 `add_qoder_account` 同一分工:网络在锁外、 +//! 本文件只在锁内做读-改-写)。这样持锁期间绝不发请求这条纪律不被破坏。 +//! +//! 记录 id = `{地区前缀}{HavanaId}`:**同一账号在两地的 id 天然不相交**, +//! 于是「两地各加一个账号」可以并存(理由见 `modelscope::region` 的 +//! `account_id_prefix`)。 +//! +//! ── 与别家添加路径的关系 ──────────────────────────────────── +//! **只有一条来源**:粘贴令牌(`api::accounts::add_account` 的 modelscope 分支)。 +//! 没有网页登录、没有桌面端导入 —— 魔搭没有桌面客户端(见 `providers/modelscope` +//! 的模块头)。 +//! +//! 本文件全是「读-改-写」文件操作,**没有任何网络请求**(持锁不做网络)。 +//! 绝不 unwrap/expect(release 是 panic=abort)。 + +use serde_json::{Map, Value}; + +use crate::server::core::account_store::priority::next_free_priority; +use crate::server::core::account_store::sql; +use crate::server::core::account_store::state::{mark_name_custom, StoredAccount}; +use crate::server::core::account_store::{AccountStore, AccountStoreError}; +use crate::server::core::providers::modelscope::probe::Identity; +use crate::server::core::providers::modelscope::Region; +use crate::server::logging; + +/// 备注名长度上限(与别家同一口径) +const MAX_NAME_LENGTH: usize = 100; + +/// 身份字段(`HavanaId`)长度上限 +const MAX_IDENTITY_LENGTH: usize = 256; + +/// 令牌长度上限(超过这个长度的输入一定是粘错了东西) +const MAX_TOKEN_LENGTH: usize = 8192; + +/// 截断到 `max` 个**字符**(不是字节;备注名可能有中文) +fn truncate_chars(value: &str, max: usize) -> String { + if value.chars().count() <= max { + return value.to_string(); + } + value.chars().take(max).collect() +} + +/// 从 payload 里取第一个非空字符串(候选键覆盖本项目落盘名与粘贴形态) +fn pick(payload: &Value, keys: &[&str]) -> String { + for key in keys { + let value = payload + .get(*key) + .and_then(Value::as_str) + .map(str::trim) + .unwrap_or(""); + if !value.is_empty() { + return value.to_string(); + } + } + String::new() +} + +impl AccountStore { + /// 取一条 ModelScope 账号记录(公开形态的原始 JSON)。 + /// + /// `region` 决定查哪一家(`modelscope` / `modelscope-intl` 是两家 provider, + /// 各自的账号集合独立)。 + /// + /// `account_id` 非空 → 按 id 直查(不属于本家返回 None); + /// 为空 → 本家**启用中**账号里优先级最靠前的一条(与 + /// `autoclaw_account_record` 的语义一致:转发默认用队首账号)。 + pub fn modelscope_account_record(&self, region: Region, account_id: &str) -> Option { + let provider_id = region.provider_id(); + let guard = self.guard(); + if !account_id.is_empty() { + let record = self.record_by_id(&guard, account_id)?; + return (record.provider() == provider_id).then(|| record.to_value()); + } + let mut candidates: Vec = self + .records_for_provider(&guard, provider_id) + .into_iter() + .filter(StoredAccount::enabled) + .collect(); + candidates.sort_by_key(StoredAccount::order_key); + candidates.into_iter().next().map(|item| item.to_value()) + } + + /// 添加/更新一个 ModelScope 账号(唯一落账号入口)。 + /// + /// payload:`accessToken` / `apiKey` / `token` / `session` 任一给出令牌(必填); + /// `userId` 可选(给了会被 `identity` 覆盖 —— 身份以上游探活结果为准, + /// 那是本家唯一的可信来源)。 + /// + /// `identity` 由调用方在**锁外**探活得到(见模块头)。令牌缺失 / 超长、 + /// 或身份缺失时报 400(拿不到身份的添加必须失败,理由见 `probe.rs`)。 + /// + /// 撞 id(本机已有同 id 记录)时:同 provider 就地更新(保留优先级与启用状态、 + /// 沿用用户改过的备注名),撞到**别的 provider** 时报错 —— 绝不覆写他人记录 + /// (与另外几家同一策略)。 + pub fn add_modelscope_account( + &self, + region: Region, + payload: &Value, + identity: &Identity, + name: Option<&str>, + ) -> Result { + let provider_id = region.provider_id(); + let token = pick(payload, &["accessToken", "apiKey", "token", "session"]); + if token.is_empty() { + return Err(AccountStoreError::new( + "缺少令牌(accessToken / apiKey / token / session)", + 400, + )); + } + if token.chars().count() > MAX_TOKEN_LENGTH { + return Err(AccountStoreError::new("令牌过长", 400)); + } + if !identity.has_user_id() { + return Err(AccountStoreError::new( + "未能从上游读到账号身份(HavanaId),无法生成稳定的账号标识", + 400, + )); + } + let user_id = truncate_chars(identity.user_id.trim(), MAX_IDENTITY_LENGTH); + let id = format!("{}{user_id}", region.account_id_prefix()); + + let guard = self.guard(); + let existing = self.record_by_id(&guard, &id); + if let Some(existing) = existing.as_ref() { + let existing_provider = existing.provider(); + if existing_provider != provider_id { + return Err(AccountStoreError::new( + format!( + "账号 id「{id}」已被{existing_provider}账号占用,无法添加同一身份的\ + ModelScope {}账号(请先处理那个账号)", + region.label() + ), + 400, + )); + } + } + // 备注名兜底:显式传入 → 既有记录里的备注名 → 上游昵称 → HavanaId + let explicit_name = name + .map(str::trim) + .filter(|value| !value.is_empty()) + .map(|value| truncate_chars(value, MAX_NAME_LENGTH)); + let record_name = explicit_name + .or_else(|| { + existing + .as_ref() + .map(StoredAccount::name) + .filter(|value| !value.is_empty()) + }) + .unwrap_or_else(|| { + let display = truncate_chars(identity.display_name.trim(), MAX_NAME_LENGTH); + if !display.is_empty() { + display + } else { + format!("ModelScope {}", user_id) + } + }); + let priority = match existing.as_ref() { + Some(record) => record.priority(), + None => { + // 优先级全局唯一(各家共用一条队列),取全库已用号段 + let used = self.with_conn(&guard, |conn| sql::priorities_all(conn))?; + next_free_priority(&used) + } + }; + let now = logging::now_ms(); + + let mut record = Map::new(); + record.insert("id".to_string(), Value::String(id.clone())); + record.insert( + "provider".to_string(), + Value::String(provider_id.to_string()), + ); + record.insert("name".to_string(), Value::String(record_name.clone())); + // 备注名标记:用户显式传了名或既有记录已打标时置位(见 `state::mark_name_custom` + // 的说明)—— 本家走自己的保存路径(不经过 `store_crud::upsert_account` + // 的统一打标),漏了会让添加时填的备注名在将来被上游昵称顶掉。 + mark_name_custom( + &mut record, + name.is_some_and(|value| !value.trim().is_empty()), + existing.as_ref(), + ); + record.insert("userId".to_string(), Value::String(user_id)); + record.insert("accessToken".to_string(), Value::String(token.clone())); + record.insert( + "tokenTail".to_string(), + Value::String( + crate::server::core::providers::modelscope::credentials::token_tail(&token), + ), + ); + record.insert("source".to_string(), Value::String("manual".to_string())); + record.insert("priority".to_string(), Value::from(priority)); + record.insert( + "enabled".to_string(), + Value::Bool( + existing + .as_ref() + .map(StoredAccount::enabled) + .unwrap_or(true), + ), + ); + record.insert( + "addedAt".to_string(), + Value::from( + existing + .as_ref() + .map(StoredAccount::added_at) + .filter(|value| *value != 0) + .unwrap_or(now), + ), + ); + record.insert("updatedAt".to_string(), Value::from(now)); + // 未知字段全量保留(用户手工加过的字段不能因为一次「更新账号」丢掉) + let mut merged = record; + if let Some(existing) = existing.as_ref() { + for (key, value) in existing.fields() { + merged.entry(key.clone()).or_insert_with(|| value.clone()); + } + } + let saved = StoredAccount::from_map(merged); + // 单行落地:`put` = DELETE + INSERT(与别家一致) + self.with_conn(&guard, |conn| sql::put(conn, &saved))?; + logging::log( + "[Accounts]", + &format!( + "✅ ModelScope {}账号已保存: {record_name}(优先级 {priority})", + region.label() + ), + ); + Ok(self.public_account(&saved)) + } + + /// ModelScope 账号的**公开形态**(进 HTTP 响应):去掉令牌本体,只留尾 4 位。 + /// + /// 没有 `edition` 字段:地区由 provider id 直接表达(两家 provider、两个分组), + /// 不需要再往记录上挂一个冗余标签 —— 那正是拆家前那套做法的残留。 + pub fn to_modelscope_public_account(&self, record: &StoredAccount) -> Value { + let mut value = record.to_value(); + if let Some(object) = value.as_object_mut() { + object.remove("accessToken"); + object.insert("available".to_string(), Value::Bool(record.enabled())); + object.insert("hasToken".to_string(), Value::Bool(true)); + } + value + } +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/account_store/store_view.rs b/desktop-tauri/src-tauri/server/src/server/core/account_store/store_view.rs index 3c349ab4..40369d90 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/account_store/store_view.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/account_store/store_view.rs @@ -361,6 +361,12 @@ impl AccountStore { // tokenTail / tokenExpireAt(续期是否在工作可被肉眼校验,见 // `orcaterm_accounts.rs`) self.to_orcaterm_public_account(record) + } else if super::is_modelscope_family(&record.provider()) { + // ModelScope(魔搭)的两个站点(`modelscope` / `modelscope-intl`)共用 + // 这一份公开形态:账号字段两地完全一致,差别只在域名(那是转发与凭证 + // 层的事,公开形态不体现)。去掉令牌本体,只留尾 4 位与「有没有令牌」 + // (见 `modelscope_accounts.rs`)。 + self.to_modelscope_public_account(record) } else if record .provider() .starts_with(crate::server::core::custom_providers::ID_PREFIX) diff --git a/desktop-tauri/src-tauri/server/src/server/core/auto_checkin.rs b/desktop-tauri/src-tauri/server/src/server/core/auto_checkin.rs index 5e71100e..56ca1033 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/auto_checkin.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/auto_checkin.rs @@ -23,6 +23,20 @@ //! 「今日已签到」也按错误的日期显示。移植自 Node 版(作者在国内,`Local` //! 恰好等于 UTC+8)时没有显式钉住这个前提,这里补上。 //! +//! ── 随机窗口(`jitterMinutes`,0 = 关闭)──────────────────── +//! 每条条目可设「随机前后 N 分钟」,窗口 = `[时刻-N, 时刻+N]` 夹到当天。 +//! 窗口起点由 tick 触发**一次**,然后本轮账号在窗口内各自取一个确定性 +//! 偏移(`spread_offset_seconds`),按时间顺序执行 —— 对上游呈现的是散在 +//! 窗口里的逐个请求,而不是每天同一分钟的一串。 +//! 两个关键实现约束: +//! ① 铺开在**后台任务**里(`spawn_spread`),不在 tick 里 await:窗口最长 +//! 4 小时,占住 tick 会延后其他条目,占住全局 `running` 会拒掉所有手动 +//! 签到;后台任务只在每个账号执行的几秒里抢锁。 +//! ② 偏移是**确定性哈希**(条目 id + 日期 + 时刻 + N + 账号 id),不是每次 +//! 随机:同一天的重试(Qoder 国际版窗口、停机重启)必须落在同一点, +//! 面板的「下次执行」也才与真实行为一致。 +//! 手动签到(批量 / 单账号 / 条目「立即执行」)不铺开,行为与改造前一致。 +//! //! ── 补签(有意的行为,别「顺手优化」)──────────────────────── //! Node 版 `start()` 的条件是**「今天还没签过」**,并不判「时间点是否已过」: //! 开着自动签到却在 00:01 时没开机、白天才启动 → 立刻补一次。 @@ -31,6 +45,8 @@ //! 把 enabled 设为 true、time 设为 23:00(未来时点)时,Node 版立即执行了 //! 一次 reason='启动补签' 的签到 —— 所以这里的条件同样只看日期键。 //! 多条目之后按条目各补各的:今天没跑过的**启用**条目每条补一次。 +//! 该行为可通过 `autoCheckin.startupCatchUp`(缺省开)整体关掉,见 +//! [`startup_catch_up`]:关掉后启动只起调度循环,等各自窗口起点由 tick 触发。 //! //! ── 配置读写 ──────────────────────────────────────────────── //! 状态存在 config.json 的 `autoCheckin` 字段:`enabled` 是总开关, @@ -62,6 +78,21 @@ pub const TICK_MS: u64 = 30_000; /// 默认触发时刻:零点一分(Node 版 DEFAULT_TIME) pub const DEFAULT_TIME: &str = "00:01"; +/// 「随机前后 N 分钟」的上限。 +/// +/// 为什么是 120 而不是更大:窗口跨度直接决定一轮签到最长铺多久,而这一轮 +/// 期间每个账号执行时都要抢全局「执行中」标记(见 `acquire_running`), +/// 窗口越大,手动签到被拒的概率越高。2 小时足够打散「每天同一分钟」的形态, +/// 又不至于让「立即执行」在最坏情况下等太久。 +pub const MAX_JITTER_MINUTES: u32 = 120; + +/// 随机窗口铺开时,为单个账号等「执行中」标记的上限。 +/// +/// 正常的争用只来自手动签到(几秒到几分钟),等 10 分钟足够;超过就说明 +/// 另一轮卡死在上游了 —— 继续等只会让铺开任务永久挂住、连带条目今天不再 +/// 重试。到点如实跳过剩余账号(见 `acquire_running`)。 +const RUNNING_WAIT_MS: i64 = 10 * 60 * 1000; + /// 缺省触发时刻(`DEFAULT_TIME` 的 owned 形态,读侧兜底用) pub fn default_time() -> String { DEFAULT_TIME.to_string() @@ -121,11 +152,16 @@ pub fn default_time() -> String { /// 受闸(`checkin_for` 传 manual=false),用户在面板上点不受闸; /// ② 「暂无可领取活动 / 等待重试」是**中性未领取**(不落当日台账,定时链 /// 稍后重试),不是失败 —— `claim_pending` 认这两个文案。 +/// - **ModelScope 国内版 / 国际版**:**没有独立签到接口** —— 调一次登录信息 +/// 接口(`GET /api/v1/users/login/info`)**本身就触发当日魔粒签到**(幂等), +/// 见 `providers::modelscope::checkin`。两个站点各打各的网页站,令牌不通用 +/// (打错得 401)。链路依据是 CPA 的 `modelscope-ratelimit` 插件源码, +/// 2026-10 实测复核。 /// /// 这是「有签到或每日活跃任务」的清单,不是「有积分概念」的清单:CatPaw 有积分 /// 查询但没有签到,因此不在此列 —— 它的账号在批量签到里被算作 `skipped`。 /// 加一家之前先确认它的签到链路真的存在(一个点了必然报错的复选框比没有更糟)。 -pub const CHECKIN_PROVIDERS: [&str; 13] = [ +pub const CHECKIN_PROVIDERS: [&str; 15] = [ "workbuddy", "workbuddy-intl", "raccoon", @@ -143,6 +179,13 @@ pub const CHECKIN_PROVIDERS: [&str; 13] = [ // 智谱清言:「每日登录积分」即本家的签到(`chatglm::checkin`)。 // 访客账号会被实现判成中性未领取(没有积分体系),不算失败。 "chatglm", + // ModelScope(魔搭)两个站点:签到就是调一次登录信息接口 + // (`GET {网页站}/api/v1/users/login/info`,调用即触发当日魔粒,幂等), + // 链路 2026-10-16 实测存在,见 `providers::modelscope::checkin` 的模块头。 + // 两个站点各打各的网页站,令牌不通用(打错得 401)。 + // 排在 chatglm 之后:上游 v3.0.8 先引入了 chatglm,保持它原来的位置不动。 + "modelscope", + "modelscope-intl", ]; /// 缺省的签到提供商集合(全选) @@ -160,13 +203,25 @@ pub fn default_providers() -> Vec { /// 会让这一家的勾选框再也取消不掉(读完就补回来,界面上表现为「取消勾选没反应」)。 /// 所以补齐只做一次,靠配置里的版本号记账;版本一旦写上去,用户之后再取消勾选 /// 就真的生效了。执行点见 `checkin_schedules::extend_providers_once`。 -pub const PROVIDERS_VERSION: i64 = 3; +pub const PROVIDERS_VERSION: i64 = 4; /// 「哪一版加入的家」——条目清单的版本低于它 = 这家还没被提供过 ⇒ 补进去。 /// 版本 1 = 多条目改造上线时的形态(9 家;`qoder-intl` 由 `normalize_providers` /// 的存量兼容规则跟着 `qoder` 带上,不在这里重复登记)。 -const PROVIDERS_ADDED_IN: [(&str, i64); 3] = - [("officeace", 2), ("codearts", 2), ("chatglm", 3)]; +/// +/// ⚠️ **版本号是「这一版加了哪几家」的记账,不是代码版本的序号** —— 合并上游 +/// 时最容易撞的就是它:上游 v3.0.8 用 3 装了 chatglm,本分支随后用 4 装 +/// ModelScope 的两站。两家都必须保留各自的版本号,谁都不许覆盖谁, +/// 否则先升级到那一边的用户永远补不进另一边的家(版本号已经写进配置了)。 +/// +/// 版本 3 = chatglm(上游 v3.0.8);版本 4 = ModelScope 国内版 / 国际版。 +const PROVIDERS_ADDED_IN: [(&str, i64); 5] = [ + ("officeace", 2), + ("codearts", 2), + ("chatglm", 3), + ("modelscope", 4), + ("modelscope-intl", 4), +]; /// 版本 `version` 之后才加入清单的家(按注册顺序)。空数组 = 这一版没有新家, /// 或配置比代码还新(装过更新的版本又退回来)——两种情况都只记账、不动清单。 @@ -335,11 +390,96 @@ pub fn today_key() -> String { beijing::today_key() } +/// 随机窗口的起止分钟(当天 00:00 起的分钟数)与跨度秒数。 +/// +/// `center` = `time` 换算成分钟;`start = max(0, center - N)`、 +/// `end = min(1439, center + N)` —— **夹到当天**。跨午夜时收敛到边界, +/// 分布因此会偏向一侧:这是有意的取舍(见模块头「随机窗口」), +/// 因为「某天没签、次日签两次」的观感比分布不均匀更糟。 +/// +/// time 非法 → None(与 `normalize_time` 同口径,调度起不来的情形不编时间)。 +pub fn window_bounds(time_text: &str, jitter_minutes: u32) -> Option<(u32, u32)> { + let normalized = normalize_time(Some(&Value::String(time_text.to_string()))).ok()?; + let (hour, minute) = normalized.split_once(':')?; + let center = hour.parse::().ok()? * 60 + minute.parse::().ok()?; + let start = center.saturating_sub(jitter_minutes); + let end = (center + jitter_minutes).min(23 * 60 + 59); + Some((start, end)) +} + +/// 窗口起点的绝对时刻(北京时间,当天)。时间非法 → None。 +fn window_start_at( + time_text: &str, + jitter_minutes: u32, + now: DateTime, +) -> Option> { + let (start, _) = window_bounds(time_text, jitter_minutes)?; + minute_of_day_at(start, now) +} + +/// 当天的第 `minute` 分钟(北京时间):窗口起点的落点。 +/// +/// 固定偏移没有夏令时问题(构造恒为 `Single`),因此不需要 Node 那种 +/// 「DST 当天该时刻不存在」的兜底 —— `single()` 取不到就当 None, +/// 也就是这台机器上的时钟环境异常到连北京时间的固定偏移都构造不出来。 +fn minute_of_day_at(minute: u32, now: DateTime) -> Option> { + let naive = now.date_naive().and_hms_opt(minute / 60, minute % 60, 0)?; + beijing::offset().from_local_datetime(&naive).single() +} + +/// 某个账号在窗口内的偏移秒数(`[0, span]`,含端点)。 +/// +/// ── 为什么是确定性哈希而不是 `getrandom` ──────────────────── +/// 同一天同一账号多次进入计算(tick 判定、重试、面板刷新)必须拿到**同一个** +/// 偏移:否则「Qoder 国际版窗口未开」的重试会每次换时间,面板也无法预演。 +/// 用 `sha256(条目 id | 日期 | 时刻 | 随机分钟 | 账号 id)` 派生,日期参与 +/// 哈希 ⇒ 每天不同;改时刻/随机值 ⇒ 当天未触发时偏移跟着变(符合直觉)。 +/// `span == 0`(N=0 或窗口被夹成一点)→ 恒 0,行为与不随机完全一致。 +/// +/// 取模偏差在 4 小时量级(≤14400)的跨度上可以忽略,不需要拒绝采样。 +pub fn spread_offset_seconds( + schedule_id: &str, + date: &str, + time_text: &str, + jitter_minutes: u32, + account_id: &str, +) -> u32 { + let Some((start, end)) = window_bounds(time_text, jitter_minutes) else { + return 0; + }; + let span = (end - start) * 60; + if span == 0 { + return 0; + } + use sha2::{Digest, Sha256}; + let mut hasher = Sha256::new(); + hasher.update(schedule_id.as_bytes()); + hasher.update(b"|"); + hasher.update(date.as_bytes()); + hasher.update(b"|"); + hasher.update(time_text.as_bytes()); + hasher.update(b"|"); + hasher.update(jitter_minutes.to_string().as_bytes()); + hasher.update(b"|"); + hasher.update(account_id.as_bytes()); + let digest = hasher.finalize(); + let mut bytes = [0u8; 8]; + bytes.copy_from_slice(&digest[..8]); + (u64::from_le_bytes(bytes) % (span as u64 + 1)) as u32 +} + /// 今天的触发时刻(北京时间);已过则返回 Some,未到返回 None。 /// 对应 Node 版 dueNow:非法的 time 文本在这里同样表现为 None(Node 是抛异常, /// 但调用方一律 catch 后 return,结果一致)。 -fn due_now(time_text: &str, now: DateTime) -> Option> { - let target = today_at(time_text, now)?; +/// +/// 有随机窗口时判的是**窗口起点**(到点即开始铺开,见 `spawn_spread`), +/// 而不是窗口中心——中心时刻本身不执行任何东西。 +fn due_now( + time_text: &str, + jitter_minutes: u32, + now: DateTime, +) -> Option> { + let target = window_start_at(time_text, jitter_minutes, now)?; if now >= target { Some(target) } else { @@ -354,32 +494,19 @@ fn due_now(time_text: &str, now: DateTime) -> Option) -> Option { - let mut target = today_at(time_text, now)?; +fn next_run_at_ms( + time_text: &str, + jitter_minutes: u32, + fired_today: bool, + now: DateTime, +) -> Option { + let mut target = window_start_at(time_text, jitter_minutes, now)?; if fired_today || target <= now { target += chrono::Duration::days(1); } Some(target.timestamp_millis()) } -/// 今天的 HH:MM 时刻(北京时间);time 文本非法时 None。 -/// -/// Node 用 `target.setHours(hour, minute, 0, 0)`(就地改到当天); -/// chrono 没有 set_* 的就地 API,用 `with_ymd_and_hms` 重建。 -/// 固定偏移没有夏令时问题(构造恒为 `Single`),因此不需要 Node 那种 -/// 「DST 当天该时刻不存在」的兜底 —— `single()` 取不到就当 None, -/// 也就是这台机器上的时钟环境异常到连北京时间的固定偏移都构造不出来。 -fn today_at(time_text: &str, now: DateTime) -> Option> { - let normalized = normalize_time(Some(&Value::String(time_text.to_string()))).ok()?; - let (hour, minute) = normalized.split_once(':')?; - let hour: u32 = hour.parse().ok()?; - let minute: u32 = minute.parse().ok()?; - let naive = now.date_naive().and_hms_opt(hour, minute, 0)?; - beijing::offset() - .from_local_datetime(&naive) - .single() -} - // ─── 状态读写 ─────────────────────────────────────────────── /// `autoCheckin` 字段的原始对象(非对象/缺失都给空对象)。 @@ -398,6 +525,19 @@ pub fn master_enabled() -> bool { raw_object().get("enabled").and_then(Value::as_bool) == Some(true) } +/// 「启动时立即补签」(`autoCheckin.startupCatchUp`,缺省 **开**)。 +/// +/// 开着 = 改造前的行为:启动时今天没签过的条目立刻补一次,不看时点是否已过 +/// (理由见模块头「补签」)。关掉 = 启动不补,交给 tick 按窗口起点判定 —— +/// 用户开了随机窗口又不希望「早上开机就提前签掉」时用这个开关。 +/// 缺省为开是刻意的:升级后行为零变化。 +pub fn startup_catch_up() -> bool { + raw_object() + .get("startupCatchUp") + .and_then(Value::as_bool) + .unwrap_or(true) +} + /// 合并写回 `autoCheckin`(对应 Node 版 writeState 的 `{...current, ...patch}`)。 /// 走 config.rs 的 `update_raw_field`,config.json 里的其它字段原样保留。 /// `pub(crate)`:多条目配置在同一键下写回,合并逻辑只有这一份。 @@ -421,6 +561,12 @@ struct Inner { task: Option>, /// 停机标志:stop() 置位后循环退出(幂等;再次 start 会重置) stopped: Arc, + /// 正在进行的「随机窗口铺开」任务,键是 `条目 id | 日期`。 + /// + /// 与 `running` 是两件事:铺开任务的大部分时间在 sleep(不该占执行锁), + /// 但同一个条目同一天不能起两轮(每个 tick 都会看到它到点且未落账 —— + /// 落账在 spawned 任务结束前,必须靠这个集合挡住重复 spawn)。 + spreads: std::collections::HashSet, } /// 定时签到服务句柄:内部一把锁 + Clone,与 update / models 同构。 @@ -451,6 +597,22 @@ impl Drop for RunningGuard { } } +/// 铺开任务的存续标记:Drop 时把 key 从 `spreads` 移除。 +/// +/// 覆盖三种出口:正常结束、提前 return、后台任务被 abort。守卫必须**移进** +/// 被 spawn 的 future 里 —— 放在 `spawn_spread` 的外层,函数一返回就 drop, +/// 等于什么都没保护。漏了这一步的后果是这条条目当天再也不会被 tick 重试。 +struct SpreadGuard { + service: AutoCheckin, + key: String, +} + +impl Drop for SpreadGuard { + fn drop(&mut self) { + self.service.finish_spread(&self.key); + } +} + impl AutoCheckin { pub fn new(store: AccountStore, billing: BillingService) -> Self { Self { @@ -460,6 +622,7 @@ impl AutoCheckin { running: false, task: None, stopped: Arc::new(AtomicBool::new(false)), + spreads: std::collections::HashSet::new(), })), } } @@ -499,7 +662,12 @@ impl AutoCheckin { .map(|schedule| { let fired_today = schedule.last_fired_date.as_deref() == Some(today.as_str()); let next_run_at = if master && schedule.enabled { - next_run_at_ms(&schedule.time, fired_today, now) + next_run_at_ms( + &schedule.time, + schedule.jitter_minutes, + fired_today, + now, + ) } else { None }; @@ -510,6 +678,7 @@ impl AutoCheckin { "displayLabel": checkin_schedules::display_label(schedule), "enabled": schedule.enabled, "time": schedule.time, + "jitterMinutes": schedule.jitter_minutes, "providers": schedule.providers, "lastFiredDate": schedule.last_fired_date, "lastFiredToday": fired_today, @@ -533,6 +702,7 @@ impl AutoCheckin { label: String::new(), enabled: false, time: default_time(), + jitter_minutes: 0, providers: default_providers(), last_fired_date: None, last_result: None, @@ -557,6 +727,8 @@ impl AutoCheckin { json!({ "id": id, "label": provider_label(id) }) }).collect::>(), "schedules": entries, + // 启动时立即补签(缺省 true;界面用总开关面板下面的那颗开关回显) + "startupCatchUp": startup_catch_up(), "running": self.is_running(), }) } @@ -635,23 +807,7 @@ impl AutoCheckin { Some(summary) } Err(error) => { - // 失败也写 lastResult(failed 里放错误文案),与 Node 的 catch 分支一致 - let failure = json!({ - "at": logging::now_ms(), - "date": today, - "reason": reason, - "succeeded": 0, - "active": 0, - "total": 0, - "skipped": 0, - "failed": [error.message.clone()], - "failedCount": 1, - }); - write_state(json!({ "lastResult": failure.clone() })); - if let Some(id) = schedule_id { - checkin_schedules::mark_result(id, Some(failure)); - } - logging::log("[Checkin]", &format!("❌ 定时签到失败: {}", error.message)); + self.record_failure(schedule_id, &today, reason, &error.message); None } }; @@ -659,8 +815,280 @@ impl AutoCheckin { outcome } + /// 失败分支:写 lastResult(failed 里放错误文案),与 Node 的 catch 分支一致。 + /// 两条路径共用:`fire_for` 的 `run_checkin` 报错、`spawn_spread` 的目标 + /// 解析失败(两者都只记一处账,文案口径一致)。 + fn record_failure(&self, schedule_id: Option<&str>, today: &str, reason: &str, message: &str) { + let failure = json!({ + "at": logging::now_ms(), + "date": today, + "reason": reason, + "succeeded": 0, + "active": 0, + "total": 0, + "skipped": 0, + "failed": [message], + "failedCount": 1, + }); + write_state(json!({ "lastResult": failure.clone() })); + if let Some(id) = schedule_id { + checkin_schedules::mark_result(id, Some(failure)); + } + logging::log("[Checkin]", &format!("❌ 定时签到失败: {message}")); + } + + /// 等到墙上时钟到达 `at_ms`;停机时返回 false。 + /// + /// 不直接 `sleep(很长的时长)`:tokio 定时器基于**单调时钟**,机器休眠期间 + /// 不推进,一觉醒来会白等超出预期的时间;而且单次长 sleep 期间无法响应 + /// 停机。这里封顶 30 秒,每一段都按墙上时钟(与 tick 同源,见模块头 + /// 「触发方式」)重新计算剩余量 —— 休眠、改系统时间都能自愈。 + async fn wait_until(&self, at_ms: i64) -> bool { + loop { + if self.lock().stopped.load(Ordering::SeqCst) { + return false; + } + let remaining = at_ms - logging::now_ms(); + if remaining <= 0 { + return true; + } + let chunk = remaining.min(TICK_MS as i64); + tokio::time::sleep(Duration::from_millis(chunk as u64)).await; + } + } + + /// 抢「执行中」标记;已有轮次在跑时按 500ms 轮询等待,直到拿到、停机 + /// 或等满 `RUNNING_WAIT_MS`。 + /// + /// 给随机窗口铺开用:铺开任务逐个账号执行,每次执行前抢一次锁,执行完 + /// 立刻放 —— 两个账号之间的 sleep 不持有锁,因此手动签到只可能在这些 + /// 几秒钟的窗口里撞上并得到「正在执行中」,而不是整段窗口都被拒绝。 + /// + /// **超时不是可选的**:另一轮签到若卡在上游(连接不断、迟迟不回), + /// `running` 会一直为 true。无限等待会让铺开任务永久挂住,连带 `spreads` + /// 里的 key 永不释放 —— 这条条目今天彻底静默。等满就如实跳过这个账号 + /// (返回 None 让调用方 break),本次轮次照常汇总落账。 + async fn acquire_running(&self) -> Option { + let deadline = logging::now_ms() + RUNNING_WAIT_MS; + loop { + { + let mut inner = self.lock(); + if inner.stopped.load(Ordering::SeqCst) { + return None; + } + if !inner.running { + inner.running = true; + return Some(RunningGuard { inner: self.inner.clone() }); + } + } + if logging::now_ms() >= deadline { + logging::verbose( + "[Checkin]", + "另一轮签到长时间未结束,本轮随机窗口跳过剩余账号", + ); + return None; + } + tokio::time::sleep(Duration::from_millis(500)).await; + } + } + + /// 起一轮「随机窗口铺开」:条目到窗口起点后,本轮账号在窗口内各自 + /// 随机一个时刻执行。 + /// + /// ── 为什么是后台任务而不是在 tick 里 await ───────────────── + /// 窗口最长 `2 × MAX_JITTER_MINUTES`(4 小时)。若照 `fire_for` 那样在 + /// tick 里一路 await 到底:① tick 循环被占住,其他条目到点会被延后; + /// ② 全局 `running` 会被持有一整个窗口,期间所有手动签到都被拒。 + /// 所以这里只做**同步的准备工作**(落账、解析目标、算好计划)后 spawn, + /// tick 立即返回;账号之间的等待(sleep)都在后台任务里、且不在锁内。 + fn spawn_spread(&self, schedule: &Schedule, reason: &str, today: &str) { + let key = format!("{}|{today}", schedule.id); + { + let mut inner = self.lock(); + if inner.spreads.contains(&key) { + return; + } + inner.spreads.insert(key.clone()); + } + // 从这里起,key 的移除由 Drop 负责:**任何**提前 return 或任务 abort + // 都要把 key 清掉,否则这条条目今天再也不会被 tick 重试(永久静默)。 + // 与 `RunningGuard` 同一手法,只是作用对象不同。 + let _spread_guard = SpreadGuard { service: self.clone(), key: key.clone() }; + // 先落日期再执行(与 fire_for 同一理由:进程中途被杀也不会反复补签) + write_state(json!({ "lastFiredDate": today })); + checkin_schedules::mark_fired(&schedule.id, Some(today)); + let span_minutes = window_bounds(&schedule.time, schedule.jitter_minutes) + .map(|(start, end)| end - start) + .unwrap_or(0); + logging::log( + "[Checkin]", + &format!( + "⏰ 定时签到开始({reason},{} 分钟窗口内逐个账号随机执行)", + span_minutes + ), + ); + + // ── 目标解析在 spawn **之前**做 ────────────────────────── + // 两个理由: + // ① 解析失败要走「回退去重标记」的路径(见下),而那需要已经拿到结果; + // ② 账号集合在 spawn 时就定下来,后台任务跑 4 小时期间账号增删不会让 + // 计划中途变化(与 fire_for 一次性解析目标的口径一致)。 + let (targets, skipped) = + match checkin::resolve_checkin_targets(&self.store, schedule.providers.as_slice(), None) { + Ok(found) => found, + Err(error) => { + // 整条条目失败:记账 + **回退今天已触发标记**,让下个 tick + // 还能再来一次。不回退的话一次偶发失败会让这条条目当天彻底 + // 静默(fire_for 那侧失败也落账,但它是单轮执行、重试代价高; + // 铺开的失败多半来自账号库暂时读不出来,值得再试)。 + self.record_failure(Some(&schedule.id), today, reason, &error.message); + checkin_schedules::mark_fired(&schedule.id, None); + return; + } + }; + let Some((start_minute, _)) = window_bounds(&schedule.time, schedule.jitter_minutes) else { + // time 在读取时已归一,走到这里说明配置在调度后被改坏 + self.record_failure(Some(&schedule.id), today, reason, "定时条目的时刻无效"); + checkin_schedules::mark_fired(&schedule.id, None); + return; + }; + // 起点必须由**这一轮的日期**推出,不能用「此刻」的日期:任务若恰好 + // 跨过零点(23:5x 的窗口),用现在的时间会算出次日同一分钟, + // 所有账号要白睡约 24 小时。today 是 spawn 时的日期键。 + let Some(start_at_ms) = chrono::NaiveDate::parse_from_str(today, "%Y-%m-%d") + .ok() + .and_then(|date| date.and_hms_opt(start_minute / 60, start_minute % 60, 0)) + .and_then(|naive| beijing::offset().from_local_datetime(&naive).single()) + .map(|target| target.timestamp_millis()) + else { + self.record_failure(Some(&schedule.id), today, reason, "无法计算随机窗口的起点"); + checkin_schedules::mark_fired(&schedule.id, None); + return; + }; + + // 计划也在这里算好:偏移是纯函数,不依赖后台任务的状态 + let mut plan: Vec<(i64, Value)> = targets + .iter() + .map(|account| { + let account_id = account.get("id").and_then(Value::as_str).unwrap_or(""); + let offset = spread_offset_seconds( + &schedule.id, + today, + &schedule.time, + schedule.jitter_minutes, + account_id, + ); + (start_at_ms + i64::from(offset) * 1000, account.clone()) + }) + .collect(); + plan.sort_by_key(|(at, _)| *at); + logging::verbose( + "[Checkin]", + &format!( + "随机窗口计划({}): {} 个账号,窗口起点 {},首个 {},末个 {}", + checkin_schedules::display_label(schedule), + plan.len(), + start_at_ms, + plan.first().map(|(at, _)| *at).unwrap_or(start_at_ms), + plan.last().map(|(at, _)| *at).unwrap_or(start_at_ms), + ), + ); + + let service = self.clone(); + let schedule = schedule.clone(); + let reason = reason.to_string(); + let today = today.to_string(); + // 守卫**移进**后台任务:任务正常结束、提前 return、或被 abort(停机时 + // `stop()` 只关循环,`spawn_task` 的 future 随运行时一起 drop)都会在 + // Drop 里清掉 key。放在外层是不行的 —— 外层函数一返回守卫就 drop 了。 + crate::spawn_task(async move { + let _spread_guard = _spread_guard; + service.run_spread(schedule, reason, today, plan, skipped).await; + }); + } + + /// 铺开任务的执行体:逐个账号等到自己的偏移时刻再签。 + /// + /// 偏移已过的(窗口中途启动、补签、Qoder 国际版重试)立即执行 —— + /// 这正是「错过窗口就全部立刻签完」的实现,不需要单独分支。 + async fn run_spread( + &self, + schedule: Schedule, + reason: String, + today: String, + plan: Vec<(i64, Value)>, + skipped: usize, + ) { + let mut results = Vec::with_capacity(plan.len()); + // 本轮是否因为「等不到执行锁 / 停机」而提前收工:这种情况下还有账号 + // 一次都没签,今天该保持未落账让后续 tick 接手(见下面的处理)。 + let mut cut_short = false; + for (at, account) in plan { + // 睡在锁外:这段时间别人可以正常手动签到 + if !self.wait_until(at).await { + cut_short = true; + break; + } + let Some(_guard) = self.acquire_running().await else { + cut_short = true; + break; + }; + results.push( + checkin::run_account( + &self.store, + &self.billing, + &account, + false, + "schedule", + &reason, + ) + .await, + ); + } + + // 原始汇总(带 results 数组)先记签到历史台账,再转成界面摘要: + // `record_success` 产出的摘要没有 results(只留前 5 条失败文案), + // 台账需要逐账号明细(见 checkin_history 的模块头)。 + let result = checkin::summarize_results(&results, skipped); + crate::server::core::checkin_history::record(&result, &reason); + let summary = self.record_success(&result, &today, &reason); + checkin_schedules::mark_result(&schedule.id, Some(summary.clone())); + // ── 今天要不要保持「未落账」───────────────────────────── + // 两种情况都要留着让后续 tick 再试: + // ① 有 Qoder 国际版账号还在等 10:00 的活动窗口(既有规则); + // ② 本轮被提前截断(停机 / 等锁超时):剩下的账号今天还一次没签, + // 落账就等于把它们整天静默掉。已经签过的账号重试时是幂等的。 + let qoder_pending = summary.get("qoderIntlPending").and_then(Value::as_bool) == Some(true); + if qoder_pending || cut_short { + checkin_schedules::mark_fired(&schedule.id, None); + } + if qoder_pending { + logging::log( + "[Checkin]", + "⏳ Qoder 国际版的活动窗口未开(官方每日 10:00 UTC+8),今天会自动重试到领到为止", + ); + } + if cut_short { + logging::log( + "[Checkin]", + "⏸ 本轮随机窗口提前收工(停机或等执行锁超时),剩余账号由后续调度继续", + ); + } + // key 的移除由 `SpreadGuard` 的 Drop 负责(见 spawn_spread 的注释) + } + + /// 铺开任务收尾:从「进行中」集合移除(幂等;`SpreadGuard` 的 Drop 也走这里)。 + fn finish_spread(&self, key: &str) { + self.lock().spreads.remove(key); + } + /// 本轮是否有「Qoder 国际版账号没领到且不算已签」的行 —— 有则今天保持 /// 未落账状态,等窗口开了重试(见 tick 的说明)。 + /// + /// 判定只看这一条账号的结果,**不要求它同时是「未成功」**:重试是整条 + /// 条目重来,已经领到的账号在下一次会返回 `alreadyCompleted`(不算 pending), + /// 而仍未领到的账号会继续 pending —— 「只要还有 pending 就继续等窗口」, + /// 领到之后下一轮就自然落到已签,不再重试。 fn qoder_intl_pending(result: &Value) -> bool { result .get("results") @@ -778,8 +1206,8 @@ impl AutoCheckin { if !schedule.enabled { continue; } - // 未到点直接看下一条(time 在读取时已归一,这里不会解析失败) - if due_now(&schedule.time, now).is_none() { + // 未到窗口起点直接看下一条(time 在读取时已归一,这里不会解析失败) + if due_now(&schedule.time, schedule.jitter_minutes, now).is_none() { continue; } // 条目级当天去重 @@ -788,6 +1216,11 @@ impl AutoCheckin { } let reason = format!("到点触发({})", checkin_schedules::display_label(&schedule)); + // 随机窗口:后台铺开,不占 tick 循环与全局执行锁(见 spawn_spread) + if schedule.jitter_minutes > 0 { + self.spawn_spread(&schedule, &reason, &today); + continue; + } match self.fire_for(&reason, Some(&schedule.id), "schedule").await { Some(result) => { // 领取轮次完成,但里面有「Qoder 国际版无活动」的行 → 这一条 @@ -842,11 +1275,22 @@ impl AutoCheckin { /// (理由见模块头部「补签」)。多条目之后按条目各补各的:今天没跑过的 /// **启用**条目每条补一次,串在一个任务里跑(fire 的全局防重本来就只允许 /// 一轮在跑,串行省得互相抢空)。 + /// + /// 关掉「启动时立即补签」(`startup_catch_up`)时只起调度循环、不补签: + /// 今天还没到窗口起点的条目留给 tick —— 否则早上开机就会把当天的随机 + /// 窗口提前签掉,等于随机失效。已过窗口的条目 tick 下一个 30 秒就会补。 pub fn start(&self) { if !master_enabled() { return; } self.schedule(); + if !startup_catch_up() { + logging::verbose( + "[Checkin]", + "启动补签已关闭:今天未执行的条目等到各自的窗口起点再由调度触发", + ); + return; + } let today = today_key(); let pending: Vec = checkin_schedules::list() .into_iter() @@ -906,9 +1350,19 @@ impl AutoCheckin { let has_enabled = payload.get("enabled").is_some(); let has_time = payload.get("time").is_some(); let has_providers = payload.get("providers").is_some(); - if !has_enabled && !has_time && !has_providers { + let has_startup_catch_up = payload.get("startupCatchUp").is_some(); + if !has_enabled && !has_time && !has_providers && !has_startup_catch_up { return Err(AutoCheckinConfigError::new("没有需要更新的字段")); } + if has_startup_catch_up { + // 与 enabled 同款口径:只有显式 true 才算开,其余(null / 字符串 / 0)都关 + let on = payload.get("startupCatchUp") == Some(&Value::Bool(true)); + write_state(json!({ "startupCatchUp": on })); + logging::log( + "[Checkin]", + &format!("启动时立即补签已{}", if on { "开启" } else { "关闭" }), + ); + } if has_enabled { // Node: `enabled !== undefined` → `patch.enabled = enabled === true`, // 也就是说 null / 字符串 / 0 都会把开关置为 false(不是「忽略」) @@ -1016,3 +1470,165 @@ pub fn stop_global() { service.stop(); } } + +#[cfg(test)] +mod tests { + //! 随机窗口的纯函数边界。 + //! + //! 只测不碰全局 config / 网络的函数(`window_bounds` / + //! `spread_offset_seconds` / `due_now` / `next_run_at_ms`):这些是 + //! 调度语义的全部来源,边界错一格就是「某天不签」或「同一天签两次」。 + //! `tick` / `spawn_spread` 的端到端需要 mock 账号库与上游,不在这一层做。 + use super::*; + use chrono::TimeZone; + + /// 构造一个北京时间时刻(测试用;固定偏移恒为 `Single`) + fn at(month: u32, day: u32, hour: u32, minute: u32) -> DateTime { + beijing::offset() + .with_ymd_and_hms(2026, month, day, hour, minute, 0) + .single() + .expect("北京时间构造恒成功") + } + + // ── 窗口边界 ────────────────────────────────────────────── + + #[test] + fn window_without_jitter_is_the_point_itself() { + assert_eq!(window_bounds("07:20", 0), Some((7 * 60 + 20, 7 * 60 + 20))); + } + + #[test] + fn window_extends_both_ways() { + assert_eq!(window_bounds("07:20", 30), Some((6 * 60 + 50, 7 * 60 + 50))); + } + + #[test] + fn window_clamps_to_day_start() { + // 00:01 - 30 分钟夹到 00:00,而不是昨天 23:31 + assert_eq!(window_bounds("00:01", 30), Some((0, 31))); + } + + #[test] + fn window_clamps_to_day_end() { + // 23:50 + 30 分钟夹到 23:59,而不是次日 00:20 + assert_eq!(window_bounds("23:50", 30), Some((23 * 60 + 20, 23 * 60 + 59))); + } + + #[test] + fn window_rejects_invalid_time() { + assert_eq!(window_bounds("25:00", 10), None); + assert_eq!(window_bounds("", 10), None); + } + + // ── 账号偏移 ────────────────────────────────────────────── + + #[test] + fn spread_offset_is_deterministic() { + let first = spread_offset_seconds("default", "2026-10-17", "07:20", 30, "acc-1"); + let second = spread_offset_seconds("default", "2026-10-17", "07:20", 30, "acc-1"); + assert_eq!(first, second, "同一天同一账号必须落在同一偏移,否则重试会换时间"); + } + + #[test] + fn spread_offset_changes_with_date() { + // 日期参与哈希是「每天不同」的全部依据;这里只钉住「至少变了一个」, + // 不假设具体数值(哈希值是实现细节) + let today = spread_offset_seconds("default", "2026-10-17", "07:20", 30, "acc-1"); + let tomorrow = spread_offset_seconds("default", "2026-10-18", "07:20", 30, "acc-1"); + assert_ne!(today, tomorrow); + } + + #[test] + fn spread_offset_stays_inside_window() { + let (start, end) = window_bounds("07:20", 30).unwrap(); + let span = (end - start) * 60; + for index in 0..64 { + let account = format!("acc-{index}"); + let offset = spread_offset_seconds("default", "2026-10-17", "07:20", 30, &account); + assert!(offset <= span, "偏移 {offset} 超出窗口跨度 {span}"); + } + } + + #[test] + fn spread_offset_is_zero_without_jitter() { + // N=0 时窗口跨度 0,偏移必须恒 0 —— 这是「不随机时行为逐字不变」的保证 + for account in ["acc-1", "acc-2", "acc-3"] { + assert_eq!( + spread_offset_seconds("default", "2026-10-17", "07:20", 0, account), + 0 + ); + } + } + + #[test] + fn spread_offsets_spread_across_accounts() { + // 不要求完美均匀,只要求不是所有账号都堆在同一点(哈希取模的正常形态) + let offsets: std::collections::HashSet = (0..32) + .map(|index| { + spread_offset_seconds( + "default", + "2026-10-17", + "07:20", + 30, + &format!("acc-{index}"), + ) + }) + .collect(); + assert!(offsets.len() > 16, "32 个账号只落出 {} 个不同偏移", offsets.len()); + } + + // ── 触发判定与展示 ──────────────────────────────────────── + + #[test] + fn due_now_keeps_legacy_semantics_without_jitter() { + let now = at(10, 17, 7, 20); + assert_eq!(due_now("07:20", 0, now), Some(now)); + assert_eq!(due_now("07:21", 0, now), None); + } + + #[test] + fn due_now_fires_at_window_start() { + let now = at(10, 17, 6, 50); + // 中心是 07:20,N=30 ⇒ 06:50 就到点 + assert_eq!(due_now("07:20", 30, now), Some(now)); + assert_eq!(due_now("07:20", 30, at(10, 17, 6, 49)), None); + } + + #[test] + fn next_run_without_jitter_matches_legacy() { + let now = at(10, 17, 6, 0); + let target = at(10, 17, 7, 20); + assert_eq!(next_run_at_ms("07:20", 0, false, now), Some(target.timestamp_millis())); + // 已过 → 明天 + let later = at(10, 17, 8, 0); + let tomorrow = at(10, 18, 7, 20); + assert_eq!(next_run_at_ms("07:20", 0, false, later), Some(tomorrow.timestamp_millis())); + // 今天已触发(启动补签会在时点前落账)→ 明天 + assert_eq!( + next_run_at_ms("07:20", 0, true, now), + Some(tomorrow.timestamp_millis()) + ); + } + + #[test] + fn next_run_uses_window_start() { + let now = at(10, 17, 6, 0); + let start = at(10, 17, 6, 50); + assert_eq!( + next_run_at_ms("07:20", 30, false, now), + Some(start.timestamp_millis()) + ); + } + + #[test] + fn next_run_after_window_start_rolls_to_tomorrow() { + // 已过窗口起点即使还没到中心时刻,今天的窗口也已开始过 —— 展示明天, + // 与 tick 的 due_now(now >= start 即触发)保持一致 + let now = at(10, 17, 7, 0); + let tomorrow = at(10, 18, 6, 50); + assert_eq!( + next_run_at_ms("07:20", 30, false, now), + Some(tomorrow.timestamp_millis()) + ); + } +} diff --git a/desktop-tauri/src-tauri/server/src/server/core/billing/checkin.rs b/desktop-tauri/src-tauri/server/src/server/core/billing/checkin.rs index fc607b8e..8cc2fe80 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/billing/checkin.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/billing/checkin.rs @@ -432,6 +432,22 @@ pub async fn checkin_for( } row } + // ModelScope(魔搭)的两个站点:签到 = 调一次登录信息接口 + // (`GET {网页站}/api/v1/users/login/info`,**调用即触发当日魔粒**, + // 幂等;见 `providers::modelscope::checkin` 的模块头)。 + // 两个站点各打各的网页站、令牌不通用 —— 地区由 provider id 反查 + // (账号集合按 provider 隔离,同一 id 不可能同时属于两家)。 + "modelscope" | "modelscope-intl" => { + let region = + crate::server::core::providers::modelscope::Region::from_provider_id(provider_id) + .unwrap_or(crate::server::core::providers::modelscope::Region::Cn); + let claim = crate::server::core::providers::modelscope::checkin::claim_daily_checkin( + region, store, &id, + ) + .await + .map_err(|error| error.message); + claim_result(id, name, &display, true, claim) + } // 兜底只服务默认那家(WorkBuddy 国内版)——**不是**「剩下所有家」。 // 这里曾经是无所不包的 `_`:一个 provider 只要没在上面列出,就会拿自己的 // 令牌去打腾讯的签到接口,稳定报错且看不出原因(Qoder 接入前正是这个处境)。 @@ -704,39 +720,71 @@ pub async fn run_checkin( let manual = matches!(source, "single" | "manual"); let mut results = Vec::with_capacity(targets.len()); for account in &targets { - let row = checkin_for(store, billing, account, manual).await; - // 落签到时间:手动单签与定时签到走的是**这一段**(两条链都调本函数), - // 所以账号页的「已签到」在两种路径下都会亮起来,不需要各自记一次。 - // 写盘失败只记日志、不改签到结果 —— 上游那边积分已经领到了, - // 因为一次落盘失败就把成功的签到报成失败是本末倒置。 - if let Some(account_id) = row.get("id").and_then(Value::as_str) { - // 判据是 [`day_completed`](claim 说完成,或国际版活跃链路完成)—— - // 与台账的 outcome 判定同源;判据只此一份,别在这里再写一份。 - if day_completed(&row) && !store.mark_checkin(account_id, logging::now_ms()) { - logging::verbose( - "[Accounts]", - &format!("账号 {account_id} 的签到时间未能落盘(账号可能已被删除)"), - ); - } + results.push(run_account(store, billing, account, manual, source, reason).await); + } + let summary = summarize_results(&results, skipped); + // 批量轮次进台账(签到中心时间线)。写盘失败只记日志:上游那边积分已经 + // 领到,台账缺一条不该让这次签到的响应报错。 + if id.is_none() { + crate::server::core::checkin_history::record(&summary, reason); + } + Ok(summary) +} + +/// 单个账号的签到 + 落 `checkinAt` + 记签到记录台账。 +/// +/// 从 `run_checkin` 的循环体抽出(2026-10 随机窗口改造):定时铺开路径 +/// (`auto_checkin::run_spread`)逐个账号调用它,与批量路径共用同一段记账, +/// 不会出现「铺开签到的账号不亮『已签到』」这类两套行为。 +/// `manual` 的语义见 [`checkin_for`](只对 CodeArts 的限流闸有意义)。 +pub async fn run_account( + store: &AccountStore, + billing: &BillingService, + account: &Value, + manual: bool, + source: &str, + reason: &str, +) -> Value { + let row = checkin_for(store, billing, account, manual).await; + // 落签到时间:手动单签与定时签到走的是**这一段**(两条链都调本函数), + // 所以账号页的「已签到」在两种路径下都会亮起来,不需要各自记一次。 + // 写盘失败只记日志、不改签到结果 —— 上游那边积分已经领到了, + // 因为一次落盘失败就把成功的签到报成失败是本末倒置。 + if let Some(account_id) = row.get("id").and_then(Value::as_str) { + // 判据是 [`day_completed`](claim 说完成,或国际版活跃链路完成)—— + // 与台账的 outcome 判定同源;判据只此一份,别在这里再写一份。 + if day_completed(&row) && !store.mark_checkin(account_id, logging::now_ms()) { + logging::verbose( + "[Accounts]", + &format!("账号 {account_id} 的签到时间未能落盘(账号可能已被删除)"), + ); } - // 签到记录台账(schema v11):每个账号行落一条明细(成败 / 错误原文 / - // 收益文案都在结果行里)。写盘失败只记日志:台账缺一条不该让这次 - // 签到的响应报错 —— 与上面 mark_checkin 的取舍同构。provider 由账号 - // 记录带上(结果行里没有这个字段,记录页的提供商筛选列要用)。 - crate::server::core::checkin_records::record_row( - &row, - account.get("provider").and_then(Value::as_str).unwrap_or(""), - source, - reason, - ); - results.push(row); } - // 「真实领取」与「今日已领取」都表示本日成功领到分,计入 succeeded; - // 活跃链路(保活对话 / 活跃上报 / 网页会话)单独统计在 `active` —— - // 它不产生「领取」,不并入 succeeded,免得把两类事混成一个数。 - // 注意 succeeded 只是这行日志的计数:落 `checkinAt` 的判据是 - // [`day_completed`](活跃链路完成同样落账),两者刻意不同 —— 前者计量 - // 「真领到的分」,后者回答「今天是否已完成」。 + // 签到记录台账(schema v11):每个账号行落一条明细(成败 / 错误原文 / + // 收益文案都在结果行里)。写盘失败只记日志:台账缺一条不该让这次 + // 签到的响应报错 —— 与上面 mark_checkin 的取舍同构。provider 由账号 + // 记录带上(结果行里没有这个字段,记录页的提供商筛选列要用)。 + crate::server::core::checkin_records::record_row( + &row, + account.get("provider").and_then(Value::as_str).unwrap_or(""), + source, + reason, + ); + row +} + +/// 一轮签到结果 → `{results, succeeded, active, total, skipped}` 汇总。 +/// +/// 「真实领取」与「今日已领取」都表示本日成功领到分,计入 succeeded; +/// 活跃链路(保活对话 / 活跃上报 / 网页会话)单独统计在 `active` —— +/// 它不产生「领取」,不并入 succeeded,免得把两类事混成一个数。 +/// 注意 succeeded 只是这行日志的计数:落 `checkinAt` 的判据是 +/// [`day_completed`](活跃链路完成同样落账),两者刻意不同 —— 前者计量 +/// 「真领到的分」,后者回答「今天是否已完成」。 +/// +/// 抽成公开函数供 `auto_checkin::run_spread` 复用:铺开路径自己控制节奏, +/// 但统计口径必须与批量路径逐字一致。 +pub fn summarize_results(results: &[Value], skipped: usize) -> Value { let succeeded = results .iter() .filter(|item| { @@ -771,27 +819,13 @@ pub async fn run_checkin( results.len() ), ); - // 批量轮次进台账(签到中心时间线)。写盘失败只记日志:上游那边积分已经 - // 领到,台账缺一条不该让这次签到的响应报错。 - if id.is_none() { - crate::server::core::checkin_history::record( - &json!({ - "succeeded": succeeded, - "active": active, - "total": results.len(), - "skipped": skipped, - "results": results, - }), - reason, - ); - } - Ok(json!({ + json!({ "results": results, "succeeded": succeeded, "active": active, "total": results.len(), "skipped": skipped, - })) + }) } #[cfg(test)] diff --git a/desktop-tauri/src-tauri/server/src/server/core/checkin_schedules.rs b/desktop-tauri/src-tauri/server/src/server/core/checkin_schedules.rs index 9c0a11dd..bbe4146b 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/checkin_schedules.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/checkin_schedules.rs @@ -2,11 +2,13 @@ //! //! ── 形状 ──────────────────────────────────────────────────── //! 每条条目是一次「定点签到」的完整配置: -//! `{id, label, enabled, time, providers, lastFiredDate, lastResult}` +//! `{id, label, enabled, time, jitterMinutes, providers, lastFiredDate, lastResult}` //! - `id` 稳定标识(界面按它 upsert / 删除 / 立即执行;合成条目是 "default") //! - `label` 展示名(可空;空时展示退到 `time`) //! - `enabled` 条目自己的开关 //! - `time` HH:MM,北京时间口径(见 `core::beijing`,issue #138) +//! - `jitterMinutes` 随机前后 N 分钟(0 = 不随机);窗口与账号铺开的语义见 +//! `core::auto_checkin` 的模块头「随机窗口」 //! - `providers` 这条要签的提供商(`CHECKIN_PROVIDERS` 子集,至少一家) //! - `lastFiredDate` / `lastResult` 条目级的当天去重与上一轮结果 //! 总开关沿用 `autoCheckin.enabled`(见 `core::auto_checkin`):关了所有条目都不跑。 @@ -40,11 +42,51 @@ pub struct Schedule { pub label: String, pub enabled: bool, pub time: String, + /// 随机前后 N 分钟(0 = 不随机,时刻即触发点)。窗口与账号铺开见 + /// `auto_checkin` 的「随机窗口」说明。 + pub jitter_minutes: u32, pub providers: Vec, pub last_fired_date: Option, pub last_result: Option, } +/// 读侧的随机分钟归一:缺省 / 非数字 / 负数 / 小数一律当 0,超上限夹取。 +/// +/// 读侧刻意宽容(与 `time` 坏了回落 `DEFAULT_TIME` 同一原则):配置是用户 +/// 手改过也可能被旧版本写过,读不出来时退到「不随机」这个安全行为, +/// 而不是让整条条目失效。写入侧的校验更严(见 `upsert`),非法值当场拒绝。 +pub fn normalize_jitter(value: Option<&Value>) -> u32 { + let Some(number) = value.and_then(Value::as_u64) else { + return 0; + }; + u32::try_from(number) + .unwrap_or(auto_checkin::MAX_JITTER_MINUTES) + .min(auto_checkin::MAX_JITTER_MINUTES) +} + +/// 写入侧的随机分钟校验:`None` 表示「这次请求没带该字段」(保持原值), +/// `Some(0)` 是**合法的显式值**(关闭随机)——两者必须能区分开。 +/// +/// 非法值当场拒绝而不是悄悄夹取:用户填 999 却看到保存成功、实际只按 120 +/// 生效,比直接报错更难排查。错误文案与 `normalize_time` 的既有风格一致。 +fn parse_jitter(value: Option<&Value>) -> Result, String> { + let Some(value) = value else { + return Ok(None); + }; + // `as_u64` 已经挡住了负数、小数、字符串与 null,这里只剩「超上限」要判 + value + .as_u64() + .and_then(|number| u32::try_from(number).ok()) + .filter(|minutes| *minutes <= auto_checkin::MAX_JITTER_MINUTES) + .map(Some) + .ok_or_else(|| { + format!( + "随机分钟应为 0 - {} 的整数", + auto_checkin::MAX_JITTER_MINUTES + ) + }) +} + /// 展示名:用户起的名,没起就退到时刻(时刻是唯一必填项,一定能展示) pub fn display_label(schedule: &Schedule) -> &str { if schedule.label.is_empty() { @@ -72,7 +114,7 @@ fn stored_entries() -> Option> { .cloned() } -/// 单条的归一化:id / label / enabled / time / providers 逐个兜底。 +/// 单条的归一化:id / label / enabled / time / jitter / providers 逐个兜底。 /// time 坏了回落 DEFAULT_TIME(调度起不来比时刻错更糟,与 auto_checkin 同)。 fn normalize_schedule(raw: &Value) -> Schedule { let id = raw @@ -92,12 +134,14 @@ fn normalize_schedule(raw: &Value) -> Schedule { .filter(|value| !value.is_null()) .and_then(|value| auto_checkin::normalize_time(Some(value)).ok()) .unwrap_or_else(auto_checkin::default_time); + let jitter_minutes = normalize_jitter(raw.get("jitterMinutes")); let providers = auto_checkin::normalize_providers(raw.get("providers")); Schedule { id, label, enabled, time, + jitter_minutes, providers, last_fired_date: raw .get("lastFiredDate") @@ -139,13 +183,18 @@ fn write_entries(entries: Vec) { config::update_raw_field(auto_checkin::CONFIG_KEY, Value::Object(merged)); } -/// 条目 → 存储原文(保留 lastFiredDate / lastResult,条目级的去重状态跨重启) +/// 条目 → 存储原文(保留 lastFiredDate / lastResult,条目级的去重状态跨重启)。 +/// +/// ⚠️ 新增字段必须同时加到 `normalize_schedule` 与本函数:`patch_entry` 是 +/// 「读原文 → normalize → 改 → to_value 全量写回」,漏一处就会让 `mark_fired` +/// 每次把该字段静默清掉。 fn to_value(schedule: &Schedule) -> Value { json!({ "id": schedule.id, "label": schedule.label, "enabled": schedule.enabled, "time": schedule.time, + "jitterMinutes": schedule.jitter_minutes, "providers": schedule.providers, "lastFiredDate": schedule.last_fired_date, "lastResult": schedule.last_result, @@ -168,6 +217,7 @@ pub fn upsert(payload: &Value) -> Result { .unwrap_or_else(|| format!("schedule-{}", crate::server::logging::now_ms())); let time = auto_checkin::normalize_time(payload.get("time")) .map_err(|error| error.message)?; + let jitter_minutes = parse_jitter(payload.get("jitterMinutes"))?; // 范围:只认注册过的提供商(去重、按注册顺序);一条不勾到点也无账号可签 let list_value = payload.get("providers"); let picked: Vec = CHECKIN_PROVIDERS @@ -209,6 +259,15 @@ pub fn upsert(payload: &Value) -> Result { None => true, }, }; + // 随机分钟同样「缺省保持原值、新建默认 0」:界面的条目开关按钮是整表单 + // 重发,漏带这个字段时不能把它清零(见前端 `toggleScheduleEnabled`)。 + let jitter_minutes = match jitter_minutes { + Some(minutes) => minutes, + None => existing_entry + .as_ref() + .map(|old| old.jitter_minutes) + .unwrap_or(0), + }; // 更新已有条目时保留它的去重状态;新建条目从「今天还没跑」开始 let (last_fired_date, last_result) = existing_entry .map(|old| (old.last_fired_date, old.last_result)) @@ -225,6 +284,7 @@ pub fn upsert(payload: &Value) -> Result { label, enabled, time, + jitter_minutes, providers: picked, last_fired_date, last_result, @@ -387,3 +447,68 @@ pub fn extend_providers_once() -> bool { fn record_providers_version() { auto_checkin::write_state(json!({ "providersVersion": auto_checkin::PROVIDERS_VERSION })); } + +#[cfg(test)] +mod tests { + //! 随机分钟字段的归一与往返。 + //! + //! 重点钉住 `normalize_schedule` ↔ `to_value` 的对称性:`patch_entry` 是 + //! 「读原文 → normalize → 改 → to_value 全量写回」,漏了任何一侧, + //! `mark_fired` 都会把 `jitterMinutes` 静默清掉(用户只在第二天发现随机 + //! 没了,极难排查)。这些函数不碰全局 config,可并行跑。 + use super::*; + use serde_json::json; + + fn roundtrip(raw: Value) -> Value { + to_value(&normalize_schedule(&raw)) + } + + #[test] + fn jitter_roundtrips_through_storage() { + let stored = roundtrip(json!({ + "id": "s1", + "enabled": true, + "time": "07:20", + "jitterMinutes": 45, + "providers": ["trae"], + })); + assert_eq!(stored.get("jitterMinutes").and_then(Value::as_u64), Some(45)); + } + + #[test] + fn missing_jitter_reads_as_zero() { + let schedule = normalize_schedule(&json!({ + "id": "s1", + "time": "07:20", + "providers": ["trae"], + })); + assert_eq!(schedule.jitter_minutes, 0); + } + + #[test] + fn invalid_jitter_reads_as_zero_or_clamps() { + // 读侧宽容:手改配置写坏了不能整条条目失效 + assert_eq!(normalize_jitter(Some(&json!(null))), 0); + assert_eq!(normalize_jitter(Some(&json!("abc"))), 0); + assert_eq!(normalize_jitter(Some(&json!(-5))), 0); + assert_eq!(normalize_jitter(None), 0); + // 超上限夹取(不报错) + assert_eq!( + normalize_jitter(Some(&json!(9999))), + auto_checkin::MAX_JITTER_MINUTES + ); + } + + #[test] + fn write_side_rejects_invalid_jitter() { + // 写入侧严格:用户填 999 却按 120 生效比直接报错更难排查。 + // None = 「没带这个字段」→ 保持原值,与 Some(0) 必须区分开。 + assert_eq!(parse_jitter(None).unwrap(), None); + assert_eq!(parse_jitter(Some(&json!(0))).unwrap(), Some(0)); + assert_eq!(parse_jitter(Some(&json!(120))).unwrap(), Some(120)); + assert!(parse_jitter(Some(&json!(121))).is_err()); + assert!(parse_jitter(Some(&json!(-1))).is_err()); + assert!(parse_jitter(Some(&json!(1.5))).is_err()); + assert!(parse_jitter(Some(&json!("30"))).is_err()); + } +} diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/adapter.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/adapter.rs index 2f32ce92..07378242 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/providers/adapter.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/adapter.rs @@ -1168,6 +1168,13 @@ pub fn adapter_for(kind: ProviderKind) -> &'static dyn ProviderAdapter { // (见 `chatglm/mod.rs` 与 `protocol::chatglm_stream` 的模块头)。 // 它是本项目**唯一**「访客免登录即可用」的一家(`guest/access` 换证)。 ProviderKind::Chatglm => &super::chatglm::CHATGLM_ADAPTER, + // ModelScope 的两个站点是两个 provider、两个实例(同一份实现的按地区 + // 参数化,见 `modelscope::region` 与 `modelscope::mod` 的模块头): + // 国内站打 `api-inference.modelscope.cn` / `modelscope.cn`, + // 国际站打 `.ai` 两个域 —— 打错了会拿到 401(实测), + // 所以这里 kind → region 必须逐字对应。 + ProviderKind::Modelscope => &super::modelscope::MODELSCOPE_ADAPTER, + ProviderKind::ModelscopeIntl => &super::modelscope::MODELSCOPE_INTL_ADAPTER, } } @@ -1271,6 +1278,12 @@ pub fn implemented_kinds() -> Vec { // 且有远程目录(`operation/detail?tag=available_models`)—— 必须在 // 列表里,否则目录刷新循环不会问它(与 Trae / Loomy / Kuku 同一理由)。 ProviderKind::Chatglm, + // ModelScope 的两个站点各算一家:与国内版各自一份模型清单(各打各的 + // 推理域)、各自的缓存槽与刷新排期 —— 两家都必须在列表里,否则国际版的 + // 目录刷新永远不会被调度(症状是「国际版账号加了、模型列表一直是空的」, + // 与 WorkBuddy 国际版那条同一理由)。 + ProviderKind::Modelscope, + ProviderKind::ModelscopeIntl, ] } diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/catalog.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/catalog.rs index cd8a9b8b..3c80eb32 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/providers/catalog.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/catalog.rs @@ -196,6 +196,17 @@ pub(crate) fn refresh_meta(kind: ProviderKind) -> (bool, i64) { super::chatglm::models::remote_refreshed(), super::chatglm::models::last_refreshed_at(), ), + // ModelScope 的两个站点各有一份独立清单(缓存按地区分格,见 + // `modelscope::models` 的模块头):这里如实各查**自己那一格**。 + // 上游**没有**内置兜底清单,所以「有内容」就等于「远程拉到过」。 + ProviderKind::Modelscope | ProviderKind::ModelscopeIntl => { + let region = super::modelscope::Region::from_kind(kind) + .unwrap_or(super::modelscope::Region::Cn); + ( + super::modelscope::models::remote_refreshed(region), + super::modelscope::models::last_refreshed_at(region), + ) + } } } diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/catalog_cache.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/catalog_cache.rs index 12b4c31e..b053acf5 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/providers/catalog_cache.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/catalog_cache.rs @@ -109,6 +109,14 @@ pub const SCOPE_OFFICEACE: &str = "officeace"; /// 智谱清言(`chatglm.cn`)的模型目录缓存槽 pub const SCOPE_CHATGLM: &str = "chatglm"; +/// ModelScope(魔搭)**国内站**的模型目录缓存槽 +/// (`GET {推理域}/models`,OpenAI 格式目录) +pub const SCOPE_MODELSCOPE_CN: &str = "modelscopeCn"; +/// ModelScope **国际站**(两个站点各一份清单 —— 实测两地各 36 条且内容不同, +/// 缓存必须分开,否则先刷的那一站会把另一站的清单覆盖掉, +/// 见 `providers::modelscope::region` 的模块头) +pub const SCOPE_MODELSCOPE_INTL: &str = "modelscopeIntl"; + /// 全部 scope(事实来源:`cached_scopes` 按它遍历;新增一家时加在这里)。 pub const ALL_SCOPES: &[&str] = &[ SCOPE_WORKBUDDY, @@ -131,6 +139,8 @@ pub const ALL_SCOPES: &[&str] = &[ SCOPE_ANTIGRAVITY, SCOPE_OFFICEACE, SCOPE_CHATGLM, + SCOPE_MODELSCOPE_CN, + SCOPE_MODELSCOPE_INTL, ]; /// 一份清单缓存 diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/mod.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/mod.rs index 4da9adbf..344e98d6 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/providers/mod.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/mod.rs @@ -145,6 +145,11 @@ pub mod loomy; /// 含工具自动批准与提问自动应答)全部已接通;`is_stateful` 为 true, /// 见 `monkeycode/mod.rs` 的模块头。 pub mod monkeycode; +/// ModelScope(魔搭)的两个站点。适配实现在 `modelscope/`: +/// 账号管理(粘贴 `ms-` 令牌 + 探活取身份)+ **无状态 OpenAI 兼容转发** + +/// 每日签到 + 魔粒余额;无续期、无桌面端导入。**一套实现、两个 provider** +/// (`modelscope` / `modelscope-intl`,两站账号体系分开,见 `modelscope/region.rs`)。 +pub mod modelscope; pub mod officeace; /// OrcaTerm(腾讯云遨驰终端桌面客户端)。适配实现在 `orcaterm/`: /// 账号管理(**粘贴 accessToken** / 导入桌面端 `data.bin` 登录态)+ @@ -500,6 +505,29 @@ pub enum ProviderKind { /// 智谱清言这一家只有 `chatglm.cn` 一个站点(测试域 `test.chatglm.cn` /// 是**环境**不是地区,靠 `CHATGLM_BASE_URL` 覆盖即可)。 Chatglm, + /// ModelScope(魔搭)**国内站**(`modelscope`)。适配实现在 `modelscope/`: + /// 账号管理(粘贴 `ms-` 令牌 + 探活取身份)、无状态 OpenAI 兼容转发、 + /// 每日签到与魔粒余额。 + /// + /// ── 与 [`ProviderKind::ModelscopeIntl`] 是同一套协议的两个站点 ──── + /// 与 AutoClaw / ZCode / MonkeyCode 同一思路:魔搭的**两个站点各有独立的 + /// 账号体系**(国内令牌打国际站网页接口得 `401 access forbidden`,实测), + /// 所以地区必须是 provider 身份而不是账号上的字段。 + /// 拆成两个 provider 还解决一个具体故障:模型目录只有一份的话, + /// 两个站(各自 36 条、内容不同)会互相覆盖。 + /// + /// 实现是**一套**:`modelscope::ModelScopeAdapter` 持有一个 `modelscope::Region`, + /// 两个静态实例(`MODELSCOPE_ADAPTER` / `MODELSCOPE_INTL_ADAPTER`)由 + /// `adapter_for` 按 kind 给出。地区 → provider 的互查在 `modelscope::Region` + /// (`kind` / `provider_id` / `from_provider_id`),别处不要再写 + /// `"modelscope-intl"` 这类字面量。 + /// + /// provider id 都是新名字(本家是全新接入,没有需要保住的存量 id)。 + Modelscope, + /// ModelScope(魔搭)**国际站**(`modelscope-intl`,站点 `www.modelscope.ai`)。 + /// 与 [`ProviderKind::Modelscope`] 同一套协议、不同站点(网页站与推理域都不同, + /// 见 `modelscope::region`)。 + ModelscopeIntl, } /// 一个提供商的静态元数据。 @@ -602,6 +630,16 @@ pub const PROVIDERS: &[ProviderMeta] = &[ // 大面积同名 —— 靠末位让同名模型优先归已有各家(那些是开放平台账号, // 配额与稳定性都比本家的消费级网页端好)。 ProviderMeta { id: "chatglm", label: "智谱清言" }, + // ModelScope(魔搭)的两个站点**相邻**排列(与 AutoClaw / Qoder / ZCode / + // MonkeyCode 同一理由:同一条产品线的两个版本,中间隔着别家会让「找国际版」 + // 变成一次扫描)。顺序也决定模型目录合并时同名模型先归谁家 —— + // 国内版在前(用户直觉里「魔搭就是国内那个站」)。 + // + // 两个地区**都带版本后缀**(与 WorkBuddy 同款):它们是两家独立的提供商 + // (账号体系、模型目录都分开),名字是用户区分它们的唯一线索 —— + // 只给国际版加后缀会让「ModelScope」读起来像「两地通吃的那一家」。 + ProviderMeta { id: "modelscope", label: "ModelScope 国内版" }, + ProviderMeta { id: "modelscope-intl", label: "ModelScope 国际版" }, ]; /// provider id 在注册表里的下标(未知 id → None)。 @@ -687,6 +725,8 @@ pub fn kind_from_id(id: &str) -> Option { "officeace" => Some(ProviderKind::OfficeAce), "orcaterm" => Some(ProviderKind::OrcaTerm), "chatglm" => Some(ProviderKind::Chatglm), + "modelscope" => Some(ProviderKind::Modelscope), + "modelscope-intl" => Some(ProviderKind::ModelscopeIntl), // 走到这里 = 上面的注册表判定已放行、这个 match 却没有对应分支: // 只可能是有人给 `PROVIDERS` 加了条目忘了加这里。开发期喊出来; // release 返回 None(见上:宁可为「未知」,不可误认成别家)。 @@ -730,6 +770,8 @@ pub const fn kind_id(kind: ProviderKind) -> &'static str { ProviderKind::OfficeAce => "officeace", ProviderKind::OrcaTerm => "orcaterm", ProviderKind::Chatglm => "chatglm", + ProviderKind::Modelscope => "modelscope", + ProviderKind::ModelscopeIntl => "modelscope-intl", } } diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/balance.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/balance.rs new file mode 100644 index 00000000..4db955a2 --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/balance.rs @@ -0,0 +1,156 @@ +//! ModelScope 余额 / 用量查询:魔粒钱包 + 今日已用调用数(2026-10-16 实测)。 +//! +//! ── 两个接口(都在**网页站**,cookie 鉴权)─────────────────────── +//! ```text +//! GET {网页站}/openapi/v1/magicubes/balance +//! → {"success":true,"data":{"total_balance":108,"available_balance":106,"frozen_amount":2}} +//! +//! GET {网页站}/api/v1/inference/rate-limit +//! → {"Code":200,"Success":true,"Data":{"currentUsagePerDay":72}, …} +//! ``` +//! 第一个是**主读数**(魔粒钱包,单位的「魔粒」);第二个是「今天已经用掉多少次 +//! 调用」——它决定今天还能不能继续打上游,是限流链路要看的数。 +//! +//! ── 为什么第二个接口失败只降级、不整条失败 ──────────────────── +//! 主问题是「我还有多少魔粒」,`rate-limit` 是附加读数。让一个附加接口的抖动 +//! 把余额整条变成红色失败,用户会以为钱包也读不到了 —— 所以它失败只记 verbose 日志、 +//! 少给那一行,`raw` 里如实标出没取到。 +//! +//! ── 量纲:三行明细里只有前两行是「魔粒」──────────────────────── +//! `currentUsagePerDay` 的单位是**调用次数**,不是魔粒。它不进 `wallets` +//! (那是钱包明细,同一量纲),而是进 `credits[]`(逐份读数,名字自带量纲说明), +//! 与 `loomy::balance` 把「永久 / 每日赠送」并列的处置同形。名字里写明「次」 +//! 是为了不让界面把它读成「今天用掉了 72 魔粒」。 +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本文件零 unwrap/expect/panic。 + +use serde_json::{json, Value}; + +use crate::server::core::account_store::AccountStore; +use crate::server::errors::GatewayError; +use crate::server::logging; + +use super::client; +use super::credentials; +use super::region::Region; + +/// 魔粒钱包路径(相对网页站) +pub const BALANCE_PATH: &str = "/openapi/v1/magicubes/balance"; + +/// 今日用量路径(相对网页站) +pub const RATE_LIMIT_PATH: &str = "/api/v1/inference/rate-limit"; + +/// 从一份 JSON 里取一个数字(字段缺失 / 非法时给 None)。 +/// +/// 上游有把数字序列化成字符串的形态,两种都认(与 `loomy::balance` 同名函数同款)。 +fn pick_number(data: &Value, key: &str) -> Option { + let value = data.get(key)?; + if let Some(number) = value.as_f64() { + return Some(number); + } + value + .as_str() + .and_then(|text| text.trim().parse::().ok()) +} + +/// 查询某 ModelScope 账号的魔粒余额与今日用量。 +pub async fn query_usage( + region: Region, + store: &AccountStore, + account_id: &str, +) -> Result { + let record = store.modelscope_account_record(region, account_id); + if !account_id.is_empty() && record.is_none() { + return Err(GatewayError::with_status( + 404, + format!( + "ModelScope {}账号 {account_id} 不存在(请重新添加)", + region.label() + ), + )); + } + let credentials = credentials::from_record(region, record.as_ref())?; + + // ── 主读数:魔粒钱包 ──────────────────────────────────── + let balance_payload = + client::site_get(region, BALANCE_PATH, &credentials.token, "魔粒余额查询").await?; + if !client::succeeded(&balance_payload) { + let message = client::message_of(&balance_payload); + return Err(GatewayError::with_status( + 502, + if message.trim().is_empty() { + format!("魔粒余额查询失败(上游 Code={})", client::code_of(&balance_payload)) + } else { + format!("魔粒余额查询失败:{message}") + }, + )); + } + let wallet = client::data_of(&balance_payload); + let available = pick_number(&wallet, "available_balance").unwrap_or(0.0); + let total = pick_number(&wallet, "total_balance"); + let frozen = pick_number(&wallet, "frozen_amount").unwrap_or(0.0); + + // ── 附加读数:今日已用调用数(失败只降级,见模块头)────────── + // 原始报文一并留下(`raw.rateLimit`):没取到给 `Value::Null` —— 排障时 + // 一眼能分辨「上游给了 0」与「这次根本没问到」,缺键则分辨不出。 + let (used_today, rate_limit_raw) = match client::site_get( + region, + RATE_LIMIT_PATH, + &credentials.token, + "今日用量查询", + ) + .await + { + Ok(payload) if client::succeeded(&payload) => ( + pick_number(&client::data_of(&payload), "currentUsagePerDay"), + payload, + ), + Ok(payload) => (None, payload), + Err(error) => { + logging::verbose( + "[Usage]", + &format!("ModelScope 今日用量未取到(余额照常返回):{}", error.message), + ); + (None, Value::Null) + } + }; + + let mut wallets = vec![json!({ + "type": "magicubes", + "displayName": "魔粒余额", + "balance": available, + })]; + if let Some(total) = total { + if let Some(object) = wallets.first_mut().and_then(Value::as_object_mut) { + object.insert("total".to_string(), Value::from(total)); + } + } + if let Some(object) = wallets.first_mut().and_then(Value::as_object_mut) { + object.insert("frozen".to_string(), Value::from(frozen)); + } + + let mut credits = vec![ + json!({ "name": "可用魔粒", "remain": available }), + json!({ "name": "冻结魔粒", "remain": frozen }), + ]; + // 今日已用的量纲是「次」(见模块头)—— 名字里写明,别让界面读成魔粒 + if let Some(used) = used_today { + credits.push(json!({ "name": "今日已用(次)", "remain": used, "daily": true })); + } + + let mut document = json!({ + "available": available, + "unit": "魔粒", + "wallets": wallets, + "raw": { + "balance": balance_payload, + // 没取到时为 null(如实标出,而不是缺键),见上面的取值处 + "rateLimit": rate_limit_raw, + }, + }); + if let Some(object) = document.as_object_mut() { + object.insert("credits".to_string(), Value::Array(credits)); + } + Ok(document) +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/checkin.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/checkin.rs new file mode 100644 index 00000000..222b60d5 --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/checkin.rs @@ -0,0 +1,114 @@ +//! ModelScope 每日签到:**读一次登录信息就完成**(2026-10-16 实测 + 插件源码对照)。 +//! +//! ── 上游是什么 ────────────────────────────────────────────── +//! 魔搭**没有独立的签到接口**(官方网页的「每日签到」按钮背后就是这条): +//! +//! ```text +//! GET {网页站}/api/v1/users/login/info Cookie: m_session_id= +//! → {"Code":200,"Success":true,"Data":{"Name":"…","NickName":"…", +//! "HavanaId":"…","Email":"…"}, …} +//! ``` +//! +//! **调用这个端点本身就触发当日的魔粒签到**(激活当日魔粒额度), +//! 返回体里给的是账号身份,而不是「签到成功」这四个字 —— +//! 这是本家签到与别家最大的不同,也是「看起来只是读了个用户信息」的原因。 +//! +//! ── 依据来自哪里(不是猜的)───────────────────────────────── +//! CPA 的 `modelscope-ratelimit` 插件(v2.4.10,`cmd/plugin/main.go` 的午夜签到段) +//! 就是按这个口径做的:遍历账号 → 调 `/api/v1/users/login/info` → +//! 把这次调用登记成当日签到(`store.RecordCheckIn(aid, now)`)。 +//! 本实现照同一条链路,只是把触发时机交给本项目的自动签到框架。 +//! +//! ── 幂等 ──────────────────────────────────────────────────── +//! 一天内调多次是安全的(插件同样每天只调一次,但没有「今天已签过」的拒绝返回)。 +//! 因此「今天已经触发过」**不算失败** —— 如实报成功并说明是重复调用, +//! 与 Loomy 的 `first-login` 同一口径。 +//! +//! ── 两个地区打各自的站 ────────────────────────────────────── +//! `region` 决定站点。打错了会拿到 `401 access forbidden`(实测:国内站的令牌打 +//! 国际站就是这个响应),这里把它如实翻成「令牌不属于该站点」而不是笼统的失败 —— +//! 那正是用户把两地账号加混时最需要看到的一句话。 +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本文件零 unwrap/expect/panic。 + +use serde_json::{json, Value}; + +use crate::server::core::account_store::AccountStore; +use crate::server::errors::GatewayError; +use crate::server::logging; + +use super::client; +use super::credentials; +use super::region::Region; + +/// 登录信息路径(相对网页站)。**它就是签到**,见模块头。 +pub const LOGIN_INFO_PATH: &str = "/api/v1/users/login/info"; + +/// ModelScope 账号的每日签到(自动签到框架的 claim)。 +/// +/// 返回 `{success, msg}` —— 与 WorkBuddy / 小浣熊 / AutoClaw / Qoder / Loomy +/// 的 claim 同一形状(`billing::checkin` 的汇总只认这两个字段)。 +pub async fn claim_daily_checkin( + region: Region, + store: &AccountStore, + account_id: &str, +) -> Result { + let record = store.modelscope_account_record(region, account_id); + if !account_id.is_empty() && record.is_none() { + return Err(GatewayError::with_status( + 404, + format!( + "ModelScope {}账号 {account_id} 不存在(请重新添加)", + region.label() + ), + )); + } + let credentials = credentials::from_record(region, record.as_ref())?; + + let payload = match client::site_get( + region, + LOGIN_INFO_PATH, + &credentials.token, + "每日签到", + ) + .await + { + Ok(payload) => payload, + // 401 原样透出(调用方按「刷新后重试」的既有处置走;本家没有续期, + // 最终会如实报「请重新粘贴令牌」) + Err(error) => return Err(error), + }; + + if !client::succeeded(&payload) { + let message = client::message_of(&payload); + let message = if message.trim().is_empty() { + format!("每日签到失败(上游 Code={})", client::code_of(&payload)) + } else { + format!("每日签到失败:{message}") + }; + logging::log("[Checkin]", &format!("⚠️ ModelScope {message}")); + return Ok(json!({ "success": false, "msg": message })); + } + + // 成功时上游给的是账号身份(不是「签到成功」)—— 把显示名播报出来, + // 用户一眼能确认「这条记录签的是哪个账号」(多账号场景下这是有用的信息) + let data = client::data_of(&payload); + let display = data + .get("NickName") + .or_else(|| data.get("Name")) + .or_else(|| data.get("nickname")) + .or_else(|| data.get("name")) + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty()) + .unwrap_or("") + .to_string(); + let msg = if display.is_empty() { + format!("魔搭{}每日签到已触发", region.label()) + } else { + format!("魔搭{}每日签到已触发({display})", region.label()) + }; + logging::log("[Checkin]", &format!("✅ {msg}")); + Ok(json!({ "success": true, "msg": msg })) +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/client.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/client.rs new file mode 100644 index 00000000..5fb0b473 --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/client.rs @@ -0,0 +1,223 @@ +//! ModelScope 两种出站请求的薄封装:网页站(cookie 鉴权)与推理域(Bearer)。 +//! +//! ── 为什么收在一处 ────────────────────────────────────────── +//! 四处消费者(`checkin` / `balance` / `models` / 账号添加时的探活)共用同一套 +//! 超时、错误翻译与「响应信封 → 人话」口径;各写一份会让「哪个码算令牌失效」 +//! 这类判据分叉。 +//! +//! ── 上游的**两种信封**(实测 2026-10-16,都出现在同一家的不同接口上)── +//! 这是本文件最需要注意的一处:魔搭自己的接口没统一大小写。 +//! +//! ```text +//! /api/v1/users/login/info {"Code":200,"Success":true,"Data":{…},"Message":"success"} +//! /api/v1/inference/rate-limit {"Code":200,"Success":true,"Data":{…}} +//! /openapi/v1/magicubes/balance {"success":true,"data":{…}} ← 全小写 +//! ``` +//! +//! 因此取值一律**两种写法都认**([`succeeded`] / [`data_of`] / [`message_of`]), +//! 不要只按一种写死 —— 那会让某一条链路把成功读成失败(或反之)。 +//! +//! ── 令牌失效的判据 ────────────────────────────────────────── +//! 网页站对无效令牌给的是 **HTTP 401 + `{"Code":10019901001,"Message":"access +//! forbidden"}`**(实测:拿国内站的 key 打国际站网页接口就是这个响应)。 +//! 也有接口用 HTTP 200 + `Success:false` 表达失败 —— 两条路都要认: +//! HTTP 401/403 → [`GatewayError`] 401,业务位为假 → 502 并把上游文案带出来。 +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本文件零 unwrap/expect/panic。 + +use serde_json::Value; + +use crate::server::core::auth_http::send_raw; +use crate::server::errors::GatewayError; + +use super::region::Region; + +/// 网页站接口的超时(余额 / 签到都是小请求,20 秒足够;别用 egress 默认的 600 秒 +/// SSE 超时,那会让一个挂住的查询把前端转圈转到天荒地老) +const REQUEST_TIMEOUT_MS: u64 = 20_000; + +/// 响应信封的**成功位**(大写 `Success` 与小写 `success` 都认,见模块头)。 +/// +/// 两种都没有时看 `Code`(缺失则视为成功 —— HTTP 已经 2xx 了,没有反证就照实报成功)。 +pub fn succeeded(payload: &Value) -> bool { + if let Some(flag) = payload.get("Success").and_then(Value::as_bool) { + return flag; + } + if let Some(flag) = payload.get("success").and_then(Value::as_bool) { + return flag; + } + match payload.get("Code").and_then(Value::as_i64) { + Some(code) => code == 200, + None => true, + } +} + +/// 响应信封里的**业务数据**(`Data` / `data` 两层都认)。 +pub fn data_of(payload: &Value) -> Value { + payload + .get("Data") + .or_else(|| payload.get("data")) + .cloned() + .unwrap_or(Value::Null) +} + +/// 响应信封里的**上游文案**(`Message` / `message` / `msg` 三种都认)。 +pub fn message_of(payload: &Value) -> String { + payload + .get("Message") + .or_else(|| payload.get("message")) + .or_else(|| payload.get("msg")) + .and_then(Value::as_str) + .map(str::trim) + .unwrap_or("") + .to_string() +} + +/// 响应信封里的业务码(`Code` / `code`;都没有时给 0)。 +pub fn code_of(payload: &Value) -> i64 { + payload + .get("Code") + .or_else(|| payload.get("code")) + .and_then(Value::as_i64) + .unwrap_or(0) +} + +/// 拼一个网页站 URL(`region` 决定站点,见 `region.rs`)。 +pub fn site_url(region: Region, path: &str) -> String { + format!("{}{path}", region.site_base_url()) +} + +/// 向**网页站**发一次带会话 cookie 的 GET。 +/// +/// 鉴权是 `Cookie: m_session_id=<令牌>`(实测口径,与插件 `msclient.go` 的 +/// `req.Header.Set("Cookie", "m_session_id="+sessionID)` 一致)。 +/// +/// 返回上游响应体;HTTP 层失败翻译成网关错误。**业务位不在本函数里判** —— +/// 调用方各自知道「这次调用的成功长什么样」(签到只看 HTTP,余额看业务位)。 +pub async fn site_get( + region: Region, + path: &str, + token: &str, + what: &str, +) -> Result { + if token.trim().is_empty() { + return Err(GatewayError::with_status( + 401, + "ModelScope 账号缺少令牌,无法查询", + )); + } + let url = site_url(region, path); + let headers = vec![("Cookie".to_string(), format!("m_session_id={token}"))]; + let response = send_raw("GET", &url, None, &headers, None, Some(REQUEST_TIMEOUT_MS)) + .await + .map_err(|error| { + if error.is_timeout() { + GatewayError::with_status(504, format!("{what}超时,请稍后重试")) + } else { + GatewayError::with_status(502, format!("{what}失败:{error}")) + } + })?; + if !response.ok { + if response.status == 401 || response.status == 403 { + return Err(GatewayError::with_status( + 401, + format!( + "{what}:ModelScope 令牌已失效或不属于该站点({}),请重新粘贴(HTTP {})", + region.site_base_url(), + response.status + ), + )); + } + return Err(GatewayError::with_status( + response.status as i32, + format!("{what}返回 HTTP {}", response.status), + )); + } + Ok(response.payload.unwrap_or(Value::Null)) +} + +/// 向**推理域**发一次带 Bearer 的 GET(目前只有模型目录用)。 +/// +/// 与 [`site_get`] 是**两个域**:网页站挂了会连签到一起失败,而推理域挂了只影响 +/// 模型目录 —— 分开成两个函数,才不会让排障时误判成同一处故障。 +pub async fn inference_get( + region: Region, + path: &str, + token: &str, + what: &str, +) -> Result { + if token.trim().is_empty() { + return Err(GatewayError::with_status( + 401, + "ModelScope 账号缺少令牌,无法查询", + )); + } + let url = format!("{}{path}", region.inference_base_url()); + let headers = vec![( + "Authorization".to_string(), + format!("Bearer {token}"), + )]; + let response = send_raw("GET", &url, None, &headers, None, Some(REQUEST_TIMEOUT_MS)) + .await + .map_err(|error| { + if error.is_timeout() { + GatewayError::with_status(504, format!("{what}超时,请稍后重试")) + } else { + GatewayError::with_status(502, format!("{what}失败:{error}")) + } + })?; + if !response.ok { + if response.status == 401 || response.status == 403 { + return Err(GatewayError::with_status( + 401, + format!("{what}:ModelScope 令牌已失效,请重新粘贴(HTTP {})", response.status), + )); + } + return Err(GatewayError::with_status( + response.status as i32, + format!("{what}返回 HTTP {}", response.status), + )); + } + Ok(response.payload.unwrap_or(Value::Null)) +} + +#[cfg(test)] +mod tests { + use super::{code_of, data_of, message_of, succeeded}; + use serde_json::json; + + /// 大写信封(login/info、rate-limit 的实测形态) + #[test] + fn the_uppercase_envelope_is_read() { + let payload = json!({"Code": 200, "Success": true, "Data": {"a": 1}, "Message": "success"}); + assert!(succeeded(&payload)); + assert_eq!(code_of(&payload), 200); + assert_eq!(data_of(&payload), json!({"a": 1})); + assert_eq!(message_of(&payload), "success"); + } + + /// 小写信封(magicubes/balance 的实测形态)—— 只认大写会让余额查询整条挂掉 + #[test] + fn the_lowercase_envelope_is_read() { + let payload = json!({"success": true, "data": {"total_balance": 108}}); + assert!(succeeded(&payload)); + assert_eq!(data_of(&payload), json!({"total_balance": 108})); + } + + /// 显式的失败位必须被认出来(否则签到会把上游的拒绝记成成功) + #[test] + fn an_explicit_failure_flag_is_not_a_success() { + assert!(!succeeded(&json!({"Success": false, "Message": "access forbidden"}))); + assert!(!succeeded(&json!({"success": false}))); + // 上游实测的错误码(`access forbidden`)—— 超过 i32 范围,用 i64 字面量 + assert!(!succeeded(&json!({"Code": 10019901001i64, "Success": false}))); + } + + /// `Code` 是唯一线索时(没有布尔位)按 200 判 + #[test] + fn the_code_is_the_last_resort() { + assert!(succeeded(&json!({"Code": 200}))); + assert!(!succeeded(&json!({"Code": 500}))); + } +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/credentials.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/credentials.rs new file mode 100644 index 00000000..85d81c03 --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/credentials.rs @@ -0,0 +1,148 @@ +//! ModelScope 凭证:**只有一条来源** —— 账号记录里的 `ms-` 令牌。 +//! +//! ── 为什么只要一个字段(实测依据,见 `region.rs` 的模块头)──────── +//! 同一个 `ms-...` 令牌既作 `Authorization: Bearer` 调推理,又作 +//! `Cookie: m_session_id=` 调网页站接口 —— 两条链路 2026-10-16 实测都是 200。 +//! 所以本模块比 CodeArts / OfficeAce 那两家(网关凭据 + 控制面临时凭据两层) +//! 薄得多:取一个令牌、判一次非空,就完了。 +//! +//! ── 没有续期(与 Loomy 同一处境)───────────────────────────── +//! 魔搭的 `ms-` 令牌是**长期有效**的(插件源码注释:「session 就是 api key 本身…… +//! 永不过期」;实测也没有任何 refresh / renew 接口)。因此: +//! - `supports_refresh()` 为 false —— 维护任务不问本家; +//! - 令牌失效(上游 401 / 业务码拒绝)只能重新去魔搭控制台复制一个; +//! - 没有「过期时刻」这个概念,账号页不显示有效期(前端 +//! `PROVIDER_FEATURES` 的 `expiry` 给空串)。 +//! +//! ── 备份字段 ──────────────────────────────────────────────── +//! `accessToken` 是本项目落盘名(`has_token()` / `access_token()` 一族认它); +//! 粘贴形态另外兼容 `apiKey` / `token` / `session` —— 用户从别处复制过来的 +//! JSON 里字段名并不统一,宽容读取比报错更实用。 +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本文件零 unwrap/expect/panic。 + +use serde_json::Value; + +use crate::server::errors::GatewayError; + +use super::region::Region; + +/// 一次转发 / 查询用的凭证快照。 +#[derive(Clone, Debug)] +pub struct ModelScopeCredentials { + /// 地区(决定打哪个推理域、哪个网页站) + pub region: Region, + /// 账号记录 id + pub id: String, + /// `ms-` 令牌(**两用**:Bearer 调推理、cookie 值调网页站) + pub token: String, + /// 魔搭侧用户 id(`HavanaId`;身份标识,也是账号 id 的种子) + pub user_id: String, + /// 展示名(记录的备注名) + pub name: String, +} + +impl ModelScopeCredentials { + /// 推理基址(`build_chat_request` 与目录刷新用;见 `Region::inference_base_url`) + pub fn inference_base_url(&self) -> &'static str { + self.region.inference_base_url() + } +} + +/// 从一条取值链里挑第一个非空字符串(记录可能被手工编辑过,宽容读取) +fn pick<'a>(record: &'a Value, keys: &[&str]) -> String { + for key in keys { + let value = record + .get(*key) + .and_then(Value::as_str) + .map(str::trim) + .unwrap_or(""); + if !value.is_empty() { + return value.to_string(); + } + } + String::new() +} + +/// 从**上传的 payload**里取令牌(添加路径专用:先取出来去探活,再交给落账号入口)。 +/// +/// 与 [`from_record`] 的取值链**逐字相同**(同一组候选键)—— 两处口径分叉的话, +/// 「能探活成功却落不进账号」或反之都会变成难查的静默问题。 +pub fn token_from_payload(payload: &Value) -> String { + pick(payload, &["accessToken", "apiKey", "token", "session"]) +} + +/// 从账号记录解析凭证(**唯一入口**;`record` 为 None 时报「没有可用账号」)。 +pub fn from_record( + region: Region, + record: Option<&Value>, +) -> Result { + let Some(record) = record else { + return Err(GatewayError::with_status( + 401, + format!( + "没有可用的 ModelScope {}账号:请在账号页粘贴 `ms-` 开头的令牌添加", + region.label() + ), + )); + }; + let token = pick(record, &["accessToken", "apiKey", "token", "session"]); + if token.is_empty() { + return Err(GatewayError::with_status( + 401, + "ModelScope 账号缺少令牌,请重新粘贴", + )); + } + Ok(ModelScopeCredentials { + region, + id: pick(record, &["id"]), + token, + user_id: pick(record, &["userId", "havanaId", "user_id"]), + name: pick(record, &["name"]), + }) +} + +/// 令牌尾 4 字符(公开形态与默认备注名用;与别家同一口径)。 +/// +/// 按 `char` 取而不按字节切:`ms-` 后面的内容是上游生成的 ASCII,但**粘贴形态** +/// 的输入框不做格式校验,一个带汉字的误粘贴就能让按字节回切落在多字节字符中间 +/// (release 是 `panic=abort`,一次 panic 带走整个进程)。 +pub fn token_tail(token: &str) -> String { + let chars: Vec = token.chars().collect(); + let start = chars.len().saturating_sub(4); + chars[start..].iter().collect() +} + +#[cfg(test)] +mod tests { + use super::{from_record, token_tail}; + use crate::server::core::providers::modelscope::region::Region; + use serde_json::json; + + #[test] + fn a_record_without_a_token_is_rejected() { + let record = json!({ "id": "modelscope-1", "name": "x" }); + assert!(from_record(Region::Cn, Some(&record)).is_err()); + assert!(from_record(Region::Cn, None).is_err()); + } + + /// 粘贴形态的字段名都认(`accessToken` 是本项目落盘名,其余是手工粘贴的常见写法) + #[test] + fn pasted_field_names_are_all_accepted() { + for key in ["accessToken", "apiKey", "token", "session"] { + let record = json!({ key: "ms-abc123" }); + let credentials = from_record(Region::Cn, Some(&record)) + .unwrap_or_else(|_| panic!("字段 {key} 应当被接受")); + assert_eq!(credentials.token, "ms-abc123"); + } + } + + #[test] + fn token_tail_survives_multibyte_input() { + assert_eq!(token_tail("ms-abcdefgh"), "efgh"); + // 多字节内容不得 panic(按字符取) + assert_eq!(token_tail("令牌令牌令牌"), "令牌令牌"); + assert_eq!(token_tail("ab"), "ab"); + } +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/errors.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/errors.rs new file mode 100644 index 00000000..11325980 --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/errors.rs @@ -0,0 +1,147 @@ +//! ModelScope 的**账号级失败判据**:三类不该被当成「速率窗口」的拒绝。 +//! +//! ── 为什么要单独一个文件 ──────────────────────────────────── +//! 魔搭把「账号条件不满足」和「速率窗口撞上」都用 429 / 403 表达,**只能靠文案 +//! 区分** —— 而两者的正确处置完全不同:前者在充值 / 完成验证之前**一直**不可用 +//! (按天数冷却),后者等一会儿就好(分钟级冷却)。 +//! +//! 判据来源:CPA 的 `modelscope-ratelimit` 插件(源码 +//! `D:\GitHub\modelscope-ratelimit`,`internal/ratelimit/apply.go` 的 +//! `IsInsufficientBalance` / `IsUnverifiedAccount`,两处都是线上实测得来), +//! 本文件照同一套文案子串做匹配。 +//! +//! ── 三类是什么(附上游真实报文)────────────────────────────── +//! ```text +//! ① 魔粒耗尽 429 {"error":{"message":"insufficient balance","request_id":"…"}} +//! 账号的魔粒用完了。充魔粒之前这把令牌确实不可用 —— 插件按「当日禁用」处理, +//! 跨过午夜再试一次(充了值就恢复)。 +//! ② 未验证邮箱 403 正文含 "email verification" / "verified accounts" / "/my/settings/account" +//! 账号没完成邮箱验证,魔粒推理接口直接拒绝服务,充魔粒也救不回来 —— +//! 唯一出路是去账号设置页完成验证。 +//! ``` +//! +//! ── 本网关怎么用这两条 ────────────────────────────────────── +//! 两类都 → `QuotaLimited` 且 `reset_at` 给**下一个北京零点**(`mark_account_limited` +//! 会据此把账号冷却到那个时刻,跨天自动解冻)。 +//! +//! ── 插件里还有一条,本网关**有意不照搬**(说明理由,免得将来被当成遗漏)── +//! 插件把 `503 + "model_not_ready"`(上游 vLLM 还在加载权重)当作**整家不可用**摘掉。 +//! 本网关**不做**:那件事与账号无关(本家每把令牌都会被同样拒绝),罚账号是错的 —— +//! 而 agent2api 也没有「按 provider 摘家」的接口,照搬只能退化成「随便找个账号记一笔 +//! 限额」。这里的默认处置是 `Fatal`(不罚账号,如实回给客户端、由客户端重试), +//! 那正是这条失败应有的语义。代价是编排层换号前会各撞一次,但 `model_not_ready` +//! 是**短暂**状态(权重加载完就好),撞几次的代价远小于把一个好账号记成限额。 +//! +//! ⚠️ **判据一律大小写不敏感的子串匹配,且只在「这次请求已经失败」的分支上调用** —— +//! 子串匹配本身不区分「上游报的错」与「模型自己生成的内容」,正常响应里若出现这些 +//! 字样会被误判(插件源码在 `IsInputContentInspectionFailed` 上方写了同一条警告)。 +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本文件零 unwrap/expect/panic。 + +/// 一整天(毫秒) +const DAY_MS: i64 = 24 * 60 * 60 * 1000; + +/// 北京时间的固定偏移(UTC+8)。 +/// +/// 用**固定偏移**而不是机器时区:网关可能跑在 UTC 容器里(`.3` 上的部署就是), +/// 而魔搭的一整套「当日」口径(签到、魔粒发放、日额度)都是按北京时间算的 —— +/// 「明天零点」必须是北京的那个。与 `codearts::welfare` 的同名常量同一处置。 +const DAY_ZONE_OFFSET_SECONDS: i32 = 8 * 3600; + +/// 一次失败是否意味着**账号魔粒耗尽**(429 + `insufficient balance`)。 +/// +/// 只看文案不看状态码也可以,但两样都看更稳(插件源码的 `IsInsufficientBalance` +/// 同样要求 429)—— 别的 4xx 里出现这串字的场合不存在,多一道闸门不损失什么。 +pub fn is_insufficient_balance(status: u16, message: &str) -> bool { + status == 429 && contains_ci(message, "insufficient balance") +} + +/// 一次失败是否意味着**账号未完成邮箱验证**(403 + 三选一的特征串)。 +/// +/// **必须同时看状态码与文案**(插件源码的注释写明了理由):403 还有别的权限语义, +/// 只看状态码会把无关失败误判成「账号未验证」,而那会让用户去查一个不存在的问题。 +pub fn is_unverified_account(status: u16, message: &str) -> bool { + if status != 403 { + return false; + } + ["email verification", "verified accounts", "/my/settings/account"] + .iter() + .any(|marker| contains_ci(message, marker)) +} + +/// 大小写不敏感的子串匹配(空值一律 false) +fn contains_ci(haystack: &str, needle: &str) -> bool { + if needle.is_empty() { + return false; + } + haystack.to_ascii_lowercase().contains(&needle.to_ascii_lowercase()) +} + +/// `now_ms` 之后最近的**北京时间零点**(毫秒时间戳,纯函数)。 +/// +/// 给「魔粒耗尽 / 账号未验证 ⇒ 冷却到明天」用:这两种状态在充值 / 完成验证之前 +/// 一直不可用,而魔搭的日口径是北京零点 —— 跨过那个点再试一次,既不会在当天 +/// 反复白撞,也不会把账号永久钉死(用户当天处理完之后,次日自动回来)。 +/// +/// 边界:恰好落在零点上时给**次日**零点(刚过零点,下一个重置点是一整天之后)。 +/// 用 `div_euclid` 而不是 `/`:负数时刻(1970 前)在 Rust 里默认向零取整会算错整天边界。 +pub fn next_day_boundary_ms(now_ms: i64) -> i64 { + let shifted = now_ms + i64::from(DAY_ZONE_OFFSET_SECONDS) * 1000; + let start_of_today = shifted.div_euclid(DAY_MS) * DAY_MS; + start_of_today + DAY_MS - i64::from(DAY_ZONE_OFFSET_SECONDS) * 1000 +} + +#[cfg(test)] +mod tests { + use super::{is_insufficient_balance, is_unverified_account, next_day_boundary_ms}; + + /// 上游真实报文里的文案(插件测试夹具逐字同款) + #[test] + fn the_measured_insufficient_balance_body_is_recognised() { + assert!(is_insufficient_balance(429, "insufficient balance")); + // 大小写与前后缀都不影响 + assert!(is_insufficient_balance(429, "Insufficient Balance")); + assert!(is_insufficient_balance( + 429, + "{\"error\":{\"message\":\"insufficient balance\",\"request_id\":\"x\"}}" + )); + // 必须是 429:别的状态码配这串字不是「魔粒耗尽」的语义 + assert!(!is_insufficient_balance(400, "insufficient balance")); + assert!(!is_insufficient_balance(429, "rate limit exceeded")); + } + + /// 403 的两种语义必须分开 —— 把「未验证邮箱」当成「令牌失效」会让用户 + /// 白白去重新粘贴一个本来就好好的令牌 + #[test] + fn the_unverified_account_markers_are_recognised() { + assert!(is_unverified_account( + 403, + "please complete email verification before using inference" + )); + assert!(is_unverified_account(403, "only verified accounts can call this API")); + assert!(is_unverified_account(403, "visit https://modelscope.cn/my/settings/account")); + // 裸 403(没有任何特征串)不是这一条 + assert!(!is_unverified_account(403, "access forbidden")); + assert!(!is_unverified_account(401, "email verification")); + } + + /// 北京零点:与 codearts 的同名函数同一口径(那里有自己的测试守着) + #[test] + fn the_day_boundary_is_the_coming_beijing_midnight() { + // 2026-10-16 12:00 北京 = 04:00 UTC → 时间戳 1792123200000 + let noon_cst = 1792123200000i64; + let boundary = next_day_boundary_ms(noon_cst); + // 距北京零点还有 12 小时 + assert_eq!(boundary - noon_cst, 12 * 60 * 60 * 1000); + // 再问一次已经落在零点上的时刻:给次日零点(不是同一刻) + assert_eq!(next_day_boundary_ms(boundary), boundary + 24 * 60 * 60 * 1000); + } + + /// 空串不得命中任何一条(`contains_ci` 的 needle 非空,但上游可能给出空 message) + #[test] + fn an_empty_message_matches_nothing() { + assert!(!is_insufficient_balance(429, "")); + assert!(!is_unverified_account(403, "")); + } +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/mod.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/mod.rs new file mode 100644 index 00000000..b1260cff --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/mod.rs @@ -0,0 +1,439 @@ +//! ModelScope(魔搭)适配器:**无状态 OpenAI 兼容转发 + 每日签到 + 魔粒余额**。 +//! +//! ── 上游长什么样(2026-10-16 实测;接口清单来自 CPA 的 `modelscope-ratelimit` +//! 插件源码,逐条 curl 复核)─────────────────────────────── +//! ```text +//! 推理 POST {推理域}/chat/completions Authorization: Bearer +//! 目录 GET {推理域}/models 同上 +//! 签到 GET {网页站}/api/v1/users/login/info Cookie: m_session_id=<令牌> +//! 魔粒余额 GET {网页站}/openapi/v1/magicubes/balance 同上 +//! 今日用量 GET {网页站}/api/v1/inference/rate-limit 同上 +//! ``` +//! 两个域(推理 / 网页站)各一套地址,两地(国内 / 国际)各一套账号 —— +//! 全部收在 [`region`] 里,别处不要再写域名。 +//! +//! 本家**无状态**(一次 HTTP 请求 = 一次回答,标准 OpenAI 协议),与 Loomy / +//! AutoClaw / OfficeAce 同构:`supports_chat` / `is_stateful` 走默认值, +//! 转发链只需 `build_chat_request`。 +//! +//! ── 三个实测事实决定了本家的形状 ───────────────────────────── +//! 1. **一个 `ms-` 令牌两用**(Bearer 调推理、cookie 值调网页站)⇒ 只要一个 +//! 凭证字段(见 `credentials.rs`); +//! 2. **两个站点的账号体系是分开的**(国内令牌打 `www.modelscope.ai` 得 +//! `401 access forbidden`)⇒ 地区必须是 provider 身份而不是账号上的字段 +//! (见 `region.rs`); +//! 3. **模型清单是账号相关的**(实测 36 条,不是全站几千个)⇒ 不编静态兜底 +//! 表(见 `models.rs`)。 +//! +//! ── 与别家的取舍(都写在各自模块头,这里给索引)────────────── +//! 1. **没有续期**(`supports_refresh = false`):`ms-` 令牌长期有效、上游没有 +//! refresh 接口,失效只能重新粘贴 —— 见 `credentials.rs`; +//! 2. **没有环境变量覆盖**:两个域名是官方硬编码的稳定值,加一层没人会用的 +//! 分支只是过度设计(KISS)—— 见 `region.rs`; +//! 3. **没有静态兜底模型清单**:编一份会让用户看到自己其实调不通的模型 —— +//! 见 `models.rs`。 +//! +//! ── 思考等级 ──────────────────────────────────────────────── +//! 上游是标准 OpenAI 兼容,`/v1/models` 不给能力位(实测只有 id),因此 +//! **不做** `reasoning_patch`:按 id 猜思考位会在两个方向上一起猜错 +//! (把非思考模型当思考模型、反之亦然)。要绑定的用户走模型规则层显式指定。 +//! +//! ── 子模块分工 ────────────────────────────────────────────── +//! ```text +//! region.rs 地区(两套域名 + 两条 provider 身份) +//! credentials.rs 账号记录 → 凭证快照(只有一个令牌字段) +//! client.rs 网页站(cookie)/ 推理域(Bearer)两条出站链路 + 两种响应信封 +//! models.rs GET {推理域}/models(10 分钟缓存 + 落盘缓存,两个地区两格) +//! probe.rs 添加账号时的令牌探活(换身份 + 顺带触发当日签到) +//! checkin.rs 每日签到(调登录信息接口即触发,幂等) +//! balance.rs 魔粒钱包 + 今日已用调用数 +//! ``` +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本目录零 unwrap/expect/panic。 + +pub mod balance; +pub mod checkin; +pub mod client; +pub mod credentials; +pub mod errors; +pub mod models; +pub mod probe; +pub mod region; + +use axum::http::HeaderMap; +use serde_json::Value; + +use crate::server::core::account_store::AccountStore; +use crate::server::core::providers::adapter::{ + ChatRequestPlan, ModelRefreshOutcome, ProviderAdapter, UpstreamErrorClass, +}; +use crate::server::core::providers::{content_block, ProviderKind}; +use crate::server::errors::GatewayError; +use crate::server::logging; + +pub use region::Region; + +/// 适配器实例:**按地区参数化**(一份实现、两个静态实例)。 +/// +/// 与 AutoClaw / ZCode / MonkeyCode 同一形态:地区不是账号字段而是 provider 身份, +/// 因此 `adapter_for` 按 kind 给出两个实例之一 —— 这样「这条账号打哪个站」 +/// 由身份保证,不需要在每一处转发/查询里再读一次账号上的地区。 +/// +/// **无状态**:它不持有任何数据 —— 凭证在账号存储、目录在 `models.rs` 的 +/// 进程级句柄(按 `region` 分格)。 +pub struct ModelScopeAdapter { + region: Region, +} + +/// 国内站适配器(`adapter_for(ProviderKind::Modelscope)` 返回它) +pub static MODELSCOPE_ADAPTER: ModelScopeAdapter = ModelScopeAdapter { region: Region::Cn }; + +/// 国际站适配器(`adapter_for(ProviderKind::ModelscopeIntl)` 返回它) +pub static MODELSCOPE_INTL_ADAPTER: ModelScopeAdapter = ModelScopeAdapter { region: Region::Intl }; + +/// 出站请求体:原样透传 + 把 `stream_options.include_usage` 置真。 +/// +/// 实测依据见 `build_chat_request` 的说明:不置真时魔搭的流式响应**永远不给 +/// 真值 usage**(每个 chunk 都带全零),网关的记账与客户端的 token 显示会一起归零。 +/// +/// 非对象 body(畸形请求)原样返回,不在这一层报错 —— 让上游去拒绝它。 +fn request_body(body: &Value) -> Value { + let mut payload = body.clone(); + let Some(object) = payload.as_object_mut() else { + return payload; + }; + // 保留客户端已设的其余 `stream_options` 键,只把 include_usage 置真 + let mut options = object + .get("stream_options") + .and_then(Value::as_object) + .cloned() + .unwrap_or_default(); + options.insert("include_usage".to_string(), Value::Bool(true)); + object.insert("stream_options".to_string(), Value::Object(options)); + payload +} + +impl ProviderAdapter for ModelScopeAdapter { + fn kind(&self) -> ProviderKind { + self.region.kind() + } + + /// 模型清单来自远程目录(`models.rs` 的进程缓存 + 落盘缓存,两个地区各一格) + fn list_models(&self) -> Vec { + models::list(self.region) + } + + /// 构造 `POST {推理域}/chat/completions`(标准 OpenAI 协议,body 原样透传 + /// **外加一个 `stream_options.include_usage`**,理由见下)。 + /// + /// ── 为什么必须注入 `include_usage`(2026-10-16 实测,一个会静默毁账的坑)── + /// 魔搭的流式响应是**非标准形态**:**每一个 chunk 都带一个 `usage` 对象**, + /// 而且**值全是 0**(标准 OpenAI 是除最后一块外都为 `null`)。真值只在末尾那个 + /// `choices: []` 的 usage-only 块里 —— **而且那一块只在请求显式带上 + /// `stream_options.include_usage: true` 时才发**。实测对照(同一模型同一提问): + /// + /// ```text + /// 不带 include_usage:最后一帧是 {"choices":[{"finish_reason":"stop"}], + /// "usage":{0,0,0}} ← 真值根本没出现 + /// 带 include_usage:{"choices":[], "usage":{62,32,94}} ← 真值在这一块 + /// ``` + /// + /// 后果链:本网关**恒以流式请求上游**(`upstream::payload` 的既有口径), + /// 客户端要非流式时再由聚合器把流折成完整响应(`aggregate.rs` 模块头)。 + /// 不注入这个开关时,聚合器读到的最后一个 usage 就是那串全零 —— + /// 于是**非流式请求的 usage 恒为 0**,请求日志、报表与前端 token 显示一起归零, + /// 而内容完全正常(这个故障只在统计上可见,排查时极难联想到「上游少发了一帧」)。 + /// 流式请求受影响较小(真值帧本来就没下发,客户端同样看到全零)。 + /// + /// 与 CodeArts(`codearts/chat.rs`)的处置一致:**总是请求 usage**。 + /// + /// ── 为什么**不**改别的(模型与流式意向都原样透传)──────────────── + /// 魔搭的 `/v1/models` 里混着非对话模型(生图、基座,见 `models.rs`), + /// 但「哪些模型支持什么」本网关没有任何可信依据去猜(按 id 猜会猜错), + /// 让上游自己判 —— 它给的 400 会被 `classify_error` 如实透出(不是 `Fatal`, + /// 会换账号)。模型 id 也原样发(`组织/模型名`,没有路由前缀那套)。 + /// + /// 客户端已经自己写了 `stream_options` 时**保留它的其余键**、只把 + /// `include_usage` 置真:那两个字段本就是标准 OpenAI 的同一个对象, + /// 覆盖整个对象会把用户显式设过的东西悄悄丢掉。 + fn build_chat_request( + &self, + account: &Value, + body: &Value, + _client_headers: &HeaderMap, + ) -> Result { + let token = account + .get("auth") + .and_then(|auth| auth.get("accessToken")) + .and_then(Value::as_str) + .unwrap_or("") + .trim() + .to_string(); + if token.is_empty() { + return Err(GatewayError::with_status( + 401, + "ModelScope 账号缺少令牌,无法转发(请重新粘贴 `ms-` 令牌)", + )); + } + let headers: Vec<(String, String)> = vec![ + // send_raw 会自动补 Content-Type;这里只加鉴权与 Accept + ("Authorization".to_string(), format!("Bearer {token}")), + ("Accept".to_string(), "text/event-stream".to_string()), + ]; + Ok(ChatRequestPlan::chat( + format!("{}/chat/completions", self.region.inference_base_url()), + headers, + request_body(body), + )) + } + + /// 上游错误分类。**顺序要紧**:两条「账号级」判据必须在裸 401/403 与裸 429 之前, + /// 否则它们会被归成「令牌失效」或「速率窗口」,各自的正确处置就都丢了。 + /// + /// 1. **魔粒耗尽**(429 + `insufficient balance`)→ `QuotaLimited` + + /// 冷却到下一个北京零点。它不是速率窗口:充值之前这把令牌**一直**不可用, + /// 按分钟冷却只会在当天反复白撞; + /// 2. **未验证邮箱**(403 + 特征串)→ 同样冷却到次日。⚠️ 漏了这条的后果最糟: + /// 403 会被当成「令牌失效」,界面提示用户去**重新粘贴一个本来就好好的令牌**, + /// 而真正要做的是去账号设置页完成邮箱验证 —— 一个把人引向错误方向的提示; + /// 3. **裸 401 / 403** → `TokenExpired`(本家无续期,刷新链会走到「重新粘贴」提示); + /// 4. **其余 429** → `QuotaLimited`,上游不给结构化恢复时间(`reset_at: None`, + /// 由 `mark_rate_limited` 给 10 分钟兜底); + /// 5. 其余 → 内容拦截分类(审核文案不罚账号)或原样透传。 + /// + /// 前两条的判据依据(上游真实报文)见 `errors.rs` 的模块头。 + fn classify_error(&self, status: u16, error_body: &Value) -> UpstreamErrorClass { + let raw = error_body + .get("message") + .or_else(|| error_body.get("Message")) + .and_then(Value::as_str) + .map(str::trim) + .filter(|text| !text.is_empty()) + .unwrap_or("上游错误"); + let upstream_code = error_body + .get("code") + .or_else(|| error_body.get("Code")) + .and_then(Value::as_i64); + let message = format!("上游返回 {status}: {raw}"); + let label = self.region.label(); + + if errors::is_insufficient_balance(status, raw) { + return UpstreamErrorClass::QuotaLimited { + reset_at: Some(errors::next_day_boundary_ms(logging::now_ms())), + message: format!( + "ModelScope {label}账号的魔粒已耗尽(上游:{raw}),将在下一个自然日\ + (北京时间 0 点)自动恢复;给账号充值后立即恢复" + ), + upstream_code, + status, + }; + } + if errors::is_unverified_account(status, raw) { + return UpstreamErrorClass::QuotaLimited { + reset_at: Some(errors::next_day_boundary_ms(logging::now_ms())), + message: format!( + "ModelScope {label}账号未完成邮箱验证,魔粒推理接口拒绝服务\ + (上游:{raw})——请到魔搭账号设置页完成邮箱验证,验证后次日自动恢复" + ), + upstream_code, + status, + }; + } + if status == 401 || status == 403 { + return UpstreamErrorClass::TokenExpired { message }; + } + if status == 429 { + return UpstreamErrorClass::QuotaLimited { + reset_at: None, + message, + upstream_code, + status, + }; + } + content_block::classify_or_fatal(status, error_body, message, upstream_code) + } + + /// 取可用令牌。本家**没有续期**:这里只做「记录里有没有令牌」的检查, + /// 服务端拒了就是 401,编排层会把它归成 `TokenExpired` 并在刷新失败后 + /// 如实报给客户端(「请重新粘贴令牌」)。 + fn ensure_access_token<'a>( + &'a self, + store: &'a AccountStore, + account_id: &'a str, + ) -> std::pin::Pin> + Send + 'a>> + { + let region = self.region; + Box::pin(async move { + let record = store.modelscope_account_record(region, account_id); + if !account_id.is_empty() && record.is_none() { + return Err(GatewayError::with_status( + 401, + format!( + "ModelScope {}账号 {account_id} 不存在(请重新添加)", + region.label() + ), + )); + } + let credentials = credentials::from_record(region, record.as_ref())?; + Ok(credentials.token) + }) + } + + /// 没有续期手段(上游没有 refresh 接口)——维护任务不问本家 + fn supports_refresh(&self) -> bool { + false + } + + /// 有远程目录(`GET {推理域}/models`,见 `models.rs`) + fn supports_model_refresh(&self) -> bool { + true + } + + /// 刷模型目录:用指定账号(空串 = 本家库里第一个可用账号)的令牌。 + /// + /// 「一个账号都没有」不是失败 —— 那是「用户还没添加账号」的正常状态, + /// 返回 `unchanged()`(与 Loomy / AutoClaw 在无登录态时的处置一致: + /// 脚本 / CI 不该看到一个红色失败)。 + fn refresh_models<'a>( + &'a self, + store: &'a AccountStore, + account_id: &'a str, + force: bool, + ) -> std::pin::Pin + Send + 'a>> { + let region = self.region; + Box::pin(async move { + let record = store.modelscope_account_record(region, account_id); + if record.is_none() { + if account_id.is_empty() { + crate::server::logging::verbose( + "[Models]", + &format!("ModelScope {}模型目录刷新跳过:尚未添加账号", region.label()), + ); + return ModelRefreshOutcome::unchanged(); + } + return ModelRefreshOutcome::failed("指定的账号不存在或不可用,请重新选择"); + } + let credentials = match credentials::from_record(region, record.as_ref()) { + Ok(credentials) => credentials, + Err(error) => return ModelRefreshOutcome::failed(error.message), + }; + models::refresh(region, &credentials.token, force).await + }) + } + + /// 有余额概念(魔粒钱包) + fn supports_usage(&self) -> bool { + true + } + + /// 查魔粒余额与今日已用调用数(见 `balance.rs`)。 + /// 401 由调用方走统一的「刷新后重试」链路 —— 本家刷新必失败,最终如实报重贴令牌。 + fn query_usage<'a>( + &'a self, + store: &'a AccountStore, + account_id: &'a str, + ) -> std::pin::Pin> + Send + 'a>> + { + let region = self.region; + Box::pin(async move { balance::query_usage(region, store, account_id).await }) + } +} + +#[cfg(test)] +mod tests { + use super::request_body; + use serde_json::json; + + /// 这是整个渠道最关键的一处注入:漏了它,非流式请求的 usage 恒为 0 + /// (实测依据见 `build_chat_request` 的说明) + #[test] + fn include_usage_is_injected() { + let body = json!({"model": "Qwen/Qwen3.8-Flash-Next", "stream": true}); + let out = request_body(&body); + assert_eq!( + out.pointer("/stream_options/include_usage").and_then(|v| v.as_bool()), + Some(true) + ); + // 其余字段原样保留 + assert_eq!(out.get("model").and_then(|v| v.as_str()), Some("Qwen/Qwen3.8-Flash-Next")); + assert_eq!(out.get("stream").and_then(|v| v.as_bool()), Some(true)); + // 调用方传进来的 body 不被就地改动(`build_chat_request` 拿的是借用) + assert!(body.get("stream_options").is_none()); + } + + /// 客户端自己写过 `stream_options` 时,只补 include_usage、不覆盖整个对象 + #[test] + fn other_stream_option_keys_survive() { + let out = request_body(&json!({"stream_options": {"custom_flag": 1}})); + assert_eq!(out.pointer("/stream_options/custom_flag").and_then(|v| v.as_i64()), Some(1)); + assert_eq!( + out.pointer("/stream_options/include_usage").and_then(|v| v.as_bool()), + Some(true) + ); + } + + /// 畸形 body(非对象)原样返回 —— 让上游去拒绝它,不在这一层报错 + #[test] + fn a_non_object_body_is_passed_through() { + assert_eq!(request_body(&json!(null)), json!(null)); + assert_eq!(request_body(&json!([1, 2])), json!([1, 2])); + } + + /// 错误分类的分支顺序:两条「账号级」判据必须先于裸 401/403 与裸 429 命中 + /// —— 顺序反了它们就会被归成「令牌失效」或「速率窗口」,各自的正确处置都丢。 + #[test] + fn classify_error_splits_account_level_failures_from_rate_windows() { + use crate::server::core::providers::adapter::{ProviderAdapter, UpstreamErrorClass}; + + let adapter = &super::MODELSCOPE_ADAPTER; + + // ① 魔粒耗尽(上游真实报文)→ 限流 + 冷却到明天(reset_at 必须给出来) + match adapter.classify_error(429, &json!({"message": "insufficient balance"})) { + UpstreamErrorClass::QuotaLimited { reset_at, status, .. } => { + assert_eq!(status, 429); + let reset_at = reset_at.expect("魔粒耗尽的冷却必须给到次日零点,不能是 None"); + assert!(reset_at > crate::server::logging::now_ms(), "冷却时刻必须在未来"); + } + other => panic!("魔粒耗尽应当归成限流,实际是 {other:?}"), + } + + // ② 未验证邮箱(上游真实文案的一段)→ 同样是次日冷却,**不是**「令牌失效」 + let unverified = json!({ + "message": "For account security, please complete your profile via email \ + verification. ModelScope Magicubes is only available to verified \ + accounts. Please refer to https://modelscope.cn/my/settings/account" + }); + match adapter.classify_error(403, &unverified) { + UpstreamErrorClass::QuotaLimited { reset_at, .. } => { + assert!(reset_at.is_some(), "未验证邮箱也要冷却到次日"); + } + other => panic!("未验证邮箱应当归成限流而不是令牌失效,实际是 {other:?}"), + } + + // ③ 裸 403(没有特征串)→ 令牌失效 + assert!(matches!( + adapter.classify_error(403, &json!({"message": "access forbidden"})), + UpstreamErrorClass::TokenExpired { .. } + )); + // 裸 401 同理 + assert!(matches!( + adapter.classify_error(401, &json!({"message": "unauthorized"})), + UpstreamErrorClass::TokenExpired { .. } + )); + + // ④ 普通 429(速率窗口)→ 限流且**不**给 reset_at(交给存储层 10 分钟兜底) + match adapter.classify_error(429, &json!({"message": "rate limit exceeded"})) { + UpstreamErrorClass::QuotaLimited { reset_at, .. } => { + assert!(reset_at.is_none(), "速率窗口不该被冷却到明天"); + } + other => panic!("速率窗口应当归成限流,实际是 {other:?}"), + } + + // ⑤ 「insufficient balance」配非 429 状态码时**不**走魔粒耗尽那条 + assert!(matches!( + adapter.classify_error(400, &json!({"message": "insufficient balance"})), + UpstreamErrorClass::Fatal { .. } | UpstreamErrorClass::ContentBlocked { .. } + )); + } +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/models.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/models.rs new file mode 100644 index 00000000..c77ae80c --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/models.rs @@ -0,0 +1,222 @@ +//! ModelScope 模型目录:`GET {推理域}/models`(标准 OpenAI 形态)+ 持久化缓存。 +//! +//! ── 上游形态(2026-10-16 真实账号实测)────────────────────── +//! ```text +//! GET https://api-inference.modelscope.cn/v1/models Authorization: Bearer +//! → {"object":"list","data":[{"id":"Qwen/Qwen3.8-Flash-Next", +//! "object":"","owned_by":"system","created":1789…}, …]} +//! ``` +//! **只有 `id`**:没有 `name`、没有 `capabilities`、没有上下文长度 —— +//! 与 Loomy / MonkeyCode 那种带能力位的目录不同,这里能如实给出的只有 id 本身。 +//! +//! ── 清单是**账号相关**的(这是不做静态兜底表的理由)──────────── +//! 实测同一个令牌拉到的是 **36 条**,而不是魔搭全站的几千个模型 —— +//! 它给的是「这个账号在 API-Inference 上能调的模型」。 +//! 换句话说清单随账号变(免费额度、实名状态、地区都可能影响它), +//! 因此**编一份静态兜底表是有害的**:用户会看到一批自己其实调不通的模型, +//! 而目录的用途正是回答「我能用什么」。拉不到就如实报失败、保留旧清单 +//! —— 与 `loomy::models` 同一取舍。 +//! +//! ── 清单里混着非对话模型(照实列出,不筛)──────────────────── +//! 实测 36 条里含生图(`Qwen/Qwen-Image-Edit`)、基座(`PaddlePaddle/ERNIE-4.5-*-PT`) +//! 等并非 chat 用途的条目。上游给的就是它的清单,这里**不按 id 猜用途去过滤** —— +//! 猜错会把能用的模型藏起来(用户报「xxx 明明能用却不在列表里」比多几条调不通的 +//! 更难查)。真调不通时,`classify_error` 会把上游的 400 如实透出。 +//! +//! ── 两个地区两套缓存(拆成两个 provider 的核心收益之一)──────── +//! 缓存槽按 scope 分开(`catalog_cache::SCOPE_MODELSCOPE_CN` / `_INTL`), +//! 两个站的清单互不覆盖 —— 这正是当初把地区拆成两家 provider 要解决的问题 +//! (见 `region.rs` 的模块头)。 +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本文件零 unwrap/expect/panic。 + +use std::sync::{Mutex, OnceLock}; + +use serde_json::{json, Value}; + +use crate::server::core::providers::adapter::ModelRefreshOutcome; +use crate::server::core::providers::catalog_cache; + +use super::client; +use super::region::Region; + +/// 模型列表路径(相对推理域) +pub const MODELS_PATH: &str = "/models"; + +/// 自动路径的缓存 TTL(与各家同档) +const TTL_MS: i64 = 10 * 60 * 1000; + +/// 进程内缓存(首次访问时从落盘缓存读回) +struct CatalogState { + models: Vec, + fetched_at: i64, +} + +/// 两个地区各一个槽(`OnceLock` 初始化,避免在 `static` 里做分配) +static STATE_CN: OnceLock>> = OnceLock::new(); +static STATE_INTL: OnceLock>> = OnceLock::new(); + +/// 本地区对应的落盘缓存 scope +fn scope_of(region: Region) -> &'static str { + match region { + Region::Cn => catalog_cache::SCOPE_MODELSCOPE_CN, + Region::Intl => catalog_cache::SCOPE_MODELSCOPE_INTL, + } +} + +/// 取本地区的状态句柄(毒锁按「上一个持有者 panic 过、数据可能半更新」处理: +/// 本项目的取值是「继续用」,因为这份缓存是可重建的展示数据,不值得让进程挂掉) +fn state(region: Region) -> &'static Mutex> { + match region { + Region::Cn => STATE_CN.get_or_init(|| Mutex::new(None)), + Region::Intl => STATE_INTL.get_or_init(|| Mutex::new(None)), + } +} + +/// 在锁内执行一段取值,并在首次访问时把落盘缓存装回内存 +fn with_state(region: Region, f: impl FnOnce(&mut Option) -> R) -> R { + let mutex = state(region); + let mut guard = mutex.lock().unwrap_or_else(|poisoned| poisoned.into_inner()); + if guard.is_none() { + if let Some(cached) = catalog_cache::load(scope_of(region)) { + *guard = Some(CatalogState { + models: cached.models, + fetched_at: cached.fetched_at, + }); + } + } + f(&mut guard) +} + +/// 把一个 OpenAI 目录条目映射成聚合层认的形态 +/// (键名对照 `core/models/shape.rs::list_item`:`id` / `name` / 能力位)。 +/// +/// 上游只给 `id`(实测),所以 `name` 就用 id 本身:魔搭的 id 是 +/// `组织/模型名`(`Qwen/Qwen3.8-Flash-Next`),它本身就是可读的展示名, +/// 拆掉组织段反而会让同名模型(不同组织的同名条目)在界面上无法区分。 +/// +/// 工具位按 OpenAI 兼容网关的既有能力给 true(照 `autoclaw::models` 的处置: +/// 缺失时保守回落)。**思考位不给** —— 上游没有能力位、按 id 猜会猜错 +/// (实测同一个模型既可能走 `reasoning_content` 也可能直接答), +/// 交给模型规则层由用户显式绑定更诚实。 +fn map_entry(row: &Value) -> Option { + let id = row + .get("id") + .and_then(Value::as_str) + .map(str::trim) + .filter(|value| !value.is_empty())?; + Some(json!({ + "id": id, + "name": id, + "supportsToolCall": true, + })) +} + +/// 解析 `/models` 响应(OpenAI `{data:[...]}` 或裸数组) +pub fn parse_models(payload: &Value) -> Vec { + let rows = payload + .get("data") + .and_then(Value::as_array) + .or_else(|| payload.as_array()) + .cloned() + .unwrap_or_default(); + rows.iter().filter_map(map_entry).collect() +} + +/// 本地区当前的模型清单(内存 → 落盘缓存;都没有时为空,由刷新路径填) +pub fn list(region: Region) -> Vec { + with_state(region, |slot| { + slot.as_ref().map(|state| state.models.clone()).unwrap_or_default() + }) +} + +/// 最近一次成功刷新的时刻(毫秒;没刷过为 0)—— 界面「更新日期」列读它 +pub fn last_refreshed_at(region: Region) -> i64 { + with_state(region, |slot| slot.as_ref().map(|state| state.fetched_at).unwrap_or(0)) +} + +/// 这份清单是否来自**远程拉取**(`catalog::refresh_meta` 的「来源」列判据)。 +/// 本家没有内置兜底清单:有内容就等于远程拉到过。 +pub fn remote_refreshed(region: Region) -> bool { + with_state(region, |slot| { + slot.as_ref().map(|state| !state.models.is_empty()).unwrap_or(false) + }) +} + +/// 拉一次模型目录并落地(内存 + 持久化缓存)。 +/// +/// `force = false`(自动路径)时 10 分钟 TTL 内早退为 `unchanged()`; +/// `force = true`(用户手动刷新)真打上游。 +pub async fn refresh(region: Region, token: &str, force: bool) -> ModelRefreshOutcome { + let now = crate::server::logging::now_ms(); + if !force { + let fresh = with_state(region, |slot| { + slot.as_ref() + .map(|state| !state.models.is_empty() && now - state.fetched_at < TTL_MS) + .unwrap_or(false) + }); + if fresh { + return ModelRefreshOutcome::unchanged(); + } + } + let payload = match client::inference_get(region, MODELS_PATH, token, "模型目录查询").await { + Ok(payload) => payload, + Err(error) => return ModelRefreshOutcome::failed(error.message), + }; + let models = parse_models(&payload); + if models.is_empty() { + return ModelRefreshOutcome::failed("ModelScope 模型目录为空或格式不认识(保留现有清单)"); + } + let count = models.len(); + with_state(region, |slot| { + *slot = Some(CatalogState { + models: models.clone(), + fetched_at: now, + }); + }); + catalog_cache::save(scope_of(region), &models, now); + ModelRefreshOutcome::refreshed(count) +} + +#[cfg(test)] +mod tests { + use super::{map_entry, parse_models}; + use serde_json::json; + + /// 上游的实测形态(只有 id)必须能过 + #[test] + fn the_measured_entry_shape_is_mapped() { + let item = map_entry(&json!({ + "id": "Qwen/Qwen3.8-Flash-Next", + "object": "", + "owned_by": "system", + "created": 1789 + })) + .unwrap_or_else(|| panic!("实测条目应当被映射")); + assert_eq!(item.get("id").and_then(|v| v.as_str()), Some("Qwen/Qwen3.8-Flash-Next")); + // 展示名保留组织段(同名不同组织的条目靠它区分) + assert_eq!(item.get("name").and_then(|v| v.as_str()), Some("Qwen/Qwen3.8-Flash-Next")); + assert_eq!(item.get("supportsToolCall").and_then(|v| v.as_bool()), Some(true)); + // 不给思考位:上游没有这个信息,按 id 猜会猜错 + assert!(item.get("supportsReasoning").is_none()); + } + + #[test] + fn entries_without_an_id_are_dropped() { + assert!(map_entry(&json!({"object": "model"})).is_none()); + assert!(map_entry(&json!({"id": " "})).is_none()); + assert!(map_entry(&json!({"id": 42})).is_none()); + } + + /// `{data:[…]}` 与裸数组两种形态都认(OpenAI 兼容实现的常见分歧) + #[test] + fn both_envelope_shapes_are_parsed() { + let wrapped = json!({"object": "list", "data": [{"id": "a"}, {"id": "b"}]}); + let bare = json!([{"id": "a"}, {"id": "b"}]); + assert_eq!(parse_models(&wrapped).len(), 2); + assert_eq!(parse_models(&bare).len(), 2); + assert!(parse_models(&json!({"data": []})).is_empty()); + assert!(parse_models(&json!(null)).is_empty()); + } +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/probe.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/probe.rs new file mode 100644 index 00000000..fa8ed13e --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/probe.rs @@ -0,0 +1,165 @@ +//! 添加账号时的令牌探活:**一次调用拿两样东西** —— 令牌是否可用、账号是谁。 +//! +//! ── 为什么添加要出网(与本仓库多数家的「粘贴即落盘」不同)──────── +//! 魔搭的令牌**不携带任何可解析的身份**(它是一串不透明的 `ms-…`,不是 JWT)。 +//! 不出网的话只能拿令牌尾号当账号 id —— 同一个账号换一次令牌就会变成**两条记录**, +//! 用户看到「我明明只有一个魔搭账号,怎么越加越多」。 +//! 因此这里照 Qoder / OfficeAce 的既有处置:添加前先交换一次身份,用上游给的 +//! 稳定 id(`HavanaId`)做记录 id。 +//! +//! 顺带的两个好处: +//! 1. 令牌无效 / **不属于该站点**(国内令牌打国际站会 401 `access forbidden`) +//! 在添加的那一刻就说清楚,而不是等第一次转发才失败; +//! 2. 这次调用**同时触发当日签到**(见 `checkin.rs` 的模块头)—— +//! 添加账号的人当天就把魔粒拿到手。 +//! +//! ── 代价要说清 ────────────────────────────────────────────── +//! 探活失败(网络抖动、上游维护)会导致**添加不成功**。这是刻意的:本家 +//! 没有第二种「先落盘、以后再验证」的路径,半个账号(有记录、身份是猜的) +//! 比一条明确的失败更难收拾。错误文案会把上游原话带出来,用户知道该重试。 +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本文件零 unwrap/expect/panic。 + +use serde_json::Value; + +use crate::server::errors::GatewayError; + +use super::checkin::LOGIN_INFO_PATH; +use super::client; +use super::region::Region; + +/// 上游给的账号身份(添加账号时用来生成 id 与默认备注名)。 +#[derive(Clone, Debug)] +pub struct Identity { + /// 稳定身份(`HavanaId`);拿不到时为空串 + pub user_id: String, + /// 展示名(`NickName` → `Name`);拿不到时为空串 + pub display_name: String, +} + +impl Identity { + /// 有没有拿到稳定身份(拿不到时 `add_modelscope_account` 会拒绝这条添加) + pub fn has_user_id(&self) -> bool { + !self.user_id.trim().is_empty() + } +} + +/// 从登录信息响应里读出身份。 +/// +/// 大写(`HavanaId` / `NickName` / `Name`)与小写变体都认 —— 上游自己没统一 +/// 大小写(见 `client.rs` 的模块头),多认一种写法不会出错,少认一种会让 +/// 「加上但身份为空」变成一个难查的静默问题。 +pub fn parse_identity(payload: &Value) -> Identity { + let data = client::data_of(payload); + let pick = |keys: &[&str]| -> String { + for key in keys { + let value = data + .get(*key) + .and_then(Value::as_str) + .map(str::trim) + .unwrap_or(""); + if !value.is_empty() { + return value.to_string(); + } + } + String::new() + }; + // `HavanaId` 实测是**字符串**(`"2220378210908"`),但数字形态也容忍 + let user_id = { + let from_str = pick(&["HavanaId", "havanaId", "havana_id", "userId", "user_id"]); + if !from_str.is_empty() { + from_str + } else { + data.get("HavanaId") + .and_then(Value::as_i64) + .map(|value| value.to_string()) + .unwrap_or_default() + } + }; + Identity { + user_id, + display_name: pick(&["NickName", "FirstName", "Name", "nickname", "name"]), + } +} + +/// 用令牌探一次身份(同时也是当日签到,见模块头)。 +pub async fn identify(region: Region, token: &str) -> Result { + let payload = client::site_get(region, LOGIN_INFO_PATH, token, "令牌校验").await?; + if !client::succeeded(&payload) { + let message = client::message_of(&payload); + return Err(GatewayError::with_status( + 400, + if message.trim().is_empty() { + format!("ModelScope 令牌校验失败(上游 Code={})", client::code_of(&payload)) + } else { + format!("ModelScope 令牌校验失败:{message}") + }, + )); + } + let identity = parse_identity(&payload); + if !identity.has_user_id() { + // 读不到身份时不放行:拿令牌尾号当 id 会让同一账号越加越多(见模块头), + // 宁可让用户看到一条明确的失败 + return Err(GatewayError::with_status( + 400, + format!( + "ModelScope 令牌校验通过但读不到账号身份(HavanaId)——可能上游改了响应形态,\ + 请把这次响应反馈给开发者;{}站点的令牌才有效", + region.label() + ), + )); + } + Ok(identity) +} + +#[cfg(test)] +mod tests { + use super::parse_identity; + use serde_json::json; + + /// 实测形态(2026-10-16 国内站) + #[test] + fn the_measured_shape_is_parsed() { + let payload = json!({ + "Code": 200, + "Success": true, + "Data": { + "Avatar": "https://img.alicdn.com/…", + "Email": "someone@example.com", + "HavanaId": "2220378210908", + "Name": "taotao0918", + "NickName": "taotao0918", + "is_real_name": true + } + }); + let identity = parse_identity(&payload); + assert_eq!(identity.user_id, "2220378210908"); + // 昵称优先于登录名 + assert_eq!(identity.display_name, "taotao0918"); + assert!(identity.has_user_id()); + } + + /// `HavanaId` 是数字形态时也要读出来 + #[test] + fn a_numeric_havana_id_is_accepted() { + let payload = json!({"Data": {"HavanaId": 2220378210908i64, "Name": "x"}}); + assert_eq!(parse_identity(&payload).user_id, "2220378210908"); + } + + /// 只有登录名、没有昵称时回落到登录名 + #[test] + fn the_login_name_is_the_fallback_display_name() { + let payload = json!({"Data": {"HavanaId": "1", "Name": "fallback"}}); + assert_eq!(parse_identity(&payload).display_name, "fallback"); + } + + /// 什么都没有时是「无身份」——调用方据此拒绝添加 + #[test] + fn a_payload_without_identity_reports_none() { + let payload = json!({"Code": 200, "Success": true, "Data": {}}); + let identity = parse_identity(&payload); + assert!(!identity.has_user_id()); + assert!(identity.display_name.is_empty()); + } +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/region.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/region.rs new file mode 100644 index 00000000..7e08307d --- /dev/null +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/modelscope/region.rs @@ -0,0 +1,179 @@ +//! ModelScope(魔搭)的**地区**(国内站 / 国际站):两套域名与两条 provider 身份。 +//! +//! ── 上游长什么样(2026-10-16 实测,来源:CPA 的 modelscope-ratelimit 插件 +//! 源码 `D:\GitHub\modelscope-ratelimit` + 真实账号 curl 验证)────── +//! 魔搭是**两个站点各一套账号体系**,同一份协议、不同的域: +//! +//! ```text +//! 推理(OpenAI 兼容) 网页站(身份 / 魔粒 / 签到) +//! 国内 https://api-inference.modelscope.cn/v1 https://modelscope.cn +//! 国际 https://api-inference.modelscope.ai/v1 https://www.modelscope.ai +//! ``` +//! +//! ── 一处**实测确认**的关键事实:一个 `ms-` key 两用 ──────────── +//! 同一个 `ms-...` 令牌既作 `Authorization: Bearer` 调推理,又作 +//! `Cookie: m_session_id=` 调网页站的身份 / 魔粒接口 —— 两条链路都实测 200。 +//! 插件源码的注释也这么写(「session 就是 api key 本身……永不过期」)。 +//! 因此本家**只有一个凭证字段**,不需要像 CodeArts / OfficeAce 那样分两层。 +//! +//! ── 另一处实测确认:**两个站点的账号体系是分开的** ────────────── +//! 用国内站的 key 打 `https://www.modelscope.ai/api/v1/users/login/info` +//! 得到 `401 {"Code":10019901001,"Message":"access forbidden"}`;反过来同理。 +//! 而**推理端点两地都能用同一个 key 打通**(模型网关的 key 是账号级的、不分站)。 +//! 所以「地区」在本家不是可有可无的标签:**签到与魔粒必须打对站点**, +//! 打错了拿到的是一个必然失败的结果。 +//! +//! ── 为什么是两个 provider 而不是「一家的一个选项」(与 AutoClaw / ZCode 同一思路)── +//! 地区做成「账号上的一个字段」的后果与本仓库已修过数次的那类缺陷相同: +//! 地区成了**账号的属性**,界面上混在一起、账号记录也无法按站隔离; +//! 更要紧的是模型目录只有一份(单槽缓存 + 单条刷新排期),两个站的清单会互相覆盖。 +//! 拆成两个 provider 后各家有独立的账号、清单、启停与映射, +//! 界面上各占一个分组、在添加弹窗里相邻。 +//! +//! ── provider id 的取值 ────────────────────────────────────── +//! 本家是**全新接入**(没有任何存量账号),所以两个 id 都是新名字、 +//! 不需要像 AutoClaw 那样为存量数据保留裸 id: +//! `modelscope`(国内)与 `modelscope-intl`(国际)。 +//! +//! ── 为什么没有环境变量覆盖(与本仓库其余几家不同)────────────── +//! 别家做覆盖是历史原因(域名的多来源、代理调试、客户端内置值可被官方换掉)。 +//! 魔搭这两个域名是**硬编码在官方 SDK / 客户端里的**、2026-10 实测稳定, +//! 为它们加一层 `MODELSCOPE_*_BASE_URL` 只是多一条没人会用的分支(KISS)。 +//! 真要换域名时,改本文件的两处常量比找环境变量更直接。 +//! +//! ── 硬约束 ────────────────────────────────────────────────── +//! release 是 `panic=abort`:本文件零 unwrap/expect/panic。 + +use crate::server::core::providers::{kind_id, ProviderKind}; + +/// ModelScope 的地区。 +/// +/// 顺序 = 注册表顺序(国内版在前):`ALL` 的遍历顺序决定模型目录合并时同名模型 +/// 先归谁家、以及界面上两家的先后。**国内版在前**(用户直觉里「魔搭就是国内那个站」, +/// 与 MonkeyCode / ZCode 同一处置)。 +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)] +pub enum Region { + /// 国内站(`modelscope.cn`;provider id `modelscope`) + #[default] + Cn, + /// 国际站(`www.modelscope.ai`;provider id `modelscope-intl`) + Intl, +} + +impl Region { + /// 两个地区(注册表顺序:国内版在前) + pub const ALL: [Region; 2] = [Region::Cn, Region::Intl]; + + /// 本地区对应哪个 provider kind(地区 → 身份的**唯一**映射) + pub fn kind(self) -> ProviderKind { + match self { + Self::Cn => ProviderKind::Modelscope, + Self::Intl => ProviderKind::ModelscopeIntl, + } + } + + /// 本地区的 provider id(`"modelscope"` / `"modelscope-intl"`) + pub fn provider_id(self) -> &'static str { + kind_id(self.kind()) + } + + /// provider id → 地区(本家之外的 id 返回 None) + pub fn from_provider_id(provider_id: &str) -> Option { + Self::ALL + .into_iter() + .find(|region| region.provider_id() == provider_id) + } + + /// 这个 kind 是不是本家(两家都算)—— 判据只在这里写一份 + pub fn from_kind(kind: ProviderKind) -> Option { + Self::ALL.into_iter().find(|region| region.kind() == kind) + } + + /// 展示名(界面上跟在 `ModelScope` 后面的那一段) + pub fn label(self) -> &'static str { + match self { + Self::Cn => "国内版", + Self::Intl => "国际版", + } + } + + /// 推理基址(**含** `api-inference` 主机与尾部的 `/v1`)。 + /// + /// `build_chat_request` 在它后面拼 `/chat/completions`, + /// `models.rs` 在它后面拼 `/models` —— 两处都不要再写域名。 + pub fn inference_base_url(self) -> &'static str { + match self { + Self::Cn => "https://api-inference.modelscope.cn/v1", + Self::Intl => "https://api-inference.modelscope.ai/v1", + } + } + + /// 网页站基址(身份 / 魔粒余额 / 今日用量 / 签到都在这个域下,**不带尾部斜杠**)。 + /// + /// 国际站用 `www.` 前缀(实测 `modelscope.ai` 的接口挂在 `www` 主机上, + /// 与插件源码的 `siteBaseFromURL` 同款判定)。 + pub fn site_base_url(self) -> &'static str { + match self { + Self::Cn => "https://modelscope.cn", + Self::Intl => "https://www.modelscope.ai", + } + } + + /// 本地区账号记录 id 的**前缀**(id 生成用)。 + /// + /// 两地带前缀的理由与 AutoClaw 国际版那一节相同:两站的身份 id 空间互不相通, + /// 但**同一个人在两地的 `HavanaId` 完全可能相同**(各自注册,服务端 id 生成 + /// 规则同形就会撞)。撞了的话存储层现有的跨 provider 撞 id 保护会直接报错拒绝, + /// 「两地账号并存」就变得不可能 —— 而并存正是本功能的意义之一。 + /// + /// 本家没有存量账号,所以国内版**不必**保持裸 id,两家都带前缀(Cline 同款)。 + pub fn account_id_prefix(self) -> &'static str { + match self { + Self::Cn => "modelscope-", + Self::Intl => "modelscope-intl-", + } + } +} + +#[cfg(test)] +mod tests { + use super::Region; + + /// 两条身份必须与注册表里的 id 逐字对上 —— 对不上的话 `adapter_for` 会返回 + /// 错误的适配器实例(转发打到另一个站点),而这是编译期看不出来的。 + #[test] + fn region_ids_match_the_expected_literals() { + assert_eq!(Region::Cn.provider_id(), "modelscope"); + assert_eq!(Region::Intl.provider_id(), "modelscope-intl"); + } + + /// 互查是双射:id → region → id 必须回到原值 + #[test] + fn region_lookup_round_trips() { + for region in Region::ALL { + assert_eq!(Region::from_provider_id(region.provider_id()), Some(region)); + assert_eq!(Region::from_kind(region.kind()), Some(region)); + } + assert_eq!(Region::from_provider_id("loomy"), None); + } + + /// 两个站点的域名必须**不同** —— 写重了会让两地账号实际打到同一个站, + /// 是「看起来支持两地区、实际只有一家」的静默失效。 + #[test] + fn the_two_regions_do_not_share_a_host() { + assert_ne!(Region::Cn.inference_base_url(), Region::Intl.inference_base_url()); + assert_ne!(Region::Cn.site_base_url(), Region::Intl.site_base_url()); + } + + /// 账号 id 前缀必须**不同** —— 相同的话同一身份在两地的记录会生成同一个 id, + /// 第二个添加的账号会撞上存储层的跨 provider 保护而加不进来。 + /// + /// 注意这里**不**断言「互不为前缀」:`modelscope-intl-` 本就以 `modelscope-` + /// 开头(Cline 的两个池同款)。判「是不是 ModelScope 系」一律走 + /// `Region::from_provider_id`,绝不要用 `starts_with` 前缀判据 —— 那会把国际版 + /// 误算进国内版。 + #[test] + fn account_id_prefixes_are_distinct() { + assert_ne!(Region::Cn.account_id_prefix(), Region::Intl.account_id_prefix()); + } +} \ No newline at end of file diff --git a/desktop-tauri/src-tauri/server/src/server/core/upstream/provider_loop.rs b/desktop-tauri/src-tauri/server/src/server/core/upstream/provider_loop.rs index 1a5f88ff..4af136cd 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/upstream/provider_loop.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/upstream/provider_loop.rs @@ -95,7 +95,8 @@ use super::request::{read_upstream_error, send_chat_request, TransportRequest}; use super::usage::LogPhase; use super::{ account_display, account_label, cancellation, connections::ConnectionGuard, describe_proxy, - refusal, reset_hint, rotate, ForwardOutcome, InFlightGuard, RouteTarget, UpstreamService, + format_reset_text, refusal, reset_hint, rotate, ForwardOutcome, InFlightGuard, RouteTarget, + UpstreamService, MAX_ROUTE_ATTEMPTS, }; @@ -1390,8 +1391,28 @@ async fn attempt_queue( continue 'accounts; } None => { + // 所有候选都在冷却 / 禁用里 —— 把**最早的恢复时刻** + // 带进文案:客户端(Claude Code / Codex 等会读这条 + // 文案的)才能做合法的退避等待,而不是立刻重试再撞 + // 一次同样的墙。取不到(缓存里没有未来时刻)时退回 + // 原句,逐字与改造前相同。 + let earliest_reset = rotate::earliest_limit_reset_at( + service, + provider_ids, + &cooldown_keys, + ); + let wait_hint = if earliest_reset > 0 { + let text = format_reset_text(earliest_reset as f64); + if text.is_empty() { + String::new() + } else { + format!(",最早 {text} 恢复") + } + } else { + String::new() + }; let message = format!( - "{}(所有候选账号对模型 {model} 均已限额或禁用)", + "{}(所有候选账号对模型 {model} 均已限额或禁用{wait_hint})", failure.error.message ); rotate::report_limit_event( diff --git a/desktop-tauri/src-tauri/server/src/server/core/upstream/rotate.rs b/desktop-tauri/src-tauri/server/src/server/core/upstream/rotate.rs index f0dc5695..f3d59ae5 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/upstream/rotate.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/upstream/rotate.rs @@ -479,6 +479,61 @@ pub(super) fn account_limit_reset_at(service: &UpstreamService, account_id: &str .unwrap_or(0) } +/// 候选中**最早**的限额恢复时间戳(毫秒;一个都没有时 0)。 +/// +/// ── 用途:把「还要等多久」告诉客户端 ──────────────────────── +/// 所有候选账号都被限流时,编排层给客户端的错误文案里带上这个时刻 +/// (`provider_loop` 的「均已限额或禁用」分支)。不带的话客户端只能立刻 +/// 重试、再撞一次同样的墙;带上之后(Claude Code / Codex 这类客户端会读 +/// 文案里的时间)才能做**合法的退避等待**。 +/// +/// ── 为什么取**最早**的而不是最晚的 ───────────────────────── +/// 「最早」= 第一个可能恢复、值得再试的时刻。取最晚会让客户端多睡一段 +/// 本不必睡的时间(账号是逐个恢复的,不是同时)。 +/// +/// ── 为什么读记录而不读内存 ────────────────────────────────── +/// 与 `account_limit_reset_at` 同源(都从账号记录现读):限额是**落盘事实** +/// (重启后仍在),内存里那份不进这里 —— 两处口径一致才不会出现「日志说 +/// 10 分钟后恢复、实际记录里是明天零点」的分歧。 +/// +/// `providers` 是本次请求的候选家;冷却键按 [`routing::CooldownKeys`] 解析 +/// (与写入侧同一个键)。**启用中的账号全都算**,包括本轮已经撞过的那几个 —— +/// 它们刚被标记,恢复时刻正是客户端最该等的那个。 +/// +/// `accounts_in_providers` 只按 provider 过滤、**不过滤禁用账号**(那是选路 +/// 层的事),所以这里自己剔一遍:一个被禁用的账号即便留着未过期的冷却记录也 +/// 不算候选,报它的恢复时刻会把用户引向一个系统根本不会去的账号。 +pub(super) fn earliest_limit_reset_at( + service: &UpstreamService, + providers: &[&str], + keys: &routing::CooldownKeys<'_>, +) -> i64 { + let now = logging::now_ms(); + let accounts: Vec = accounts_in_providers(service, providers, None) + .into_iter() + .filter(|account| !matches!(account.get("enabled"), Some(Value::Bool(false)))) + .collect(); + earliest_limit_reset_at_in(&accounts, keys, now) +} + +/// [`earliest_limit_reset_at`] 的纯函数内核(账号清单与「现在」都由调用方给, +/// 便于单测直接覆盖排序语义)。 +/// +/// 过期的冷却不必再筛:`rate_limit_reset_at` 只回**未来**时刻或 0 +/// (见那里的说明),所以这里直接对非零值取最小。 +fn earliest_limit_reset_at_in( + accounts: &[Value], + keys: &routing::CooldownKeys<'_>, + now: i64, +) -> i64 { + accounts + .iter() + .map(|account| routing::rate_limit_reset_at(account, keys, now)) + .filter(|reset| *reset > 0) + .min() + .unwrap_or(0) +} + /// 全部账号达到并发上限时的**挤占**挑选:余量(`limit - count`)最大者优先。 /// /// ── 排序口径(任务约定,改动前先读)────────────────────────── @@ -721,3 +776,85 @@ pub(super) fn report_limit_event( })), ); } + +#[cfg(test)] +mod tests { + use super::earliest_limit_reset_at_in; + use crate::server::core::routing::CooldownKeys; + use serde_json::json; + + /// 造一条带限额冷却的账号记录(形状与 `mark_rate_limited` 落盘的一致) + fn limited(id: &str, provider: &str, model: &str, reset_at: i64) -> serde_json::Value { + json!({ + "id": id, + "provider": provider, + "enabled": true, + "rateLimits": { model: { "status": 429, "resetAt": reset_at } }, + }) + } + + fn unlimited(id: &str, provider: &str) -> serde_json::Value { + json!({ "id": id, "provider": provider, "enabled": true }) + } + + /// 取**最早**的恢复时刻(不是最晚):客户端该睡到第一个可能恢复的点 + #[test] + fn the_earliest_reset_wins() { + let keys = CooldownKeys::new("Qwen/Qwen3.8-Flash-Next"); + let now = 1_000_000i64; + let accounts = vec![ + limited("a", "modelscope", "Qwen/Qwen3.8-Flash-Next", now + 600_000), + limited("b", "modelscope", "Qwen/Qwen3.8-Flash-Next", now + 60_000), + limited("c", "modelscope", "Qwen/Qwen3.8-Flash-Next", now + 300_000), + ]; + assert_eq!(earliest_limit_reset_at_in(&accounts, &keys, now), now + 60_000); + } + + /// 没有处在冷却期的账号 → 0(调用方据此退回原句,不拼「最早…恢复」) + #[test] + fn no_future_reset_reports_zero() { + let keys = CooldownKeys::new("m"); + let now = 1_000_000i64; + assert_eq!(earliest_limit_reset_at_in(&[], &keys, now), 0); + assert_eq!( + earliest_limit_reset_at_in(&[unlimited("a", "modelscope")], &keys, now), + 0 + ); + } + + /// **已过期**的冷却不算数(记录还在但时刻已过 = 未限额,与 + /// `rate_limit_reset_at` 的口径一致)——算进去会让文案报一个过去的时刻 + #[test] + fn an_expired_cooldown_is_not_counted() { + let keys = CooldownKeys::new("m"); + let now = 1_000_000i64; + let accounts = vec![ + limited("a", "modelscope", "m", now - 1), + limited("b", "modelscope", "m", now), + ]; + assert_eq!(earliest_limit_reset_at_in(&accounts, &keys, now), 0); + } + + /// 冷却**按模型**分键:别的模型的冷却不该影响本模型的「还要等多久」 + #[test] + fn another_models_cooldown_is_ignored() { + let keys = CooldownKeys::new("m"); + let now = 1_000_000i64; + let accounts = vec![limited("a", "modelscope", "other-model", now + 600_000)]; + assert_eq!(earliest_limit_reset_at_in(&accounts, &keys, now), 0); + } + + /// 多账号时取全体最早(这条覆盖的是「取 min 而不是取第一个」) + #[test] + fn the_minimum_spans_all_accounts() { + let keys = CooldownKeys::new("m"); + let now = 1_000_000i64; + let accounts = vec![ + limited("a", "modelscope", "m", now + 900_000), + unlimited("b", "modelscope"), + limited("c", "modelscope", "m", now + 120_000), + limited("d", "modelscope-intl", "m", now + 500_000), + ]; + assert_eq!(earliest_limit_reset_at_in(&accounts, &keys, now), now + 120_000); + } +} diff --git a/desktop-tauri/ui-islands/src/islands/accounts-domain.ts b/desktop-tauri/ui-islands/src/islands/accounts-domain.ts index 4b3b1e91..52c6b89f 100644 --- a/desktop-tauri/ui-islands/src/islands/accounts-domain.ts +++ b/desktop-tauri/ui-islands/src/islands/accounts-domain.ts @@ -237,6 +237,20 @@ const PROVIDER_FEATURES: Record = { // `expiry: ''` —— refresh token 不过期、access token 自动续期,这一列对它没有可显示的事实 // (与 kuku 同一处置:界面不渲染「有效期」)。 antigravity: { usage: true, edition: false, identifier: 'userId', expiry: '' }, + // ModelScope(魔搭)的两个站点(`modelscope` / `modelscope-intl`):两条同一份 + // —— 账号字段、余额形态、签到链路两地完全一致,差别只在域名(那是转发与 + // 凭证层的事,这里不体现)。 + // `usage: true` —— 额度是魔粒钱包(`available_balance`),外加「今日已用调用数」 + // 一行,见后端 providers::modelscope::balance;`creditDetail: true` 让余额格 + // 挂出「积分明细」(可用 / 冻结 / 今日已用三行)。 + // `edition: false` —— 地区由 provider id 直接表达(两家 provider、两个分组), + // 不需要再渲染一个地区列。 + // `identifier: 'userId'` —— 身份键存的是上游的 HavanaId + // (见 account_store::modelscope_accounts 模块头)。 + // `expiry: ''` —— 令牌不过期、也没有过期时刻可算,这一列对它没有可显示的事实 + // (与 kuku / antigravity 同一处置:界面不渲染「有效期」)。 + modelscope: { usage: true, creditDetail: true, edition: false, identifier: 'userId', expiry: '' }, + 'modelscope-intl': { usage: true, creditDetail: true, edition: false, identifier: 'userId', expiry: '' }, // 智谱清言(chatglm.cn)。各位各有出处: // `usage: true` —— 余额是**会员积分**(`member-api` 的活动状态 `current_score`, // 外加 `payment-api` 的会员档位),见后端 `providers::chatglm::balance`。 diff --git a/desktop-tauri/ui-islands/src/islands/add-account-configs.ts b/desktop-tauri/ui-islands/src/islands/add-account-configs.ts index 27e622b2..56a3f267 100644 --- a/desktop-tauri/ui-islands/src/islands/add-account-configs.ts +++ b/desktop-tauri/ui-islands/src/islands/add-account-configs.ts @@ -837,6 +837,63 @@ const ORCATERM: ProviderConfig = { ], } +/** + * ModelScope(魔搭)的两个站点:一家一个 provider,粘贴 `ms-` 令牌。 + * + * ── 一枚令牌两用(这是本家最省事的地方)────────────────────── + * 同一个 `ms-` 令牌既作 `Authorization: Bearer` 调推理,又作 + * `Cookie: m_session_id=<令牌>` 读账号身份 / 魔粒余额 / 每日签到(实测确认)。 + * 所以凭据只有一个字段,用户从魔搭的「访问令牌」页复制一次就够。 + * + * ── 两个站点是两套独立账号 ───────────────────────────────── + * 国内站(modelscope.cn)与国际站(modelscope.ai)账号体系分开:令牌打错站点 + * 会得到 401,所以两家各一张卡、各填各的令牌。 + * + * ── 没有续期、没有桌面端导入 ─────────────────────────────── + * 令牌长期有效(上游没有 refresh 接口),失效只能重新获取;魔搭没有桌面客户端 + * (与 Loomy / MonkeyCode 同一处境),因此不渲染「导入桌面端登录态」。 + * + * ── 添加时的一次探活(会拦下添加)────────────────────────── + * 令牌不透明、解不出身份,所以网关添加前必须打一次上游换回账号身份 —— + * 令牌无效 / 站点点错会在添加的那一刻就说清楚,而不是等第一次转发才失败。 + */ +function modelscopeForm(spec: { + provider: string + label: string + site: string + siteNote: string +}): ProviderConfig { + const { provider, label, site, siteNote } = spec + return { + provider, + label, + // 没有桌面客户端,也就没有可导入的登录态文件(理由见上方注释) + desktop: false, + manualTitle: t('粘贴 API 令牌'), + // 整段是一个 t() 键:扫描器只认字符串字面量(拼接串提不到键),所以不拆行 + manualNoteHtml: t('粘贴 ModelScope 的 API 令牌(ms- 开头,在 {site} 的「访问令牌」页获取)。
{siteNote}
这枚令牌两用:网关既用它调推理,也用它读账号身份、魔粒余额与每日签到。令牌长期有效、没有续期接口,失效后重新获取再粘一次即可。', { site, siteNote }), + fields: [ + // 字段名不包 t()(各语言相同,与别家同一处置) + { key: 'accessToken', label: 'accessToken', rows: 3, placeholder: t('ms- 开头的 API 令牌') }, + { key: 'name', label: t('备注名'), optional: true, placeholder: t('可选,留空则用上游账号昵称') }, + ], + } +} + +const MODELSCOPE = modelscopeForm({ + provider: 'modelscope', + label: t('ModelScope 国内版'), + site: 'modelscope.cn', + siteNote: t('这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。'), +}) + +const MODELSCOPE_INTL = modelscopeForm({ + provider: 'modelscope-intl', + label: t('ModelScope 国际版'), + site: 'modelscope.ai', + siteNote: t('这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。'), +}) + /** * 智谱清言(`chatglm.cn`)。逆向来源:客户端 2.0.7 的 `app.asar` + * `agentmore` 线上包(见后端 `providers::chatglm` 的模块头)。 @@ -927,9 +984,12 @@ export const BUILTIN_CONFIGS: ProviderConfig[] = [ // OrcaTerm(腾讯云遨驰终端桌面客户端):粘贴 accessToken / 导入桌面端登录态, // 排在末尾(与后端注册表 PROVIDERS 的排列一致,2026-10 接入) ORCATERM, - // 智谱清言(chatglm.cn):访客模式 / 粘贴令牌 / 导入本机登录态,排在末尾 - // (与后端注册表 PROVIDERS 的排列一致,2026-10 接入) + // 智谱清言(chatglm.cn):访客模式 / 粘贴令牌 / 导入本机登录态(2026-10 接入) CHATGLM, + // ModelScope(魔搭)的两个站点相邻(与 AutoClaw / Qoder / MonkeyCode 同一拆法): + // 国内版在前 —— 与后端注册表 PROVIDERS 的追加顺序一致(2026-10 接入) + MODELSCOPE, + MODELSCOPE_INTL, ] /** WorkBuddy 的块 id(结构特殊,单独一个组件) */ diff --git a/desktop-tauri/ui-islands/src/islands/add-provider-pick.tsx b/desktop-tauri/ui-islands/src/islands/add-provider-pick.tsx index e87d4670..75f629f9 100644 --- a/desktop-tauri/ui-islands/src/islands/add-provider-pick.tsx +++ b/desktop-tauri/ui-islands/src/islands/add-provider-pick.tsx @@ -99,6 +99,11 @@ export const PROVIDER_ICONS: Record = { // (`cloudcache.tencent-cloud.com/qcloud/orcaterm/pwa/icon/orcaterm_192x192.png`, // 与客户端 / 官网显示的应用图标为同一形象) orcaterm: 'assets/providers/orcaterm.png', + // ModelScope(魔搭):取自官网 favicon(`https://modelscope.cn/favicon.ico`, + // 内含 128×128 的一帧,归一成 256×256 入库 —— 与站点标签页上显示的是同一形象; + // 国内 / 国际版共用这一张,同 AutoClaw / MonkeyCode 的形态) + modelscope: 'assets/providers/modelscope.png', + 'modelscope-intl': 'assets/providers/modelscope.png', // 智谱清言:取自客户端安装包 `resources/app.asar` 内的应用图标 // (`assets/icon.png`,512×512,与系统里显示的应用图标为同一形象; // 归一成 256×256 入库 —— 与 officeace 同一处置) diff --git a/desktop-tauri/ui-islands/src/islands/checkin-page.tsx b/desktop-tauri/ui-islands/src/islands/checkin-page.tsx index c4459a1a..6d79aa47 100644 --- a/desktop-tauri/ui-islands/src/islands/checkin-page.tsx +++ b/desktop-tauri/ui-islands/src/islands/checkin-page.tsx @@ -57,6 +57,10 @@ const PROVIDER_DESC: Record = { // 它执行的是 ops 活动交付(三个接口),一句话说明里点出这一点,用户才不会 // 拿它跟别家「一次请求」的签到比快慢。 codearts: t('每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置'), + // ModelScope(魔搭)的两个站点:签到就是调一次登录信息接口(调用即触发 + // 当日魔粒),没有独立的签到按钮 —— 说明里点出这一点,用户才不会以为漏了什么。 + modelscope: t('无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)'), + 'modelscope-intl': t('与国内版同一套链路 · 站点不同、令牌不通用'), // 智谱清言:本家的「签到」就是会员的每日登录积分(一次 POST,到账数在 // `result.score`);后面的活动领取一并执行(活动期才有得领)。 // 访客账号没有积分体系,实现会如实跳过(不算失败),说明里点出这一点, diff --git a/desktop-tauri/ui-islands/src/islands/checkin-schedule-tab.tsx b/desktop-tauri/ui-islands/src/islands/checkin-schedule-tab.tsx index c0d8277f..4ee87b41 100644 --- a/desktop-tauri/ui-islands/src/islands/checkin-schedule-tab.tsx +++ b/desktop-tauri/ui-islands/src/islands/checkin-schedule-tab.tsx @@ -9,6 +9,7 @@ import { import { deleteSchedule, getSchedulesStore, loadSchedules, runScheduleNow, saveSchedule, setEditingId, subscribeSchedulesStore, toggleMaster, toggleScheduleEnabled, + toggleStartupCatchUp, type SchedulesStore, } from './checkin-schedules-state' import type { ScheduleEntry } from './checkin-state' @@ -37,7 +38,7 @@ import type { ScheduleEntry } from './checkin-state' * 整段是一个键:扫描器只认字符串字面量(拼接串 / 模板串提不到键),所以不拆行。 */ const AUTO_CHECKIN_DESC = t( - '到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。', + '到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。', ) /* ─── store 订阅 ───────────────────────────── */ @@ -106,6 +107,9 @@ function ScheduleEditor({ entry, store }: { entry: ScheduleEntry | null; store: const isNew = entry === null const [label, setLabel] = React.useState(entry?.label ?? '') const [time, setTime] = React.useState(entry?.time ?? '00:01') + // 随机窗口(分钟)。草稿用字符串:`type='number'` 清空时是 '',直接存数字 + // 会让输入框在「删光重填」时跳回 0 + const [jitter, setJitter] = React.useState(String(entry?.jitterMinutes ?? 0)) const [picked, setPicked] = React.useState>( new Set(isNew ? options.map(option => option.id) : entry?.providers ?? []), ) @@ -115,15 +119,31 @@ function ScheduleEditor({ entry, store }: { entry: ScheduleEntry | null; store: // 只在挂载 / 切换编辑对象时初始化一次:options 后到不该把用户改了一半的勾选冲掉 // eslint-disable-next-line react-hooks/exhaustive-deps }, []) - const canSave = time.trim() !== '' && picked.size > 0 + // 0 是合法值(关闭随机);空串按 0 处理(用户删光内容就是想关掉)。 + // 非整数 / 超范围不让保存:夹取交给后端会得到「填了 999 却按 120 生效」的 + // 静默偏差,不如当场拦住。上限与后端 auto_checkin::MAX_JITTER_MINUTES 对应。 + // + // 先用正则挡掉 `Number()` 会接受的非十进制写法(`1e3` / `0x10` / ` 5 `): + // 它们转出来都是整数,但用户显然没想表达那个意思。 + const jitterText = jitter.trim() + const jitterValue = jitterText === '' ? 0 : Number(jitterText) + const jitterValid = + (jitterText === '' || /^\d+$/.test(jitterText)) && + Number.isInteger(jitterValue) && + jitterValue >= 0 && + jitterValue <= 120 + const canSave = time.trim() !== '' && picked.size > 0 && jitterValid const pickAll = (): void => setPicked(new Set(options.map(option => option.id))) const clearAll = (): void => setPicked(new Set()) const submit = async (): Promise => { + // 双重保险:按钮的 disabled 已经挡住非法输入,但回车 / 程序化点击也要挡住 + if (!canSave) return await saveSchedule({ id: entry?.id, label: label.trim(), enabled: entry?.enabled ?? true, time: time.trim(), + jitterMinutes: jitterValue, providers: options.map(option => option.id).filter(id => picked.has(id)), }) } @@ -155,6 +175,25 @@ function ScheduleEditor({ entry, store }: { entry: ScheduleEntry | null; store: {t('北京时间 · 错过时点开机后会自动补签')} +
+ {t('随机前后')} + + setJitter(event.currentTarget.value)} + /> + + {t('分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行')} + + +
{t('签到范围')} @@ -271,7 +310,13 @@ function ScheduleEntryRow({ entry, store }: { entry: ScheduleEntry; store: Sched : {t('已停用')}}
- {t('每天 {time} · {scope}', { time: entry.time ?? '—', scope: providersSummary(entry, options) })} + {Number(entry.jitterMinutes) > 0 + ? t('每天 {time} · 随机前后 {n} 分钟 · {scope}', { + time: entry.time ?? '—', + n: Number(entry.jitterMinutes), + scope: providersSummary(entry, options), + }) + : t('每天 {time} · {scope}', { time: entry.time ?? '—', scope: providersSummary(entry, options) })}
{t('上次执行:{line}', { line: lastResultLine(entry) })} @@ -530,6 +575,8 @@ function ScheduleTab(): React.ReactElement { const data = store.data const masterOn = data?.enabled === true + // 缺省开:老配置没有这个键,与后端 `startup_catch_up()` 的缺省一致 + const startupCatchUp = data?.startupCatchUp !== false const entries = Array.isArray(data?.schedules) ? data!.schedules! : [] // 保活模型链(全局一份,随卡迁入本页):草稿非空表示用户正在编辑,否则跟随快照 const keepalive = checkin.snapshot?.keepalive @@ -579,6 +626,21 @@ function ScheduleTab(): React.ReactElement {
+
+ {t('启动补签')} + + void toggleStartupCatchUp(next === true)} + /> + + {startupCatchUp + ? t('开着:开机后今天没签过的条目立刻补签,不看随机窗口') + : t('关着:开机后等到窗口起点再签,随机窗口当天生效')} + + +
{store.editingId === 'new' ? : null} diff --git a/desktop-tauri/ui-islands/src/islands/checkin-schedules-state.ts b/desktop-tauri/ui-islands/src/islands/checkin-schedules-state.ts index 78dbb545..dbfff19e 100644 --- a/desktop-tauri/ui-islands/src/islands/checkin-schedules-state.ts +++ b/desktop-tauri/ui-islands/src/islands/checkin-schedules-state.ts @@ -132,6 +132,7 @@ export async function saveSchedule(payload: { label?: string enabled?: boolean time?: string + jitterMinutes?: number providers?: string[] }): Promise { if (store.saving) return @@ -148,17 +149,37 @@ export async function saveSchedule(payload: { } } -/** 条目开关(不发整表单:带上这条的 time / providers,后端 upsert 需要时刻必填) */ +/** 条目开关(不发整表单:带上这条的 time / jitterMinutes / providers,后端 upsert 需要时刻必填) */ export async function toggleScheduleEnabled(entry: ScheduleEntry, enabled: boolean): Promise { await saveSchedule({ id: entry.id, label: entry.label ?? '', enabled, time: entry.time ?? '', + // 必须带上:这是整表单重发,漏了会走「缺省保持原值」侥幸保住, + // 一旦后端那侧语义调整,点一次开关就会把随机窗口静默清零 + jitterMinutes: Number(entry.jitterMinutes) || 0, providers: Array.isArray(entry.providers) ? entry.providers : [], }) } +/** 「启动时立即补签」开关(全局,走老接口 POST /api/auto-checkin) */ +export async function toggleStartupCatchUp(enabled: boolean): Promise { + if (store.saving) return + patch({ saving: true }) + try { + const next = await bridge().saveAutoCheckin?.({ startupCatchUp: enabled }) + applySnapshot(next) + // 与总开关同一口径:两条分开调(扫描器只认字面量首参) + if (enabled) toast(t('启动补签已开启')) + else toast(t('启动补签已关闭')) + } catch (error) { + toast(t('保存失败:{error}', { error: errorMessage(error) }), 'err') + } finally { + patch({ saving: false }) + } +} + /** * 删除一条条目。确认在组件层做(wbConfirm),这里只管删。 * 删除合成的默认条目 = 后端写空数组,「从旧字段合成」不再发生(界面照实变空)。 diff --git a/desktop-tauri/ui-islands/src/islands/checkin-state.ts b/desktop-tauri/ui-islands/src/islands/checkin-state.ts index 6cb899d6..570c26f0 100644 --- a/desktop-tauri/ui-islands/src/islands/checkin-state.ts +++ b/desktop-tauri/ui-islands/src/islands/checkin-state.ts @@ -71,6 +71,8 @@ export type AutoCheckinState = { lastFiredToday?: boolean nextRunAt?: number | null lastResult?: CheckinHistoryEntry | null + /** 启动时立即补签(缺省 true;关掉后启动不补,等到窗口起点由调度触发) */ + startupCatchUp?: boolean running?: boolean } @@ -85,6 +87,8 @@ export type ScheduleEntry = { displayLabel?: string enabled?: boolean time?: string + /** 随机前后 N 分钟(0 / 缺省 = 不随机,窗口就是时刻本身) */ + jitterMinutes?: number providers?: string[] lastFiredDate?: string | null lastFiredToday?: boolean diff --git a/desktop-tauri/ui/assets/providers/modelscope.png b/desktop-tauri/ui/assets/providers/modelscope.png new file mode 100644 index 00000000..308b1cf1 Binary files /dev/null and b/desktop-tauri/ui/assets/providers/modelscope.png differ diff --git a/desktop-tauri/ui/i18n/en/add-account.js b/desktop-tauri/ui/i18n/en/add-account.js index 248122c3..a5f64f5a 100644 --- a/desktop-tauri/ui/i18n/en/add-account.js +++ b/desktop-tauri/ui/i18n/en/add-account.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:en/add-account —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · Models: {head}{rest}", " 等 {n} 个": " ({n} total)", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "Google refresh token starting with 1// (you can also paste the whole refresh_token=… line)", "11 位大陆手机号": "11-digit mainland China mobile number", "1~64 个字符,账号列表里按它分组显示": "1-64 characters; accounts are grouped by it in the account list", "6 位数字": "6 digits", "
  • 没有可自动领的活动
  • ": "
  • No campaigns can be claimed automatically
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    What you receive is plan gift points, which do not add to the welfare model token pool; ", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "The Anthropic-compatible endpoint is https://api.deepseek.com/anthropic (fill it in when you switch the protocol to anthropic)", "Anthropic 协议填根地址,不要带 /v1": "For the Anthropic protocol, use the root URL without /v1", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw China edition", "AutoClaw 国际版": "AutoClaw International edition", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS is required; paste the **full Cookie** (a Cookie editor can export it in one click) — the **PTOKEN must be kept**, as the gateway uses it to exchange for a KukuAI business session token from Baidu; without it, model refresh reports \"Not signed in\". A full Cookie header, a JSON array exported by a Cookie editor, or a {BDUSS, STOKEN} object are all supported. KukuAI has no refresh mechanism, so once the login state expires, just paste it again.", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=… (or the JSON exported by a Cookie editor)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "CatPaw's X-Passport-Token (login-state Cookie)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Get the Cline Pass API Key at app.cline.bot (subscription-based); the endpoint is OpenAI-compatible, the model catalog follows the Cline console, and model names are added under Model management with the plain name (e.g. glm-5.2 / kimi-k2.7-code / deepseek-v4-pro); the upstream validates the client shape, so the required client request headers are preset on this card", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT (three dot-separated segments)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT (three dot-separated parts; you can also paste a whole Bearer line or the data.bin content)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT (three dot-separated parts; a whole chatglm_token=… line works too)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode International edition", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM managed endpoint; apply for the Key at integrate.api.nvidia.com", "OfficeAce 果办": "OfficeAce", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken is Accio's login credential (a long opaque token, not a JWT); refreshToken is optional and enables automatic renewal on expiry. Enter the credential of the {label} account — {siteNote} (the easiest way to get it: just use \"Web login\" above; no need to hunt for the token manually.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken is Trae's Cloud-IDE-JWT (three dot-separated segments), and refreshToken enables automatic renewal on expiry (this provider rotates refreshToken on every use: once exchanged, the old one is void, so do not refresh the same account from two programs at once).
    When pasting manually, fill in machineId / deviceId as well: upstream ties them to the device public key uploaded at sign-in to identify the device, and swapping in a new pair from nowhere triggers the 2xxxx family of device-binding rejections.
    Without these three, the proper route is \"Web login\" above; for container / remote deployments, paste the callback URL from the address bar as prompted.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "The value of monkeycode_ai_session (you can also paste the whole Cookie)", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken is optional and enables automatic renewal on expiry; both can be obtained from the Raccoon client login-state file.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken is optional and enables automatic renewal; both can be obtained from the client login-state file. The same Cline account works in both pools; here it is grouped under {label}.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token supports the enc: prefix (decrypted automatically on Windows). Without a refreshToken, automatic renewal is not possible.", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "token is the login-state Cookie; CatPaw has no refresh mechanism, so sign in again in the client after it expires.", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "API Key starting with user_ (you can also paste the whole Authorization: Bearer … line)", "{label} 网页登录的打开方式": "How to open {label} web login", "{label} 账号地区": "{label} account region", "{label} 账号的添加方式": "How to add a {label} account", "{name} 不是合法 JSON:{reason}": "{name} is not valid JSON: {reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name} requires a JSON object (like {sample})", "{n} 个账号": "{n} accounts", "{n} 个账号,点击添加": "{n} accounts, click to add", "{seconds}s 后重发": "Resend in {seconds}s", "✅ {label}账号已添加": "✅ {label} account added", "✅ {label}账号已添加{name}": "✅ {label} account added{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ Imported {n} providers from cc-switch", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ Created custom provider \"{name}\" and added an account", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ Deleted custom provider \"{name}\"{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ Updated the existing account{name} (one account per API key; re-adding merges into it)", "✅ 登录成功,{edition}账号已加入列表": "✅ Signed in; {edition} account added to the list", "✅ 领取成功:{planId}{period}": "✅ Claim successful: {planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " One provider can hold multiple keys, rotated by priority.", "「{name}」的账号添加功能还在开发中,敬请期待。": "Adding accounts for \"{name}\" is still in development — stay tuned.", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "One Key works across many vendors; use the full \"vendor/model\" name (e.g. deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "Leave blank when the upstream needs no authentication, and check the option below (blank without the checkbox counts as no credential configured)", "上游信息": "Upstream info", "不可领({status})": "Not claimable ({status})", "不支持导入": "Import not supported", "不是有效的凭证文件:内容要是一个 JSON 对象": "Not a valid credential file: the content must be a JSON object", "不是有效的凭证文件:需要包含 accessToken 与 uid": "Not a valid credential file: accessToken and uid are required", "不是自定义提供商": "Not a custom provider", "不需要 Key:转发与拉取模型都不发送鉴权头": "No Key needed: neither forwarding nor model fetching sends auth headers", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "No sign-in needed: click the button below and the gateway will obtain a guest credential from Zhipu Qingyan directly and add it to the account list (you can fill in a note name first). The guest credential can be used for chat right away; the free quota is issued by the upstream per device.

    Note: a guest account has no points system — its member points, daily sign-in points and activity claim endpoints all require sign-in, so those capabilities are skipped for guests (no readings are shown on the accounts page or in the check-in center). To get points, use \"Fill in credentials\" to paste a signed-in account token, or \"Import desktop sign-in state\".", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "Both editions' accounts can be saved at once, each with its own model catalog (the China and International editions are two providers that can be enabled and mapped separately).", "中国版": "China edition", "今天没有需要领的活动(都已到账)": "No campaigns to claim today (all already credited)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "Tried {attempts} times today (Beijing time {day}); {left} attempts left{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "Grab three items from another machine (or from the OfficeAce desktop app's models.json) and paste them here: the model gateway base URL (baseUrl, shaped like https://modelgw-…/v2) plus modelAppKey / modelAppSecret. These three are enough to forward requests (the gateway credential never expires); the control-plane temporary credentials (accessKeyId and so on) are optional — leaving them blank disables balance queries and auto-renewal but does not affect forwarding.", "从本机导入桌面端登录态": "Import desktop login state from this machine", "任务镜像 id": "Task image id", "余额查询": "Balance query", "使用 Google 账号登录": "Sign in with Google", "使用 Zai 账号登录": "Sign in with Zai", "使用个人访问令牌(PAT)": "Use a personal access token (PAT)", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "Free models need no Key (\"This upstream needs no authentication\" is checked by default, and the gateway uses anonymous credentials automatically); for paid models, enter your Zen API Key. The free tier only accepts the official client form, so \"Emulate the official OpenCode client\" is on by default", "内嵌窗口": "Embedded window", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "Opens in the embedded window; closing it cancels the wait (if a Google account is rejected, switch to the system browser)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "Opens in the embedded window; added to the list when done; closing it cancels the wait", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "Opens in an embedded window; the account is added automatically once you have scanned — closing the window cancels the wait", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "The embedded window uses a fresh environment, so multiple accounts do not affect each other; closing it cancels the wait", "内嵌窗口(推荐)": "Embedded window (recommended)", "准备验证…": "Preparing verification…", "凭据 JSON": "Credential JSON", "凭证文件在哪?": "Where is the credential file?", "创建并添加账号": "Create and add account", "创建这个提供商,并同时建立它的第一个账号。": "Create this provider and its first account in one step.", "删除功能不可用(脚本未就绪)": "Delete is unavailable (script not ready)", "删除失败:{reason}": "Delete failed: {reason}", "删除此提供商": "Delete this provider", "及 {n} 个账号": " and {n} accounts", "发送中…": "Sending…", "发送失败:{message}": "Send failed: {message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "Send unconfirmed: the sign-in window has opened; complete the sign-in manually in that window", "取消失败:{message}": "Cancel failed: {message}", "取消等待": "Cancel sign-in", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "Only the Embedded window can restore third-party options: we cannot modify the sign-in page in the system browser", "可选": "Optional", "可选(cloudaicompanionProject):留空由网关自动发现": "Optional (cloudaicompanionProject); if blank, the gateway discovers it automatically", "可选,展示用": "Optional; for display", "可选,没有则无法自动续期": "Optional; without it, automatic renewal is not possible", "可选,留空使用凭据里的 user_name": "Optional; defaults to the user_name in the credential", "可选,留空使用账号姓名、邮箱或令牌指纹": "Optional; defaults to the account name, email, or token fingerprint", "可选,留空使用账号昵称或邮箱": "Optional; defaults to the account nickname or email", "可选,留空则用 key 尾号": "Optional; defaults to the key suffix", "可选,留空则用 userId": "Optional; defaults to userId", "可选,留空则用上游返回的账号名或账号 id": "Optional; defaults to the account name or account id returned by upstream", "可选,留空则用凭证里的账号名": "Optional; defaults to the account name in the credential", "可选,留空则用文件里的昵称": "Optional; leave empty to use the nickname from the file", "可选,留空则用登录名或 uid": "Optional; defaults to the login name or uid", "可选,留空则用脱敏手机号": "Optional; defaults to the masked phone number", "可选,留空则用脱敏手机号或 userId": "Optional; defaults to the masked phone number or userId", "可选,留空则用账号 uk": "Optional; defaults to the account uk", "可选,留空则用账号昵称": "Optional; defaults to the account nickname", "可选,留空则用账号昵称或 userId": "Optional; leave blank to use the account nickname or userId", "可选,留空则用邮箱或令牌尾号": "Optional; defaults to the email or token suffix", "可选,留空用「OfficeAce 果办」": "Optional; defaults to “OfficeAce”", "可选,留空自动生成": "Optional; generated automatically if blank", "可选,留空自动用昵称": "Optional; defaults to the nickname", "可选,给这个访客账号起个备注名": "Optional; a note name for this guest account", "可选,续期时带上": "Optional; sent when renewing", "可选,讯飞侧 userid": "Optional; the userid on the iFlytek side", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "Optional; required to start a conversation. If blank, the gateway discovers it automatically from this account's existing tasks; if it cannot find one, fill it in manually later.", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "Optional; the account email, used for display and to recognize the identity (the same account is recognized even after switching to a new token)", "可选;UUID 形态,与凭据同生共死": "Optional; UUID form, lives and dies with the credential", "可选;填了才能到期自动续期": "Optional; required for automatic renewal on expiry", "可选;用于去重与展示名(留空时网关会问一次上游)": "Optional; used for deduplication and the display name (when blank, the gateway asks upstream once)", "可选;用于生成账号 id 与展示名": "Optional; used to generate the account id and display name", "可选;纯数字串(上游只收 8–24 位数字)": "Optional; digits only (upstream accepts only 8–24 digits)", "可领取": "Claimable", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "Keyed and no-auth accounts can coexist in one provider, each routed by its own rules; multiple no-auth accounts are allowed too (each with its own egress proxy)", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "Switch the protocol to anthropic on the same address to use its Claude-compatible endpoint. Forwarding requires an OpenCode Go API Key (subscription-based; fetching the model catalog needs no Key, but requests get a 401 \"Missing API key\" from upstream)", "响应为空": "Empty response", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "SenseNova's OpenAI-compatible endpoint; balance query uses the console account and password (see \"Balance query\" below)", "国内版": "China edition", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "The China edition and **the International edition are two separate sets of accounts and plans**; credentials and claimed plans do not carry over between them.", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "The China edition's sign-in page has no Google / GitHub options (it uses WeChat / phone / email sign-in)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "The China edition's sign-in site is www.accio-ai.com, a different site from the International edition's.", "国内版(WorkBuddy)": "China edition (WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "China site: https://api.siliconflow.cn/v1", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "China site (minimaxi.com); the OpenAI-compatible address is https://api.minimaxi.com/v1", "国际版": "International edition", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "The International edition z.ai Coding plan; the OpenAI-compatible address is https://api.z.ai/api/coding/paas/v4", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "The International and China editions are **two separate sets of accounts** (two sites of the same account system); credentials do not carry over.", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "The International and China editions have separate account systems; enter the International edition's credentials. Without a refreshToken, automatic renewal is not possible.", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "The International edition's sign-in page shows only email sign-in by default; checking this restores the Google / GitHub / X options", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "The International edition's inference site is api.z.ai, a different site from the China edition's; plans are separate as well.", "国际版(WorkBuddy AI)": "International edition (WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "International site Coding plan; the OpenAI-compatible address is https://api.minimax.io/v1", "在 cc-switch 里找到": "Found", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "Complete the official sign-in in the embedded window; the account is added to the list automatically on success.", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "Generate a PAT in the Qoder account settings → Integrations for {label} (do not use a Google / GitHub token). Accounts and credentials do not carry over between the two regions.", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "Scan the WeChat QR code on the official authorization page that opens (the QR code appears right away). The account is added to the list automatically after a successful scan.", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "In the window that opens, sign in to the KukuAI main site with your Baidu account (SMS code or QR scan both work); the account is added to the list automatically on success. The gateway exchanges it with Baidu for a KukuAI business session token (requires the KukuAI client installed on this machine).", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "Sign in with your Google account in the window that opens (Antigravity's authorization page); the account is added to the list automatically once authorization completes.", "在浏览器中打开登录页": "Open the sign-in page in your browser", "地区": "Region", "填写凭证": "Enter credentials", "填写凭证添加": "Enter credentials to add", "备注名": "Label", "套餐": "Plan", "如:智谱 GLM": "e.g. Zhipu GLM", "完成登录后自动加入账号列表,昵称取自上游。": "Added to the account list automatically after sign-in; the nickname comes from upstream.", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "Official client credential directory: Windows — C:\\Users\\\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth; macOS — ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "Officially confirmed as credited", "导入": "Import", "导入中…": "Importing…", "导入凭证文件": "Import credential file", "导入失败": "Import failed", "导入失败:{reason}": "Import failed: {reason}", "导入所选": "Import selected", "导入所选({n})": "Import selected ({n})", "导入桌面端登录态": "Import desktop login state", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "The embedded window will open; the account is added to the list automatically once authorization completes. Closing the window cancels the wait. The authorization page may end with a message that it cannot open the zcode:// link — that is normal; the result has already been recorded server-side", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "The embedded window will open; the account is added to the list automatically once authorization completes. On a remote panel you can paste the callback URL. Closing the window cancels the wait. The link is valid for 5 minutes; if it times out or is not clicked, it is voided (you can start again)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "The embedded window will open; the account is added to the list automatically after sign-in. Closing the window cancels the wait", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "The authorization page will open in your system default browser (reusing the Trae account already signed in there); on the same machine the account is added automatically when done. For Docker / remote panels, paste the callback URL from the address bar as prompted.", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "The authorization page will open in your system default browser (reusing the ZCode account already signed in there); the account is added to the list automatically once authorization completes. A final message that the zcode:// link cannot be opened is normal", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "The authorization page will open in your system default browser (reusing the Huawei Cloud account already signed in there); the gateway polls the cloud for the authorization code, so it does not matter which machine the browser runs on. The account is added to the list automatically once done", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "The authorization page will open in your system default browser (reusing the Huawei Cloud account already signed in there); when the browser and the gateway are not on the same machine, paste the final callback URL back into the panel as described above", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "The sign-in page will open in your system default browser (reusing the Accio account already signed in there); the account is added to the list automatically after sign-in, and closing the popup cancels the wait", "小米 MiMo Token Plan 套餐(新加坡站)": "Xiaomi MiMo Token Plan (Singapore site)", "已到账": "Credited", "已取消登录等待": "Pending sign-in canceled", "已取消领取": "Claim canceled", "已取消验证码": "Verification canceled", "已填写手机号,正在发送验证码…": "Phone number entered; sending the code…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "Marked as needing no authentication: the account is routed normally, and no auth headers are sent outbound", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "Imported {ok}, failed {fail} (failed items are marked in the list)", "已建过 · {n} 个账号,点击继续添加": "Already created · {n} accounts, click to add more", "已建过,点击继续添加账号": "Already created, click to add another account", "已打开官方登录页,请在窗口中完成登录…": "Official sign-in page opened; complete sign-in in the window…", "已点发送,等待短信…": "Sent; waiting for the SMS…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "Sign-in page opened in your system default browser; complete sign-in in the browser…", "已领取,等官方确认": "Claimed, awaiting official confirmation", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "This app version does not support AutoClaw web login; update the app", "当前没有可领取的套餐(活动尚未开始)": "No plans are available to claim right now (the event has not started yet)", "当前环境不支持领取(桥接方法缺失)": "Claiming is not supported in this environment (bridge method missing)", "必填,CatPaw 账号标识": "Required; CatPaw account identifier", "恢复 Google / GitHub 入口": "Restore Google / GitHub options", "手机号": "Phone number", "手机验证码登录": "SMS code login", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "Open the official authorization page for Trae SOLO (trae.cn) and sign in with your Trae account: once authorized, the official page redirects back to a temporary port on this machine; a same-machine deployment receives it automatically, while Docker / remote panels should copy the callback URL from the address bar as prompted.", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "Open the official sign-in page for Accio {label} ({site}) and sign in with your Accio account: on success the official page redirects back to this machine; a same-machine setup completes automatically, while Docker / remote panels just paste the callback URL as prompted (the authorization code is passed to the gateway only on this machine, and no plaintext token is shown in the UI).", "打开 Accio {label}登录页": "Open the Accio {label} sign-in page", "打开 Antigravity 网页登录": "Open Antigravity web login", "打开 CatPaw 网页登录": "Open CatPaw web login", "打开 Cline 授权页": "Open Cline authorization page", "打开 CodeArts 授权页": "Open CodeArts authorization page", "打开 Qoder 网页登录": "Open Qoder web login", "打开 Trae 授权页": "Open Trae authorization page", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "Open the official authorization page for ZCode {label} and sign in with your account. The authorization result is recorded by the ZCode server; the gateway fetches the credential in the background and adds the account to the list.", "打开 ZCode {label}授权页": "Open the ZCode {label} authorization page", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "Open the official Huawei Cloud CodeArts authorization page to sign in: once done, the official page brings the browser back to the gateway's own /oauth/callback, and the gateway exchanges the one-time authorization code for temporary credentials and adds the account to the list.
    When the gateway runs on another machine, the web UI prompts you to paste the final callback URL from the address bar back into the panel.", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "Open the Huawei Cloud authorization page and sign in: once finished, the gateway automatically polls the cloud for the authorization code and adds the account to the list (no OfficeAce desktop app required, and no need to paste a callback URL back manually).", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "Open the official authorization page and complete the device-code authorization; you will be signing in to a {label} ({site}) account.", "打开授权页": "Open the authorization page", "打开授权页完成确认,账号自动加入 {label}{note}": "Open the authorization page and confirm; the account is added to {label} automatically{note}", "打开方式": "Open with", "打开网页登录": "Open web login", "探测失败:{message}": "Probe failed: {message}", "接入一个兼容上游": "Connect a compatible upstream", "提交中…": "Submitting…", "搜索提供商": "Search providers", "搜索提供商…": "Search providers…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "Paste the whole credential JSON written to disk by the official plugin / CLIProxyAPI (like {\"codearts_provider_credential\":{…}}; a flattened form also works).
    Required: access_key_id, secret_access_key, security_token.For automatic renewal you must paste refresh_token and oauth_context as well — temporary credentials expire in about an hour, and without that half they cannot be renewed; you would have to sign in again.", "文件是{edition}凭证,已按该版本导入": "The file contains {edition} credentials and has been imported as that edition", "新建自定义提供商": "New custom provider", "方案:{label}": "Scheme: {label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "Plaintext JWT, or the enc: encrypted value in auth.json (decrypted automatically)", "明文 JWT(国际版账号的 access token)": "Plaintext JWT (the access token of an International edition account)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "Zhipu's bigmodel.cn Coding plan; get the Key at open.bigmodel.cn/usercenter/apikeys", "未知错误": "Unknown error", "未能获取授权地址,请重试": "Could not get the authorization URL; try again", "未能读取 cc-switch 数据": "Could not read cc-switch data", "未领取成功": "Claim unsuccessful", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "Check this for upstreams like local Ollama or the OpenCode Zen free tier; otherwise the account cannot be used", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "This provider has two credentials that **do not replace each other**; fill in the one(s) for the features you need, at least one: the Coding Plan API Key is used for forwarding inference (hits {site}) and for querying the window limits (the remaining percentage of each N-hour / weekly window); the jwt is used for claiming plans and querying balance (hits the billing gateway at zcode.z.ai; officially called a Coding Plan JWT, a three-segment dot-separated string). Either one can query balance, but they read different things: the jwt reads the balance buckets and the plan expiry, while the API Key reads the window limits; and claiming only accepts the jwt, forwarding only accepts the API Key. Please enter the credentials for the {label} account — {plan} (the easiest way: just use \"Web login\" above — it exchanges this API Key for you and gets both credentials at once.)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "The local Ollama OpenAI-compatible endpoint; no API Key needed (\"This upstream needs no authentication\" is checked by default, and no auth headers are sent at all)", "本次未确认到账": "Not confirmed as credited this time", "条可导入": "are importable", "条配置,其中": "configs in cc-switch, of which", "桌面运行时不可用(Tauri 未初始化)": "Desktop runtime unavailable (Tauri not initialized)", "模型网关基址": "Model gateway base URL", "正在打开百度登录页…": "Opening the Baidu sign-in page…", "正在扫描本机 cc-switch…": "Scanning cc-switch on this machine…", "正在换发访客凭证…": "Requesting a guest credential…", "正在添加…": "Adding…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "Waiting for {name} sign-in to finish; you can start a new sign-in only after it completes or is canceled", "每周": "Weekly", "每日": "Daily", "每月": "Monthly", "没有则无法自动续期": "Without it, automatic renewal is not possible", "没有匹配「{keyword}」的提供商": "No providers match \"{keyword}\"", "添加 {name} 账号": "Add {name} account", "添加中…": "Adding…", "添加到 ": "Add to ", "添加失败:{reason}": "Add failed: {reason}", "添加小浣熊账号": "Add Raccoon account", "添加方式": "Add method", "添加访客账号": "Add a guest account", "添加账号": "Add account", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "Volcano Engine Coding plan; the general inference endpoint is https://ark.cn-beijing.volces.com/api/v3", "点击添加账号": "Click to add an account", "点开即预填,填 Key 接入": "Opens prefilled; enter your Key to connect", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "After clicking the button, first pass a slider verification (the vendor's risk control), then the sign-in page opens and the account is added automatically once you sign in.
    This is the only official sign-in method for the International edition; if you are already signed in to the client, \"Import desktop login state\" is faster.", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "Sign in with the phone number bound to your AutoClaw account: click \"Get code\", then enter the SMS code below and sign in. The code is submitted from this machine directly to the official API; no token is shown in the UI.", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "Sign in with your CatPaw account (Meituan Passport); the account is added to the list automatically on success.", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "Sign in with the phone number bound to your Loomy account: click \"Get code\" and enter it. This is the easiest way in for this provider.", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "Used for forwarding; two dot-separated segments like apiKey.secret (if left blank, this account cannot forward)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "Used for claiming plans and querying balance; if left blank, this account cannot claim or check balance", "用户 ID": "User ID", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "Sign in with your bound phone number: click \"Get code\" and enter it. This is the only official sign-in method for the China edition.", "留空则用提供商名称": "Leave blank to use the provider name", "登录 / 添加 {name} 账号": "Sign in / add {name} account", "登录 session(一长串)": "Login session (a long string)", "登录中…": "Signing in…", "登录失败:{message}": "Sign-in failed: {message}", "登录已结束": "Sign-in has ended", "登录并添加": "Sign in and add", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "Login-state file path: ~/.box-agent/config/auth.json (Windows: C:\\Users\\\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "Delete custom provider \"{name}\"? This will also delete {count} accounts under it; deletion cannot be undone.", "等待 Accio {label}登录完成…": "Waiting for Accio {label} sign-in…", "等待 CatPaw 登录完成…": "Waiting for CatPaw sign-in…", "等待 Cline 授权确认…": "Waiting for Cline authorization confirmation…", "等待 CodeArts 登录完成…": "Waiting for CodeArts sign-in…", "等待 Google 授权完成…": "Waiting for Google authorization…", "等待 KukuAI 登录完成…": "Waiting for KukuAI sign-in…", "等待 OfficeAce 登录完成…": "Waiting for OfficeAce sign-in…", "等待 OrcaTerm 登录完成…": "Waiting for OrcaTerm sign-in…", "等待 Qoder 授权完成…": "Waiting for Qoder authorization…", "等待 Trae 授权完成…": "Waiting for Trae authorization…", "等待 ZCode {label}授权完成…": "Waiting for ZCode {label} authorization…", "等待小浣熊登录完成…": "Waiting for Raccoon sign-in…", "等待登录完成…": "Waiting for sign-in…", "等待网页登录…": "Waiting for web login…", "粘贴 API Key": "Paste API Key", "粘贴 Accio 的 accessToken": "Paste the Accio accessToken", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Paste Antigravity's Google refresh token (starts with 1//; pasting the whole line containing refresh_token= also works).
    This is a manual entry besides web login (for example, exported from the official IDE you are already signed in to). The refresh token does not expire, and the gateway renews the access token automatically when it expires; if the token is lost, you can only go through Google authorization again, so keep it safe.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Paste the Command Code API Key (starts with user_; get it from the official CLI's ~/.commandcode/auth.json or the web studio). Pasting the whole line / with quotes / with the Bearer prefix all work; the gateway strips it down to the bare key itself. The key does not expire and there is no renewal API, so if it stops working just get a new one. When adding, the gateway runs a lightweight liveness check; a failure does not affect adding.", "粘贴 Cookie": "Paste Cookie", "粘贴 Google refresh token": "Paste Google refresh token", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "Paste OrcaTerm's OAuth accessToken (a JWT with three dot-separated parts; available from the desktop client's data.bin or the web version's ot_session cookie). Pasting a whole line containing Bearer / ot_session= is fine too — the gateway strips it down to the bare token. After adding, the gateway renews it automatically (the upstream has a renewal API), so you do not need to follow the 2-hour expiry by hand.", "粘贴 Qoder 个人访问令牌(pt-…)": "Paste the Qoder personal access token (pt-…)", "粘贴 accessToken": "Paste accessToken", "粘贴 access_token(一长串 JWT)": "Paste access_token (a long JWT)", "粘贴 session cookie": "Paste session cookie", "粘贴 token / refreshToken": "Paste token / refreshToken", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "Paste a token starting with workos:… (the prefix is added automatically if missing)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "Paste a Zhipu Qingyan access token (a JWT with three dot-separated parts). How to get it: open chatglm.cn in a browser, sign in, then copy the value of the chatglm_token cookie from Application → Cookies in the developer tools (pasting the whole chatglm_token=…; line works too). It is verified against the upstream once after pasting, and the account is only saved if that passes; signed-in accounts get points and sign-in capability, and the gateway renews it automatically afterwards (the upstream has a renewal API).", "粘贴登录凭据": "Paste login credentials", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "What you paste is the login session (which is also the model gateway token). Loomy has no renewal API; the session is valid for about 14 days, so just sign in again after it expires.", "粘贴网关凭据": "Paste gateway credentials", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "Paste the value of the web session cookie monkeycode_ai_session (copying the whole Cookie in the browser and pasting it directly also works; the gateway extracts the value itself).
    {siteNote}
    MonkeyCode has no renewal API: the session is valid for about 30 days (a hard limit); once it expires, sign in to the web page again and paste it one more time.", "粘贴访问令牌": "Paste an access token", "系统浏览器": "System browser", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "The system browser can reuse an existing login state (recommended for the International edition); the embedded window is cleaner.", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "Opens in the system browser (reuses the signed-in Cline account); added to the list when done", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "Opens in the system browser (reuses the Google account already signed in); added to the list when done", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "Opens in the system browser (reuses the signed-in Zai / Google account); added to the list when done", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "Opens in the system browser (reuses the signed-in Meituan account); added to the list when done", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "Opens in the system browser (reuses a signed-in account); added to the list when done", "系统默认浏览器": "System default browser", "编码套餐 API Key": "Coding Plan API Key", "网关 Secret": "Gateway secret", "网页登录": "Web login", "网页登录的打开方式": "How to open web login", "网页登录(Zai / Google)": "Web login (Zai / Google)", "自定义": "Custom", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "Self-hosted aggregation panel: fill in your own site address. Balance query calls {base}/v1/usage with this account's API key; no extra setup", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "Self-hosted aggregation panel: fill in your own site address; balance query additionally needs a NewAPI personal access token (see \"Balance query\" below)", "获取风控配置失败,将直接尝试领取:{message}": "Failed to get the risk-control config; trying to claim directly: {message}", "获取验证码": "Get code", "访客模式": "Guest mode", "访客模式(免登录)": "Guest mode (no sign-in)", "该上游无需鉴权(不发送鉴权头)": "This upstream needs no authentication (no auth headers are sent)", "该提供商": "This provider", "该提供商账号添加功能即将上线": "Account adding for this provider is coming soon", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "This custom provider no longer exists (it may have been deleted); refresh and try again", "请先选择一个自定义提供商": "Select a custom provider first", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "Complete the verification in the slider popup (a risk-control step required by the vendor)", "请填写 11 位大陆手机号": "Enter an 11-digit mainland China phone number", "请填写 6 位数字验证码": "Enter the 6-digit code", "请填写 Base URL": "Enter the Base URL", "请填写 {label}": "Enter {label}", "请填写名称": "Enter a name", "请完成验证…": "Complete the verification…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "Reads and decrypts %APPDATA%/AutoClaw/auth.json; Windows only", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "Reads ~/.cline/data/settings/providers.json; requires being signed in to the Cline client", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "Reads ~/.meituan-catpaw/auth.json; requires being signed in to the CatPaw client", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "Reads the local KukuAI client login state (%APPDATA%\\baidugenflowpro\\Network\\Cookies); requires being signed in to the KukuAI client", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "Read the local OrcaTerm client sign-in state (%APPDATA%\\com.orcaterm-desktop.app\\data.bin); the OrcaTerm client must be signed in", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "Read the local Zhipu Qingyan client sign-in state (%APPDATA%\\chatglm\\Network\\Cookies); the client must be signed in", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "Reads the account currently logged in to the official client (Tencent WorkBuddy / WorkBuddy AI) on this machine: the newest session file in its credential directory is located automatically (the official client must be logged in on this machine). The gateway renews the token after import — no need to swap tokens manually with the 2-hour expiry.", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "Reads the local client's current login state (plaintext Cookie, no decryption needed). The Cookies file is exclusively locked while the client runs, so close the KukuAI client before importing.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state).", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state). After signing in again in the client, click \"Refresh token\" to sync.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state). After signing in again in the client, just re-import.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state). Users who sign in to the client with Zai / Google should use this one.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state). This one is grouped under {label}.", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "Reads the OAuth token the local client is currently signed in with (plain-text JSON, no decryption needed). After importing, the gateway renews it automatically — no need to follow the client's 2-hour expiry by hand.", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "Read the current sign-in state of the local client. The client's cookies are DPAPI-encrypted (Chromium os_crypt), so this is Windows-only; the file may be unreadable while the client is running — quit the client and retry (or use \"Fill in credentials\" to paste a token instead).", "账号信息": "Account info", "账号信息不完整,请刷新后重试": "Account info is incomplete; refresh and try again", "账号已添加,但请留意:{warning}": "Account added, but note: {warning}", "账号版本": "Account edition", "账号类型": "Account type", "账号:{name}
    ": "Account: {name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "Routes through Inference Providers; create the Key at hf.co/settings/tokens", "还没有账号": "No accounts yet", "这一家当前不支持网页登录,请改用填写凭证": "This provider does not support web login right now; use Enter credentials instead", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "This account has no campaigns that can be claimed automatically right now (only the daily login gift points are claimed automatically)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "This quota goes through the Start Plan channel: if forwarding reports that the Coding Plan has expired, ", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "This is for the China site (monkeycode-ai.com) account: paste the China site's session. The international site (monkeycode-ai.net) is another provider with its own account; credentials are not interchangeable between the two.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "This is for the international site (monkeycode-ai.net) account: paste the international site's session. The China site (monkeycode-ai.com) is another provider with its own account; credentials are not interchangeable between the two.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Select the CatPaw client's login-state file auth.json (Windows: C:\\Users\\\\.meituan-catpaw\\auth.json; macOS / Linux: ~/.meituan-catpaw/auth.json). After import the credentials live on the gateway and can be forwarded independently — no longer dependent on this machine's client.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Select the Cline client's login-state file providers.json (Windows: C:\\Users\\\\.cline\\data\\settings\\providers.json; macOS / Linux: ~/.cline/data/settings/providers.json). After import the credentials live on the gateway and can be forwarded independently — no longer dependent on this machine's client; this record goes into {label}.", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "Select the KukuAI client's Cookies file (%APPDATA%\\baidugenflowpro\\Network\\Cookies): it is a **binary** SQLite database (no extension, not JSON). The import reads a copy of the file you selected and does not compete with the running client for the lock, so **you do not need to close the client first**. After import the credentials live on the gateway and can be forwarded independently.", "选择凭证文件导入": "Import from credential file", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "Select the official client's session credential file (workbuddy-desktop.info / workbuddy-desktop-ai.info) or an account JSON exported by wb2api (nested or flat).", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Select the Raccoon client's login-state file auth.json (Windows: C:\\Users\\\\.box-agent\\config\\auth.json; macOS / Linux: ~/.box-agent/config/auth.json). After import the credentials live on the gateway and can be forwarded independently — no longer dependent on this machine's client.", "选择提供商": "Select provider", "选择的文件不是合法 JSON": "The selected file is not valid JSON", "选择要添加账号的提供商": "Select the provider to add an account for", "重新扫描": "Rescan", "鉴权": "Authentication", "阿里云 Token Plan 套餐(国际站)": "Alibaba Cloud Token Plan (International site)", "阿里云百炼 Coding 套餐(国内站)": "Alibaba Cloud Model Studio Coding plan (China site)", "阿里云百炼 Coding 套餐(国际站)": "Alibaba Cloud Model Studio Coding plan (International site)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "Alibaba Cloud Model Studio model service (International site, OpenAI-compatible mode)", "需要图形验证码:登录窗口已弹出,请填写后继续": "Captcha required: the sign-in window has opened; fill it in to continue", "预置 API": "Preset API", "领取 CodeArts 每日福利": "Claim CodeArts daily welfare", "领取失败:{message}": "Claim failed: {message}", "领取并让官方确认": "Claim and await confirmation", "风控验证配置不完整,请稍后重试": "Risk-control verification config is incomplete; try again later", "验证码": "Verification code", "验证码已发送。收到后填入下方并点「登录并添加」": "Code sent. Enter it below and click \"Sign in and add\"", "验证码已发送,请查看手机短信": "Code sent; check your SMS", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "Code sent; check your SMS. Enter it below and click \"Sign in and add\" to finish signing in", "验证码已发送,请查看短信": "Code sent; check your messages", "验证码校验失败,请重试": "Code verification failed; try again", "验证码校验超时,请重试": "Code verification timed out; try again", "验证码组件不可用,请重试": "Verification component unavailable; try again", "验证码组件初始化超时,请重试": "Verification component initialization timed out; try again", "验证码组件加载失败,请检查网络后重试": "Verification component failed to load; check your network and try again", "验证码组件加载异常,请重试": "Verification component encountered a loading error; try again", "验证码组件加载超时,请检查网络后重试": "Verification component timed out while loading; check your network and try again", "验证码组件未加载,请重启应用后重试": "Verification component not loaded; restart the app and try again", "(免费额度池,模型名带 cline-free/ 前缀)。": " (free quota pool; model names carry the cline-free/ prefix).", "(其中 {n} 把恢复为不限制)": " ({n} of which are now unrestricted)", "(必填)": " (Required)", "(有效期 {window})": "(valid {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": " (subscription pool; model names carry the cline-pass/ prefix and the account needs the matching subscription).", ",下一次最快 {minutes} 分钟后": ", earliest next attempt in {minutes} min", ",并从 {n} 把 Key 的可用提供商里移除": ", and removed it from the allowed providers of {n} keys" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · Models: {head}{rest}", " 等 {n} 个": " ({n} total)", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "Google refresh token starting with 1// (you can also paste the whole refresh_token=… line)", "11 位大陆手机号": "11-digit mainland China mobile number", "1~64 个字符,账号列表里按它分组显示": "1-64 characters; accounts are grouped by it in the account list", "6 位数字": "6 digits", "

  • 没有可自动领的活动
  • ": "
  • No campaigns can be claimed automatically
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    What you receive is plan gift points, which do not add to the welfare model token pool; ", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "The Anthropic-compatible endpoint is https://api.deepseek.com/anthropic (fill it in when you switch the protocol to anthropic)", "Anthropic 协议填根地址,不要带 /v1": "For the Anthropic protocol, use the root URL without /v1", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw China edition", "AutoClaw 国际版": "AutoClaw International edition", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS is required; paste the **full Cookie** (a Cookie editor can export it in one click) — the **PTOKEN must be kept**, as the gateway uses it to exchange for a KukuAI business session token from Baidu; without it, model refresh reports \"Not signed in\". A full Cookie header, a JSON array exported by a Cookie editor, or a {BDUSS, STOKEN} object are all supported. KukuAI has no refresh mechanism, so once the login state expires, just paste it again.", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=… (or the JSON exported by a Cookie editor)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "CatPaw's X-Passport-Token (login-state Cookie)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Get the Cline Pass API Key at app.cline.bot (subscription-based); the endpoint is OpenAI-compatible, the model catalog follows the Cline console, and model names are added under Model management with the plain name (e.g. glm-5.2 / kimi-k2.7-code / deepseek-v4-pro); the upstream validates the client shape, so the required client request headers are preset on this card", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT (three dot-separated segments)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT (three dot-separated parts; you can also paste a whole Bearer line or the data.bin content)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT (three dot-separated parts; a whole chatglm_token=… line works too)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode International edition", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM managed endpoint; apply for the Key at integrate.api.nvidia.com", "OfficeAce 果办": "OfficeAce", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken is Accio's login credential (a long opaque token, not a JWT); refreshToken is optional and enables automatic renewal on expiry. Enter the credential of the {label} account — {siteNote} (the easiest way to get it: just use \"Web login\" above; no need to hunt for the token manually.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken is Trae's Cloud-IDE-JWT (three dot-separated segments), and refreshToken enables automatic renewal on expiry (this provider rotates refreshToken on every use: once exchanged, the old one is void, so do not refresh the same account from two programs at once).
    When pasting manually, fill in machineId / deviceId as well: upstream ties them to the device public key uploaded at sign-in to identify the device, and swapping in a new pair from nowhere triggers the 2xxxx family of device-binding rejections.
    Without these three, the proper route is \"Web login\" above; for container / remote deployments, paste the callback URL from the address bar as prompted.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "The value of monkeycode_ai_session (you can also paste the whole Cookie)", "ms- 开头的 API 令牌": "API token starting with ms-", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken is optional and enables automatic renewal on expiry; both can be obtained from the Raccoon client login-state file.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken is optional and enables automatic renewal; both can be obtained from the client login-state file. The same Cline account works in both pools; here it is grouped under {label}.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token supports the enc: prefix (decrypted automatically on Windows). Without a refreshToken, automatic renewal is not possible.", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "token is the login-state Cookie; CatPaw has no refresh mechanism, so sign in again in the client after it expires.", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "API Key starting with user_ (you can also paste the whole Authorization: Bearer … line)", "{label} 网页登录的打开方式": "How to open {label} web login", "{label} 账号地区": "{label} account region", "{label} 账号的添加方式": "How to add a {label} account", "{name} 不是合法 JSON:{reason}": "{name} is not valid JSON: {reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name} requires a JSON object (like {sample})", "{n} 个账号": "{n} accounts", "{n} 个账号,点击添加": "{n} accounts, click to add", "{seconds}s 后重发": "Resend in {seconds}s", "✅ {label}账号已添加": "✅ {label} account added", "✅ {label}账号已添加{name}": "✅ {label} account added{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ Imported {n} providers from cc-switch", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ Created custom provider \"{name}\" and added an account", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ Deleted custom provider \"{name}\"{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ Updated the existing account{name} (one account per API key; re-adding merges into it)", "✅ 登录成功,{edition}账号已加入列表": "✅ Signed in; {edition} account added to the list", "✅ 领取成功:{planId}{period}": "✅ Claim successful: {planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " One provider can hold multiple keys, rotated by priority.", "「{name}」的账号添加功能还在开发中,敬请期待。": "Adding accounts for \"{name}\" is still in development — stay tuned.", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "One Key works across many vendors; use the full \"vendor/model\" name (e.g. deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "Leave blank when the upstream needs no authentication, and check the option below (blank without the checkbox counts as no credential configured)", "上游信息": "Upstream info", "不可领({status})": "Not claimable ({status})", "不支持导入": "Import not supported", "不是有效的凭证文件:内容要是一个 JSON 对象": "Not a valid credential file: the content must be a JSON object", "不是有效的凭证文件:需要包含 accessToken 与 uid": "Not a valid credential file: accessToken and uid are required", "不是自定义提供商": "Not a custom provider", "不需要 Key:转发与拉取模型都不发送鉴权头": "No Key needed: neither forwarding nor model fetching sends auth headers", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "No sign-in needed: click the button below and the gateway will obtain a guest credential from Zhipu Qingyan directly and add it to the account list (you can fill in a note name first). The guest credential can be used for chat right away; the free quota is issued by the upstream per device.

    Note: a guest account has no points system — its member points, daily sign-in points and activity claim endpoints all require sign-in, so those capabilities are skipped for guests (no readings are shown on the accounts page or in the check-in center). To get points, use \"Fill in credentials\" to paste a signed-in account token, or \"Import desktop sign-in state\".", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "Both editions' accounts can be saved at once, each with its own model catalog (the China and International editions are two providers that can be enabled and mapped separately).", "中国版": "China edition", "今天没有需要领的活动(都已到账)": "No campaigns to claim today (all already credited)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "Tried {attempts} times today (Beijing time {day}); {left} attempts left{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "Grab three items from another machine (or from the OfficeAce desktop app's models.json) and paste them here: the model gateway base URL (baseUrl, shaped like https://modelgw-…/v2) plus modelAppKey / modelAppSecret. These three are enough to forward requests (the gateway credential never expires); the control-plane temporary credentials (accessKeyId and so on) are optional — leaving them blank disables balance queries and auto-renewal but does not affect forwarding.", "从本机导入桌面端登录态": "Import desktop login state from this machine", "任务镜像 id": "Task image id", "余额查询": "Balance query", "使用 Google 账号登录": "Sign in with Google", "使用 Zai 账号登录": "Sign in with Zai", "使用个人访问令牌(PAT)": "Use a personal access token (PAT)", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "Free models need no Key (\"This upstream needs no authentication\" is checked by default, and the gateway uses anonymous credentials automatically); for paid models, enter your Zen API Key. The free tier only accepts the official client form, so \"Emulate the official OpenCode client\" is on by default", "内嵌窗口": "Embedded window", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "Opens in the embedded window; closing it cancels the wait (if a Google account is rejected, switch to the system browser)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "Opens in the embedded window; added to the list when done; closing it cancels the wait", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "Opens in an embedded window; the account is added automatically once you have scanned — closing the window cancels the wait", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "The embedded window uses a fresh environment, so multiple accounts do not affect each other; closing it cancels the wait", "内嵌窗口(推荐)": "Embedded window (recommended)", "准备验证…": "Preparing verification…", "凭据 JSON": "Credential JSON", "凭证文件在哪?": "Where is the credential file?", "创建并添加账号": "Create and add account", "创建这个提供商,并同时建立它的第一个账号。": "Create this provider and its first account in one step.", "删除功能不可用(脚本未就绪)": "Delete is unavailable (script not ready)", "删除失败:{reason}": "Delete failed: {reason}", "删除此提供商": "Delete this provider", "及 {n} 个账号": " and {n} accounts", "发送中…": "Sending…", "发送失败:{message}": "Send failed: {message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "Send unconfirmed: the sign-in window has opened; complete the sign-in manually in that window", "取消失败:{message}": "Cancel failed: {message}", "取消等待": "Cancel sign-in", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "Only the Embedded window can restore third-party options: we cannot modify the sign-in page in the system browser", "可选": "Optional", "可选(cloudaicompanionProject):留空由网关自动发现": "Optional (cloudaicompanionProject); if blank, the gateway discovers it automatically", "可选,展示用": "Optional; for display", "可选,没有则无法自动续期": "Optional; without it, automatic renewal is not possible", "可选,留空使用凭据里的 user_name": "Optional; defaults to the user_name in the credential", "可选,留空使用账号姓名、邮箱或令牌指纹": "Optional; defaults to the account name, email, or token fingerprint", "可选,留空使用账号昵称或邮箱": "Optional; defaults to the account nickname or email", "可选,留空则用 key 尾号": "Optional; defaults to the key suffix", "可选,留空则用 userId": "Optional; defaults to userId", "可选,留空则用上游账号昵称": "Optional; if left blank, the upstream account's nickname is used", "可选,留空则用上游返回的账号名或账号 id": "Optional; defaults to the account name or account id returned by upstream", "可选,留空则用凭证里的账号名": "Optional; defaults to the account name in the credential", "可选,留空则用文件里的昵称": "Optional; leave empty to use the nickname from the file", "可选,留空则用登录名或 uid": "Optional; defaults to the login name or uid", "可选,留空则用脱敏手机号": "Optional; defaults to the masked phone number", "可选,留空则用脱敏手机号或 userId": "Optional; defaults to the masked phone number or userId", "可选,留空则用账号 uk": "Optional; defaults to the account uk", "可选,留空则用账号昵称": "Optional; defaults to the account nickname", "可选,留空则用账号昵称或 userId": "Optional; leave blank to use the account nickname or userId", "可选,留空则用邮箱或令牌尾号": "Optional; defaults to the email or token suffix", "可选,留空用「OfficeAce 果办」": "Optional; defaults to “OfficeAce”", "可选,留空自动生成": "Optional; generated automatically if blank", "可选,留空自动用昵称": "Optional; defaults to the nickname", "可选,给这个访客账号起个备注名": "Optional; a note name for this guest account", "可选,续期时带上": "Optional; sent when renewing", "可选,讯飞侧 userid": "Optional; the userid on the iFlytek side", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "Optional; required to start a conversation. If blank, the gateway discovers it automatically from this account's existing tasks; if it cannot find one, fill it in manually later.", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "Optional; the account email, used for display and to recognize the identity (the same account is recognized even after switching to a new token)", "可选;UUID 形态,与凭据同生共死": "Optional; UUID form, lives and dies with the credential", "可选;填了才能到期自动续期": "Optional; required for automatic renewal on expiry", "可选;用于去重与展示名(留空时网关会问一次上游)": "Optional; used for deduplication and the display name (when blank, the gateway asks upstream once)", "可选;用于生成账号 id 与展示名": "Optional; used to generate the account id and display name", "可选;纯数字串(上游只收 8–24 位数字)": "Optional; digits only (upstream accepts only 8–24 digits)", "可领取": "Claimable", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "Keyed and no-auth accounts can coexist in one provider, each routed by its own rules; multiple no-auth accounts are allowed too (each with its own egress proxy)", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "Switch the protocol to anthropic on the same address to use its Claude-compatible endpoint. Forwarding requires an OpenCode Go API Key (subscription-based; fetching the model catalog needs no Key, but requests get a 401 \"Missing API key\" from upstream)", "响应为空": "Empty response", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "SenseNova's OpenAI-compatible endpoint; balance query uses the console account and password (see \"Balance query\" below)", "国内版": "China edition", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "The China edition and **the International edition are two separate sets of accounts and plans**; credentials and claimed plans do not carry over between them.", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "The China edition's sign-in page has no Google / GitHub options (it uses WeChat / phone / email sign-in)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "The China edition's sign-in site is www.accio-ai.com, a different site from the International edition's.", "国内版(WorkBuddy)": "China edition (WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "China site: https://api.siliconflow.cn/v1", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "China site (minimaxi.com); the OpenAI-compatible address is https://api.minimaxi.com/v1", "国际版": "International edition", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "The International edition z.ai Coding plan; the OpenAI-compatible address is https://api.z.ai/api/coding/paas/v4", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "The International and China editions are **two separate sets of accounts** (two sites of the same account system); credentials do not carry over.", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "The International and China editions have separate account systems; enter the International edition's credentials. Without a refreshToken, automatic renewal is not possible.", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "The International edition's sign-in page shows only email sign-in by default; checking this restores the Google / GitHub / X options", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "The International edition's inference site is api.z.ai, a different site from the China edition's; plans are separate as well.", "国际版(WorkBuddy AI)": "International edition (WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "International site Coding plan; the OpenAI-compatible address is https://api.minimax.io/v1", "在 cc-switch 里找到": "Found", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "Complete the official sign-in in the embedded window; the account is added to the list automatically on success.", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "Generate a PAT in the Qoder account settings → Integrations for {label} (do not use a Google / GitHub token). Accounts and credentials do not carry over between the two regions.", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "Scan the WeChat QR code on the official authorization page that opens (the QR code appears right away). The account is added to the list automatically after a successful scan.", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "In the window that opens, sign in to the KukuAI main site with your Baidu account (SMS code or QR scan both work); the account is added to the list automatically on success. The gateway exchanges it with Baidu for a KukuAI business session token (requires the KukuAI client installed on this machine).", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "Sign in with your Google account in the window that opens (Antigravity's authorization page); the account is added to the list automatically once authorization completes.", "在浏览器中打开登录页": "Open the sign-in page in your browser", "地区": "Region", "填写凭证": "Enter credentials", "填写凭证添加": "Enter credentials to add", "备注名": "Label", "套餐": "Plan", "如:智谱 GLM": "e.g. Zhipu GLM", "完成登录后自动加入账号列表,昵称取自上游。": "Added to the account list automatically after sign-in; the nickname comes from upstream.", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "Official client credential directory: Windows — C:\\Users\\\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth; macOS — ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "Officially confirmed as credited", "导入": "Import", "导入中…": "Importing…", "导入凭证文件": "Import credential file", "导入失败": "Import failed", "导入失败:{reason}": "Import failed: {reason}", "导入所选": "Import selected", "导入所选({n})": "Import selected ({n})", "导入桌面端登录态": "Import desktop login state", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "The embedded window will open; the account is added to the list automatically once authorization completes. Closing the window cancels the wait. The authorization page may end with a message that it cannot open the zcode:// link — that is normal; the result has already been recorded server-side", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "The embedded window will open; the account is added to the list automatically once authorization completes. On a remote panel you can paste the callback URL. Closing the window cancels the wait. The link is valid for 5 minutes; if it times out or is not clicked, it is voided (you can start again)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "The embedded window will open; the account is added to the list automatically after sign-in. Closing the window cancels the wait", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "The authorization page will open in your system default browser (reusing the Trae account already signed in there); on the same machine the account is added automatically when done. For Docker / remote panels, paste the callback URL from the address bar as prompted.", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "The authorization page will open in your system default browser (reusing the ZCode account already signed in there); the account is added to the list automatically once authorization completes. A final message that the zcode:// link cannot be opened is normal", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "The authorization page will open in your system default browser (reusing the Huawei Cloud account already signed in there); the gateway polls the cloud for the authorization code, so it does not matter which machine the browser runs on. The account is added to the list automatically once done", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "The authorization page will open in your system default browser (reusing the Huawei Cloud account already signed in there); when the browser and the gateway are not on the same machine, paste the final callback URL back into the panel as described above", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "The sign-in page will open in your system default browser (reusing the Accio account already signed in there); the account is added to the list automatically after sign-in, and closing the popup cancels the wait", "小米 MiMo Token Plan 套餐(新加坡站)": "Xiaomi MiMo Token Plan (Singapore site)", "已到账": "Credited", "已取消登录等待": "Pending sign-in canceled", "已取消领取": "Claim canceled", "已取消验证码": "Verification canceled", "已填写手机号,正在发送验证码…": "Phone number entered; sending the code…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "Marked as needing no authentication: the account is routed normally, and no auth headers are sent outbound", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "Imported {ok}, failed {fail} (failed items are marked in the list)", "已建过 · {n} 个账号,点击继续添加": "Already created · {n} accounts, click to add more", "已建过,点击继续添加账号": "Already created, click to add another account", "已打开官方登录页,请在窗口中完成登录…": "Official sign-in page opened; complete sign-in in the window…", "已点发送,等待短信…": "Sent; waiting for the SMS…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "Sign-in page opened in your system default browser; complete sign-in in the browser…", "已领取,等官方确认": "Claimed, awaiting official confirmation", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "This app version does not support AutoClaw web login; update the app", "当前没有可领取的套餐(活动尚未开始)": "No plans are available to claim right now (the event has not started yet)", "当前环境不支持领取(桥接方法缺失)": "Claiming is not supported in this environment (bridge method missing)", "必填,CatPaw 账号标识": "Required; CatPaw account identifier", "恢复 Google / GitHub 入口": "Restore Google / GitHub options", "手机号": "Phone number", "手机验证码登录": "SMS code login", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "Open the official authorization page for Trae SOLO (trae.cn) and sign in with your Trae account: once authorized, the official page redirects back to a temporary port on this machine; a same-machine deployment receives it automatically, while Docker / remote panels should copy the callback URL from the address bar as prompted.", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "Open the official sign-in page for Accio {label} ({site}) and sign in with your Accio account: on success the official page redirects back to this machine; a same-machine setup completes automatically, while Docker / remote panels just paste the callback URL as prompted (the authorization code is passed to the gateway only on this machine, and no plaintext token is shown in the UI).", "打开 Accio {label}登录页": "Open the Accio {label} sign-in page", "打开 Antigravity 网页登录": "Open Antigravity web login", "打开 CatPaw 网页登录": "Open CatPaw web login", "打开 Cline 授权页": "Open Cline authorization page", "打开 CodeArts 授权页": "Open CodeArts authorization page", "打开 Qoder 网页登录": "Open Qoder web login", "打开 Trae 授权页": "Open Trae authorization page", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "Open the official authorization page for ZCode {label} and sign in with your account. The authorization result is recorded by the ZCode server; the gateway fetches the credential in the background and adds the account to the list.", "打开 ZCode {label}授权页": "Open the ZCode {label} authorization page", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "Open the official Huawei Cloud CodeArts authorization page to sign in: once done, the official page brings the browser back to the gateway's own /oauth/callback, and the gateway exchanges the one-time authorization code for temporary credentials and adds the account to the list.
    When the gateway runs on another machine, the web UI prompts you to paste the final callback URL from the address bar back into the panel.", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "Open the Huawei Cloud authorization page and sign in: once finished, the gateway automatically polls the cloud for the authorization code and adds the account to the list (no OfficeAce desktop app required, and no need to paste a callback URL back manually).", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "Open the official authorization page and complete the device-code authorization; you will be signing in to a {label} ({site}) account.", "打开授权页": "Open the authorization page", "打开授权页完成确认,账号自动加入 {label}{note}": "Open the authorization page and confirm; the account is added to {label} automatically{note}", "打开方式": "Open with", "打开网页登录": "Open web login", "探测失败:{message}": "Probe failed: {message}", "接入一个兼容上游": "Connect a compatible upstream", "提交中…": "Submitting…", "搜索提供商": "Search providers", "搜索提供商…": "Search providers…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "Paste the whole credential JSON written to disk by the official plugin / CLIProxyAPI (like {\"codearts_provider_credential\":{…}}; a flattened form also works).
    Required: access_key_id, secret_access_key, security_token.For automatic renewal you must paste refresh_token and oauth_context as well — temporary credentials expire in about an hour, and without that half they cannot be renewed; you would have to sign in again.", "文件是{edition}凭证,已按该版本导入": "The file contains {edition} credentials and has been imported as that edition", "新建自定义提供商": "New custom provider", "方案:{label}": "Scheme: {label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "Plaintext JWT, or the enc: encrypted value in auth.json (decrypted automatically)", "明文 JWT(国际版账号的 access token)": "Plaintext JWT (the access token of an International edition account)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "Zhipu's bigmodel.cn Coding plan; get the Key at open.bigmodel.cn/usercenter/apikeys", "未知错误": "Unknown error", "未能获取授权地址,请重试": "Could not get the authorization URL; try again", "未能读取 cc-switch 数据": "Could not read cc-switch data", "未领取成功": "Claim unsuccessful", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "Check this for upstreams like local Ollama or the OpenCode Zen free tier; otherwise the account cannot be used", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "This provider has two credentials that **do not replace each other**; fill in the one(s) for the features you need, at least one: the Coding Plan API Key is used for forwarding inference (hits {site}) and for querying the window limits (the remaining percentage of each N-hour / weekly window); the jwt is used for claiming plans and querying balance (hits the billing gateway at zcode.z.ai; officially called a Coding Plan JWT, a three-segment dot-separated string). Either one can query balance, but they read different things: the jwt reads the balance buckets and the plan expiry, while the API Key reads the window limits; and claiming only accepts the jwt, forwarding only accepts the API Key. Please enter the credentials for the {label} account — {plan} (the easiest way: just use \"Web login\" above — it exchanges this API Key for you and gets both credentials at once.)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "The local Ollama OpenAI-compatible endpoint; no API Key needed (\"This upstream needs no authentication\" is checked by default, and no auth headers are sent at all)", "本次未确认到账": "Not confirmed as credited this time", "条可导入": "are importable", "条配置,其中": "configs in cc-switch, of which", "桌面运行时不可用(Tauri 未初始化)": "Desktop runtime unavailable (Tauri not initialized)", "模型网关基址": "Model gateway base URL", "正在打开百度登录页…": "Opening the Baidu sign-in page…", "正在扫描本机 cc-switch…": "Scanning cc-switch on this machine…", "正在换发访客凭证…": "Requesting a guest credential…", "正在添加…": "Adding…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "Waiting for {name} sign-in to finish; you can start a new sign-in only after it completes or is canceled", "每周": "Weekly", "每日": "Daily", "每月": "Monthly", "没有则无法自动续期": "Without it, automatic renewal is not possible", "没有匹配「{keyword}」的提供商": "No providers match \"{keyword}\"", "添加 {name} 账号": "Add {name} account", "添加中…": "Adding…", "添加到 ": "Add to ", "添加失败:{reason}": "Add failed: {reason}", "添加小浣熊账号": "Add Raccoon account", "添加方式": "Add method", "添加访客账号": "Add a guest account", "添加账号": "Add account", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "Volcano Engine Coding plan; the general inference endpoint is https://ark.cn-beijing.volces.com/api/v3", "点击添加账号": "Click to add an account", "点开即预填,填 Key 接入": "Opens prefilled; enter your Key to connect", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "After clicking the button, first pass a slider verification (the vendor's risk control), then the sign-in page opens and the account is added automatically once you sign in.
    This is the only official sign-in method for the International edition; if you are already signed in to the client, \"Import desktop login state\" is faster.", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "Sign in with the phone number bound to your AutoClaw account: click \"Get code\", then enter the SMS code below and sign in. The code is submitted from this machine directly to the official API; no token is shown in the UI.", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "Sign in with your CatPaw account (Meituan Passport); the account is added to the list automatically on success.", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "Sign in with the phone number bound to your Loomy account: click \"Get code\" and enter it. This is the easiest way in for this provider.", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "Used for forwarding; two dot-separated segments like apiKey.secret (if left blank, this account cannot forward)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "Used for claiming plans and querying balance; if left blank, this account cannot claim or check balance", "用户 ID": "User ID", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "Sign in with your bound phone number: click \"Get code\" and enter it. This is the only official sign-in method for the China edition.", "留空则用提供商名称": "Leave blank to use the provider name", "登录 / 添加 {name} 账号": "Sign in / add {name} account", "登录 session(一长串)": "Login session (a long string)", "登录中…": "Signing in…", "登录失败:{message}": "Sign-in failed: {message}", "登录已结束": "Sign-in has ended", "登录并添加": "Sign in and add", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "Login-state file path: ~/.box-agent/config/auth.json (Windows: C:\\Users\\\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "Delete custom provider \"{name}\"? This will also delete {count} accounts under it; deletion cannot be undone.", "等待 Accio {label}登录完成…": "Waiting for Accio {label} sign-in…", "等待 CatPaw 登录完成…": "Waiting for CatPaw sign-in…", "等待 Cline 授权确认…": "Waiting for Cline authorization confirmation…", "等待 CodeArts 登录完成…": "Waiting for CodeArts sign-in…", "等待 Google 授权完成…": "Waiting for Google authorization…", "等待 KukuAI 登录完成…": "Waiting for KukuAI sign-in…", "等待 OfficeAce 登录完成…": "Waiting for OfficeAce sign-in…", "等待 OrcaTerm 登录完成…": "Waiting for OrcaTerm sign-in…", "等待 Qoder 授权完成…": "Waiting for Qoder authorization…", "等待 Trae 授权完成…": "Waiting for Trae authorization…", "等待 ZCode {label}授权完成…": "Waiting for ZCode {label} authorization…", "等待小浣熊登录完成…": "Waiting for Raccoon sign-in…", "等待登录完成…": "Waiting for sign-in…", "等待网页登录…": "Waiting for web login…", "粘贴 API Key": "Paste API Key", "粘贴 API 令牌": "Paste API token", "粘贴 Accio 的 accessToken": "Paste the Accio accessToken", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Paste Antigravity's Google refresh token (starts with 1//; pasting the whole line containing refresh_token= also works).
    This is a manual entry besides web login (for example, exported from the official IDE you are already signed in to). The refresh token does not expire, and the gateway renews the access token automatically when it expires; if the token is lost, you can only go through Google authorization again, so keep it safe.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Paste the Command Code API Key (starts with user_; get it from the official CLI's ~/.commandcode/auth.json or the web studio). Pasting the whole line / with quotes / with the Bearer prefix all work; the gateway strips it down to the bare key itself. The key does not expire and there is no renewal API, so if it stops working just get a new one. When adding, the gateway runs a lightweight liveness check; a failure does not affect adding.", "粘贴 Cookie": "Paste Cookie", "粘贴 Google refresh token": "Paste Google refresh token", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "Paste OrcaTerm's OAuth accessToken (a JWT with three dot-separated parts; available from the desktop client's data.bin or the web version's ot_session cookie). Pasting a whole line containing Bearer / ot_session= is fine too — the gateway strips it down to the bare token. After adding, the gateway renews it automatically (the upstream has a renewal API), so you do not need to follow the 2-hour expiry by hand.", "粘贴 Qoder 个人访问令牌(pt-…)": "Paste the Qoder personal access token (pt-…)", "粘贴 accessToken": "Paste accessToken", "粘贴 access_token(一长串 JWT)": "Paste access_token (a long JWT)", "粘贴 session cookie": "Paste session cookie", "粘贴 token / refreshToken": "Paste token / refreshToken", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "Paste a token starting with workos:… (the prefix is added automatically if missing)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "Paste a Zhipu Qingyan access token (a JWT with three dot-separated parts). How to get it: open chatglm.cn in a browser, sign in, then copy the value of the chatglm_token cookie from Application → Cookies in the developer tools (pasting the whole chatglm_token=…; line works too). It is verified against the upstream once after pasting, and the account is only saved if that passes; signed-in accounts get points and sign-in capability, and the gateway renews it automatically afterwards (the upstream has a renewal API).", "粘贴登录凭据": "Paste login credentials", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "What you paste is the login session (which is also the model gateway token). Loomy has no renewal API; the session is valid for about 14 days, so just sign in again after it expires.", "粘贴网关凭据": "Paste gateway credentials", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "Paste the value of the web session cookie monkeycode_ai_session (copying the whole Cookie in the browser and pasting it directly also works; the gateway extracts the value itself).
    {siteNote}
    MonkeyCode has no renewal API: the session is valid for about 30 days (a hard limit); once it expires, sign in to the web page again and paste it one more time.", "粘贴访问令牌": "Paste an access token", "系统浏览器": "System browser", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "The system browser can reuse an existing login state (recommended for the International edition); the embedded window is cleaner.", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "Opens in the system browser (reuses the signed-in Cline account); added to the list when done", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "Opens in the system browser (reuses the Google account already signed in); added to the list when done", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "Opens in the system browser (reuses the signed-in Zai / Google account); added to the list when done", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "Opens in the system browser (reuses the signed-in Meituan account); added to the list when done", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "Opens in the system browser (reuses a signed-in account); added to the list when done", "系统默认浏览器": "System default browser", "编码套餐 API Key": "Coding Plan API Key", "网关 Secret": "Gateway secret", "网页登录": "Web login", "网页登录的打开方式": "How to open web login", "网页登录(Zai / Google)": "Web login (Zai / Google)", "自定义": "Custom", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "Self-hosted aggregation panel: fill in your own site address. Balance query calls {base}/v1/usage with this account's API key; no extra setup", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "Self-hosted aggregation panel: fill in your own site address; balance query additionally needs a NewAPI personal access token (see \"Balance query\" below)", "获取风控配置失败,将直接尝试领取:{message}": "Failed to get the risk-control config; trying to claim directly: {message}", "获取验证码": "Get code", "访客模式": "Guest mode", "访客模式(免登录)": "Guest mode (no sign-in)", "该上游无需鉴权(不发送鉴权头)": "This upstream needs no authentication (no auth headers are sent)", "该提供商": "This provider", "该提供商账号添加功能即将上线": "Account adding for this provider is coming soon", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "This custom provider no longer exists (it may have been deleted); refresh and try again", "请先选择一个自定义提供商": "Select a custom provider first", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "Complete the verification in the slider popup (a risk-control step required by the vendor)", "请填写 11 位大陆手机号": "Enter an 11-digit mainland China phone number", "请填写 6 位数字验证码": "Enter the 6-digit code", "请填写 Base URL": "Enter the Base URL", "请填写 {label}": "Enter {label}", "请填写名称": "Enter a name", "请完成验证…": "Complete the verification…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "Reads and decrypts %APPDATA%/AutoClaw/auth.json; Windows only", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "Reads ~/.cline/data/settings/providers.json; requires being signed in to the Cline client", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "Reads ~/.meituan-catpaw/auth.json; requires being signed in to the CatPaw client", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "Reads the local KukuAI client login state (%APPDATA%\\baidugenflowpro\\Network\\Cookies); requires being signed in to the KukuAI client", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "Read the local OrcaTerm client sign-in state (%APPDATA%\\com.orcaterm-desktop.app\\data.bin); the OrcaTerm client must be signed in", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "Read the local Zhipu Qingyan client sign-in state (%APPDATA%\\chatglm\\Network\\Cookies); the client must be signed in", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "Reads the account currently logged in to the official client (Tencent WorkBuddy / WorkBuddy AI) on this machine: the newest session file in its credential directory is located automatically (the official client must be logged in on this machine). The gateway renews the token after import — no need to swap tokens manually with the 2-hour expiry.", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "Reads the local client's current login state (plaintext Cookie, no decryption needed). The Cookies file is exclusively locked while the client runs, so close the KukuAI client before importing.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state).", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state). After signing in again in the client, click \"Refresh token\" to sync.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state). After signing in again in the client, just re-import.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state). Users who sign in to the client with Zai / Google should use this one.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "Reads the local client's current login state live each time (deleting this record does not affect the client's login state). This one is grouped under {label}.", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "Reads the OAuth token the local client is currently signed in with (plain-text JSON, no decryption needed). After importing, the gateway renews it automatically — no need to follow the client's 2-hour expiry by hand.", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "Read the current sign-in state of the local client. The client's cookies are DPAPI-encrypted (Chromium os_crypt), so this is Windows-only; the file may be unreadable while the client is running — quit the client and retry (or use \"Fill in credentials\" to paste a token instead).", "账号信息": "Account info", "账号信息不完整,请刷新后重试": "Account info is incomplete; refresh and try again", "账号已添加,但请留意:{warning}": "Account added, but note: {warning}", "账号版本": "Account edition", "账号类型": "Account type", "账号:{name}
    ": "Account: {name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "Routes through Inference Providers; create the Key at hf.co/settings/tokens", "还没有账号": "No accounts yet", "这一家当前不支持网页登录,请改用填写凭证": "This provider does not support web login right now; use Enter credentials instead", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "This account has no campaigns that can be claimed automatically right now (only the daily login gift points are claimed automatically)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "This quota goes through the Start Plan channel: if forwarding reports that the Coding Plan has expired, ", "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "This is for the China site (modelscope.cn) account: paste the China site's token. The international site (modelscope.ai) is another provider with its own account; tokens are not interchangeable between the two.", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "This is for the China site (monkeycode-ai.com) account: paste the China site's session. The international site (monkeycode-ai.net) is another provider with its own account; credentials are not interchangeable between the two.", "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "This is for the international site (modelscope.ai) account: paste the international site's token. The China site (modelscope.cn) is another provider with its own account; tokens are not interchangeable between the two.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "This is for the international site (monkeycode-ai.net) account: paste the international site's session. The China site (monkeycode-ai.com) is another provider with its own account; credentials are not interchangeable between the two.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Select the CatPaw client's login-state file auth.json (Windows: C:\\Users\\\\.meituan-catpaw\\auth.json; macOS / Linux: ~/.meituan-catpaw/auth.json). After import the credentials live on the gateway and can be forwarded independently — no longer dependent on this machine's client.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Select the Cline client's login-state file providers.json (Windows: C:\\Users\\\\.cline\\data\\settings\\providers.json; macOS / Linux: ~/.cline/data/settings/providers.json). After import the credentials live on the gateway and can be forwarded independently — no longer dependent on this machine's client; this record goes into {label}.", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "Select the KukuAI client's Cookies file (%APPDATA%\\baidugenflowpro\\Network\\Cookies): it is a **binary** SQLite database (no extension, not JSON). The import reads a copy of the file you selected and does not compete with the running client for the lock, so **you do not need to close the client first**. After import the credentials live on the gateway and can be forwarded independently.", "选择凭证文件导入": "Import from credential file", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "Select the official client's session credential file (workbuddy-desktop.info / workbuddy-desktop-ai.info) or an account JSON exported by wb2api (nested or flat).", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Select the Raccoon client's login-state file auth.json (Windows: C:\\Users\\\\.box-agent\\config\\auth.json; macOS / Linux: ~/.box-agent/config/auth.json). After import the credentials live on the gateway and can be forwarded independently — no longer dependent on this machine's client.", "选择提供商": "Select provider", "选择的文件不是合法 JSON": "The selected file is not valid JSON", "选择要添加账号的提供商": "Select the provider to add an account for", "重新扫描": "Rescan", "鉴权": "Authentication", "阿里云 Token Plan 套餐(国际站)": "Alibaba Cloud Token Plan (International site)", "阿里云百炼 Coding 套餐(国内站)": "Alibaba Cloud Model Studio Coding plan (China site)", "阿里云百炼 Coding 套餐(国际站)": "Alibaba Cloud Model Studio Coding plan (International site)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "Alibaba Cloud Model Studio model service (International site, OpenAI-compatible mode)", "需要图形验证码:登录窗口已弹出,请填写后继续": "Captcha required: the sign-in window has opened; fill it in to continue", "预置 API": "Preset API", "领取 CodeArts 每日福利": "Claim CodeArts daily welfare", "领取失败:{message}": "Claim failed: {message}", "领取并让官方确认": "Claim and await confirmation", "风控验证配置不完整,请稍后重试": "Risk-control verification config is incomplete; try again later", "验证码": "Verification code", "验证码已发送。收到后填入下方并点「登录并添加」": "Code sent. Enter it below and click \"Sign in and add\"", "验证码已发送,请查看手机短信": "Code sent; check your SMS", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "Code sent; check your SMS. Enter it below and click \"Sign in and add\" to finish signing in", "验证码已发送,请查看短信": "Code sent; check your messages", "验证码校验失败,请重试": "Code verification failed; try again", "验证码校验超时,请重试": "Code verification timed out; try again", "验证码组件不可用,请重试": "Verification component unavailable; try again", "验证码组件初始化超时,请重试": "Verification component initialization timed out; try again", "验证码组件加载失败,请检查网络后重试": "Verification component failed to load; check your network and try again", "验证码组件加载异常,请重试": "Verification component encountered a loading error; try again", "验证码组件加载超时,请检查网络后重试": "Verification component timed out while loading; check your network and try again", "验证码组件未加载,请重启应用后重试": "Verification component not loaded; restart the app and try again", "(免费额度池,模型名带 cline-free/ 前缀)。": " (free quota pool; model names carry the cline-free/ prefix).", "(其中 {n} 把恢复为不限制)": " ({n} of which are now unrestricted)", "(必填)": " (Required)", "(有效期 {window})": "(valid {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": " (subscription pool; model names carry the cline-pass/ prefix and the account needs the matching subscription).", ",下一次最快 {minutes} 分钟后": ", earliest next attempt in {minutes} min", ",并从 {n} 把 Key 的可用提供商里移除": ", and removed it from the allowed providers of {n} keys" }); diff --git a/desktop-tauri/ui/i18n/en/checkin.js b/desktop-tauri/ui/i18n/en/checkin.js index 0584ca2d..ed30a8bd 100644 --- a/desktop-tauri/ui/i18n/en/checkin.js +++ b/desktop-tauri/ui/i18n/en/checkin.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:en/checkin —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "SOLO checkin_credits claims · reset at midnight (calendar day)", "UMID 组件安装失败:{error}": "UMID component installation failed: {error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy CN · Query the task tree, then light up / claim in one click · includes the school-season event and cat travel · click a row for details", "WorkBuddy 国际版保活模型,按顺序回退": "WorkBuddy International keep-alive models, tried in order", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "Free models for WorkBuddy International daily activity · one global setting, unrelated to schedules", "{date}(每天 {time})": "{date} (daily at {time})", "{label} ×{count}({reason})": "{label} ×{count} ({reason})", "{n} 项可完成": "{n} to complete", "{n} 项待领": "{n} to claim", "{total} 账号 · {done} 已签": "{done} of {total} checked in", "{total} 项任务 · {pending} 项可完成": "{total} tasks · {pending} to complete", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ UMID component installed — the next check-in can claim International points", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ Scheduled check-in enabled", "✅ 开学季任务执行完成": "✅ School-season tasks completed", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ Growth tasks completed: credits +{credit}, energy +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ Starter rewards claimed, {n} points earned in total", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ Check-in complete: {succeeded}/{total} accounts claimed successfully{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "The \"keep-alive model chain\" is the free models used to keep WorkBuddy International accounts active during daily activity runs — tried in order, stops at the first success; submit empty to restore the default ({defaults}). Same-day dedup + idempotent claiming: repeat runs only return \"already claimed\" and never add points twice.", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "The \"keep-alive model chain\" is the free models used to keep WorkBuddy International accounts active during daily activity runs — tried in order, stops at the first success; clearing the list and saving restores the default chain (current default: {defaults}). Same-day dedup + idempotent claiming: repeat runs only return \"already claimed\" and never add points twice.", "「免费领积分」的每日任务 · 逐个领取": "\"Free points\" daily tasks · claimed one by one", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "One-time rewards · queried and claimed automatically after check-in; once claimed they are recorded locally and no longer queried upstream · click a row to expand the task list", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "Claims all of the day’s rewards in one action (daily check-in + newcomer gift) · idempotency guaranteed by the upstream", "一键安装组件": "Install component", "一键完成": "Complete all", "一键领取({n})": "Claim all ({n})", "上次执行:{line}": "Last run: {line}", "上次签到时间": "Last check-in", "上次领取 {time} · 领取需通过滑块验证码": "Last claimed {time} · claim requires passing a slider CAPTCHA", "下次 {date}": "Next {date}", "下次 {date} · 点此管理条目": "Next {date} · click to manage schedules", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "Not in daily check-in: {list}. CodeArts one-time rewards are under \"Starter rewards\" below; its and ZCode's daily/plan benefits are claimed under \"Activity rewards\".", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "Not in daily check-in: {list}. CodeArts one-time rewards are under \"Starter rewards\" below, and its daily welfare is right above under \"Daily check-in\"; ZCode plan claims are under \"Activity rewards\".", "与国内版同一套任务接口 · 站点不同": "Same task API as the China edition · different site", "今天已领 {n} 份": "Claimed {n} today", "今天未领": "Not claimed today", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "Claimed today (Beijing time {day}) · {n} items confirmed received · can claim again tomorrow", "今日已执行": "Ran today", "今日已派出": "Sent out today", "今日已领取": "Claimed today", "今日签到": "Today", "今日签到进度": "Today's check-in progress", "从清单里移除": "Remove from the list", "保活": "Keep-alive", "保活 {n}": "{n} kept alive", "保活+领取": "Keep-alive + claim", "保活中…": "Keeping alive…", "保活模型链": "Keep-alive model chain", "全选": "Select all", "全部 {n} 家": "All {n} providers", "全部完成": "All done", "全部查询": "Query all", "全部结果": "All outcomes", "全部账号均可签到": "All accounts can check in", "全部领取": "All claimed", "关着:所有条目都不执行": "Off: no schedule runs", "删除失败:{error}": "Delete failed: {error}", "删除定时条目": "Delete schedule", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "At the scheduled time, automatically checks in the enabled accounts of the ticked providers (WorkBuddy CN uses the daily check-in API; the international version uses the daily-activity quest: probe the event, claim the daily-active reward, then keep alive with the free model and open a session over the web channel to light up the daily activity; Raccoon uses the desktop daily-points flow; AutoClaw uses the official client's daily check-in task; Qoder CN claims via the event, and accounts without an assigned event get a neutral notice; Qoder international needs a device risk-control identity (generated by the UMID component of the local Qoder client / qodercli) before the \"Daily 100 Credits\" event is even visible — without the component you get a clear explanation instead of an error; Trae claims SOLO's daily check-in points (reset at midnight), and when the upstream has no event for the account or the credentials lack a device ID you get \"not claimed + reason\" instead of an error; Loomy claims the first-login points once a day per account; KukuAI claims the \"Free points\" daily task; CodeArts claims the day's operational perks (claim → confirm → verify by re-reading; automatic runs are rate-limited to 6 write requests a day, 10 minutes apart); OfficeAce claims all of the day's rewards in one go (daily check-in + newcomer gift)). If the machine was off at the scheduled time, a catch-up check-in runs at boot, so nothing is missed. Every provider's check-in API is idempotent — running it again never claims twice.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "At the scheduled time, auto check-in runs for the available accounts of the selected providers (WorkBuddy China uses the daily check-in API; International uses daily activity tasks — detect the campaign, claim the daily-activity reward, then keep the account alive with free models; Raccoon uses the desktop daily points flow; AutoClaw uses the official client's daily check-in task; Qoder China uses campaign claims, and accounts with no campaign assigned get a neutral notice; Qoder International needs a device risk-control identity first (generated by the UMID component of the local Qoder client / qodercli) to see the \"Daily 100 Credits\" campaign, and a missing component yields a clear explanation instead of an error; Trae claims SOLO's daily check-in points (reset at midnight by calendar day), and when the upstream has no campaign for the account or the credential has no device ID the result is \"not claimed + the specific reason\" instead of an error; Loomy awards first-login points once a day per account; KukuAI claims the \"Free points\" daily tasks; CodeArts claims that day's campaign welfare (claim → confirm → read back to verify; automatic runs are limited to 6 write attempts per day with a 10-minute gap); OfficeAce claims all of that day's rewards in one action (daily check-in + newcomer gift)). If the machine was off at the scheduled time, the missed run is made up automatically after it starts — nothing is skipped just because the machine was off. Every provider's check-in API is idempotent, so running it again never claims twice.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "At the scheduled time, auto check-in runs for the available accounts of the selected providers (WorkBuddy China uses the daily check-in API; International uses daily activity tasks — detect the campaign, claim the daily-activity reward, then keep the account alive with free models; Raccoon uses the desktop daily points flow; AutoClaw uses the official client's daily check-in task; Qoder China uses campaign claims, and accounts with no campaign assigned get a neutral notice; Qoder International needs a device risk-control identity first (generated by the UMID component of the local Qoder client / qodercli) to see the \"Daily 100 Credits\" campaign, and a missing component yields a clear explanation instead of an error; Trae claims SOLO's daily check-in points (reset at midnight by calendar day), and when the upstream has no campaign for the account or the credential has no device ID the result is \"not claimed + the specific reason\" instead of an error; Loomy awards first-login points once a day per account; KukuAI claims the \"Free points\" daily tasks; OfficeAce claims all of that day's rewards in one action (daily check-in + newcomer gift)). If the machine was off at the scheduled time, the missed run is made up automatically after it starts — nothing is skipped just because the machine was off. Every provider's check-in API is idempotent, so running it again never claims twice.", "到点时逐个签到,已勾 {n} / {total} 家": "Checked {n} of {total} — each is checked in at the scheduled time", "北京时间 · 错过时点开机后会自动补签": "Beijing time · missed runs are made up automatically after startup", "去领取": "Claim now", "另有 {n} 个账号不参与每日签到": "{n} more accounts are not part of daily check-in", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "Claim rewards of completed tasks only (idempotent; repeated clicks will not double-credit)", "可完成": "Can complete", "可派出": "Can send out", "可选 · 缺省显示时刻": "Optional · defaults to the time", "可领奖": "Can claim", "后端未返回定时签到数据": "Backend returned no schedule data", "后端未返回签到中心数据": "The backend did not return check-in center data", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "International check-in requires the UMID component to generate a device risk-control identity (not detected on this machine).", "在途": "Traveling", "填入缺省链": "Fill in default chain", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "Pick a time and the providers, then click Save; the name is optional (the time is shown when empty)", "失败 {n}": "{n} failed", "套餐明细": "Plan details", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "Install the Qoder client or qodercli to enable it (no need to restart the gateway).", "安装中…": "Installing…", "官方客户端的每日签到任务": "Official client's daily check-in task", "定时签到": "Scheduled check-in", "定时签到已关闭": "Scheduled check-in disabled", "尚未查询": "Not queried yet", "尚未查询任务状态": "Task status not queried yet", "巡检一次": "Run one round", "已保存:{label}": "Saved: {label}", "已保存:保活模型链": "Saved: Keep-alive model chain", "已保存:定时条目": "Saved: schedule", "已删除定时条目": "Schedule deleted", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "Activity reported (streak lit up), but the campaign is not active (nothing to claim this time)", "已抽 {n} 次": "Drew {n} times", "已有结果 {checked} / 共 {total} 个账号": "Results for {checked} / {total} accounts", "已签": "Checked in", "已领 {claimed}/{total} · 累计 {earned} 积分": "Claimed {claimed}/{total} · {earned} points earned", "已领养": "Adopted", "已领取": "Claimed", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "Claim \"Daily 100 Credits\" with a device risk-control identity · requires the UMID component", "开学季执行失败:{error}": "School-season run failed: {error}", "开学季执行完成:{message}": "School-season run completed: {message}", "开学季活动": "School-season event", "开着:启用的条目按各自时刻执行": "On: enabled schedules run at their own times", "待签": "Not checked in", "待领新手福利": "Starter rewards to claim", "总开关": "Master switch", "总开关已关闭 · 在「定时签到」页打开": "Master switch is off · enable it on the \"Scheduled check-in\" tab", "成功 {n}": "{n} succeeded", "成长任务": "Growth tasks", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "Growth tasks finished ({done} succeeded, {failed} failed): credits +{credit}, energy +{energy}", "成长任务执行失败:{error}": "Growth task run failed: {error}", "执行失败:{error}": "Run failed: {error}", "执行并抽奖": "Run & draw", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "Run school-season tasks and spend all draw chances (share / chat / expert events)", "把缺省链填进清单,再点「保存」生效": "Puts the default chain into the list; click Save to apply", "抽奖机会 {n} 次": "{n} draw chances", "按住拖动调整顺序": "Press and drag to reorder", "按住拖动,调整这个模型在链里的顺序": "Press and drag to change this model's position in the chain", "按序逐个尝试,共 {n} 个": "{n} models, tried in order", "按结果筛选": "Filter by outcome", "探测 + 领取 + 保活 · 与定时签到同一套组合": "Detect + claim + keep-alive · same combo as scheduled check-in", "探测活动并领取日活奖励 · 不做保活": "Detect the campaign and claim the daily-activity reward · no keep-alive", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "Accept + light up + claim (only tasks with verified recipes)", "搜账号 / 收益 / 错误 / 触发原因": "Search account / gain / error / trigger reason", "收起新建": "Close new entry", "新建定时条目": "New scheduled entry", "新手福利": "Starter rewards", "新手福利有 {n} 项领取失败,可重试": "{n} starter reward(s) failed to claim — you can retry", "无": "None", "无独立签到接口 · 每天替账号打一次首次登录积分": "No dedicated check-in API · awards first-login points once a day per account", "无账号": "No accounts", "暂不可领": "Not claimable yet", "暂不支持": "Not supported yet", "暂无启用的条目 · 点此添加": "No enabled schedules · click to add one", "有未保存的改动": "Unsaved changes", "未勾选提供商": "No provider selected", "未开启": "Off", "未解锁": "Locked", "未领养(领养需先完成当日对话量)": "Not adopted (adoption requires the daily chat quota first)", "未领取": "Not claimed", "本地台账里今天还没领过;活动期内每天发一份新套餐": "No claim recorded locally for today yet; a new plan is issued every day during the event", "本地台账里今天(北京时间)领过的套餐:{plans}": "Plans claimed today (Beijing time) according to the local record: {plans}", "条启用": "enabled", "查询于 {time}": "Queried at {time}", "查询任务": "Query tasks", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "Query the task tree, then light up / claim in one click (includes school-season and cat travel)", "查询失败:{error}": "Query failed: {error}", "桌面端每日积分链路": "Desktop daily points flow", "正在读取定时签到数据…": "Loading schedule data…", "正在读取签到数据…": "Loading check-in data…", "每天 {time}": "Daily at {time}", "每天 {time} · {scope}": "Daily {time} · {scope}", "每天时刻": "Daily time", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "One row per account per check-in run · outcomes and gains as recorded by the backend", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "Daily activity tasks · a web-app conversation lights up the daily activity, only claims add points · the two can run separately", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "Daily sign-in points · claims member activities along the way · guest accounts have no points system (skipped)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "Daily welfare · claim → confirm → read back to verify · resets on the Beijing calendar day", "每日签到": "Daily check-in", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "Each schedule has its own time and scope · same-day dedup per entry · missed runs are made up after startup", "每账号一条明细 · 点此查看「签到记录」": "One row per account · open \"Check-in records\"", "没有可领套餐的账号(ZCode 未添加)。": "No accounts with claimable plans (ZCode not added).", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "No accounts with claimable rewards (CodeArts / ZCode not added).", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "No accounts support growth tasks (WorkBuddy CN required).", "没有支持新手福利的账号": "No accounts support starter rewards", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "No accounts support starter rewards — currently Loomy, Raccoon and CodeArts.", "没有符合筛选条件的签到记录": "No check-in records match the current filters", "没有需要执行的任务": "Nothing to run", "活动福利": "Event rewards", "活动(campaign)领取 · 每天 10:00 刷新": "Campaign claims · refreshed daily at 10:00", "活跃上报与保活均未成功,且活动未开启": "Both the activity report and keep-alive failed, and the campaign is not active", "活跃上报完成,但保活未成功且活动未开启": "Activity reported, but keep-alive failed and the campaign is not active", "活跃上报完成,但活动未开启": "Activity reported, but the campaign is not active", "活跃上报成功": "Activity reported", "活跃保活失败": "Keep-alive failed", "活跃保活完成": "Keep-alive complete", "活跃保活完成,但活动未开启": "Keep-alive complete, but the campaign is not active", "活跃保活完成,但活跃上报失败且活动未开启": "Keep-alive complete, but the activity report failed and the campaign is not active", "添加条目": "Add schedule", "添加模型": "Add model", "清单为空 —— 保存后恢复缺省链": "The list is empty — saving restores the default chain", "清单里已经有「{name}」": "The list already contains \"{name}\"", "清空失败:{error}": "Clear failed: {error}", "清空签到记录": "Clear check-in records", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "Click \"Plan details\" to see which plans you got and when they take effect; you can claim again every day during the event", "点击行展开账号明细 · 单账号签到不受范围限制": "Click a row to expand account details · single-account check-in is not limited by scope", "独立链路 · 只提供手动入口 · 不进自动签到": "Separate flow · manual entry only · not part of auto check-in", "猫猫旅行": "Cat travel", "猫猫旅行失败:{error}": "Cat travel failed: {error}", "猫猫旅行失败:{message}": "Cat travel failed: {message}", "猫猫旅行:{message}": "Cat travel: {message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "Keep the account active with free models and a web-app conversation · no rewards claimed", "确定删除「{name}」?删除后到点不再执行。": "Delete \"{name}\"? It will no longer run at its scheduled time.", "确定清空全部签到记录?清空后无法恢复。": "Clear ALL check-in records? This cannot be undone.", "确定清空当前筛选出的签到记录?清空后无法恢复。": "Clear the filtered check-in records? This cannot be undone.", "移除 {name}": "Remove {name}", "立即全部签到": "Check in all now", "签到": "Check in", "签到中…": "Checking in…", "签到中心分区": "Check-in center sections", "签到失败:{error}": "Check-in failed: {error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "Check-in complete: {succeeded}/{total} succeeded{active}, {failed} failed", "签到成功": "Check-in succeeded", "签到提供商": "Check-in providers", "签到范围": "Check-in scope", "签到触发时刻": "Check-in trigger time", "签到记录": "Check-in records", "签到记录时间范围": "Check-in records time range", "签到记录表": "Check-in records table", "累计签到记录": "Total check-in records", "结算于 {time}": "Settled at {time}", "能量 {n}": "Energy {n}", "腾讯每日签到接口 · 仅国内版": "Tencent daily check-in API · China edition only", "至少勾一家才能保存(不勾等于这条条目不签到)": "Select at least one provider to save (an empty scope means this entry checks in nothing)", "读取定时签到数据失败:{error}": "Failed to load schedule data: {error}", "读取签到数据失败:{error}": "Failed to load check-in data: {error}", "读取签到记录失败:{error}": "Failed to load check-in records: {error}", "跳过 {n}": "{n} skipped", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "Campaign delivery (claim → confirm → read back to verify) · these are plan bonus points", "还没执行过": "Never run yet", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "No schedules yet — click \"Add schedule\" to create one, or check in manually on the \"Check-in center\" tab.", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "No check-in records yet — details appear here after a manual check-in or a scheduled run.", "连登 {n} 天": "{n}-day streak", "部分": "Partial", "重签": "Check in again", "重试": "Retry", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "Limited-time trial plan · claim requires a slider CAPTCHA · view and claim one by one", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "Limited-time trial plan (start-plan), one per day during the campaign · claim requires a slider CAPTCHA", "需真实操作": "Requires real action", "非活动期": "Event inactive", "项": "items", "领取": "Claim", "领取中": "Claiming", "领取中…": "Claiming…", "领取失败": "Claim failed", "领取失败:{error}": "Claim failed: {error}", "(共 {n} 个账号)": " ({n} accounts total)", "(能量 / 连登读数本次未取到)": "(Energy / streak readings unavailable this time)", ",日活保活 {n} 个": ", {n} kept alive" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "SOLO checkin_credits claims · reset at midnight (calendar day)", "UMID 组件安装失败:{error}": "UMID component installation failed: {error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy CN · Query the task tree, then light up / claim in one click · includes the school-season event and cat travel · click a row for details", "WorkBuddy 国际版保活模型,按顺序回退": "WorkBuddy International keep-alive models, tried in order", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "Free models for WorkBuddy International daily activity · one global setting, unrelated to schedules", "{date}(每天 {time})": "{date} (daily at {time})", "{label} ×{count}({reason})": "{label} ×{count} ({reason})", "{n} 项可完成": "{n} to complete", "{n} 项待领": "{n} to claim", "{total} 账号 · {done} 已签": "{done} of {total} checked in", "{total} 项任务 · {pending} 项可完成": "{total} tasks · {pending} to complete", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ UMID component installed — the next check-in can claim International points", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ Scheduled check-in enabled", "✅ 开学季任务执行完成": "✅ School-season tasks completed", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ Growth tasks completed: credits +{credit}, energy +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ Starter rewards claimed, {n} points earned in total", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ Check-in complete: {succeeded}/{total} accounts claimed successfully{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "The \"keep-alive model chain\" is the free models used to keep WorkBuddy International accounts active during daily activity runs — tried in order, stops at the first success; submit empty to restore the default ({defaults}). Same-day dedup + idempotent claiming: repeat runs only return \"already claimed\" and never add points twice.", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "The \"keep-alive model chain\" is the free models used to keep WorkBuddy International accounts active during daily activity runs — tried in order, stops at the first success; clearing the list and saving restores the default chain (current default: {defaults}). Same-day dedup + idempotent claiming: repeat runs only return \"already claimed\" and never add points twice.", "「免费领积分」的每日任务 · 逐个领取": "\"Free points\" daily tasks · claimed one by one", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "One-time rewards · queried and claimed automatically after check-in; once claimed they are recorded locally and no longer queried upstream · click a row to expand the task list", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "Claims all of the day’s rewards in one action (daily check-in + newcomer gift) · idempotency guaranteed by the upstream", "一键安装组件": "Install component", "一键完成": "Complete all", "一键领取({n})": "Claim all ({n})", "上次执行:{line}": "Last run: {line}", "上次签到时间": "Last check-in", "上次领取 {time} · 领取需通过滑块验证码": "Last claimed {time} · claim requires passing a slider CAPTCHA", "下次 {date}": "Next {date}", "下次 {date} · 点此管理条目": "Next {date} · click to manage schedules", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "Not in daily check-in: {list}. CodeArts one-time rewards are under \"Starter rewards\" below; its and ZCode's daily/plan benefits are claimed under \"Activity rewards\".", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "Not in daily check-in: {list}. CodeArts one-time rewards are under \"Starter rewards\" below, and its daily welfare is right above under \"Daily check-in\"; ZCode plan claims are under \"Activity rewards\".", "与国内版同一套任务接口 · 站点不同": "Same task API as the China edition · different site", "与国内版同一套链路 · 站点不同、令牌不通用": "Same flow as the China edition · different site, tokens not interchangeable", "今天已领 {n} 份": "Claimed {n} today", "今天未领": "Not claimed today", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "Claimed today (Beijing time {day}) · {n} items confirmed received · can claim again tomorrow", "今日已执行": "Ran today", "今日已派出": "Sent out today", "今日已领取": "Claimed today", "今日签到": "Today", "今日签到进度": "Today's check-in progress", "从清单里移除": "Remove from the list", "保活": "Keep-alive", "保活 {n}": "{n} kept alive", "保活+领取": "Keep-alive + claim", "保活中…": "Keeping alive…", "保活模型链": "Keep-alive model chain", "全选": "Select all", "全部 {n} 家": "All {n} providers", "全部完成": "All done", "全部查询": "Query all", "全部结果": "All outcomes", "全部账号均可签到": "All accounts can check in", "全部领取": "All claimed", "关着:开机后等到窗口起点再签,随机窗口当天生效": "Off: wait for the window start after startup, so the random window applies today", "关着:所有条目都不执行": "Off: no schedule runs", "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "minutes · accounts run at random moments inside the window; 0 = run immediately at the scheduled time", "删除失败:{error}": "Delete failed: {error}", "删除定时条目": "Delete schedule", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "Signs in the available accounts of the selected providers when due (WorkBuddy CN uses its daily check-in API; WorkBuddy Intl uses the daily activity task: probe activities, claim the daily reward, then keep a free model warm and open a web session to light up the streak; Raccoon uses its desktop daily points chain; AutoClaw uses the official client's daily sign-in task; Qoder CN claims campaign rewards and shows a neutral notice for accounts without campaigns; Qoder Intl needs a device risk identity (generated by the UMID component of the local Qoder client / qodercli) to see the 'daily 100 Credits' campaign and shows a clear explanation instead of an error when the component is missing; Trae claims the SOLO daily check-in credits (reset at local midnight) and reports 'not claimed + reason' instead of an error when the upstream has no campaign for the account or the credential has no device id; Loomy calls its first-login points endpoint once a day; KukuAI claims the 'free points' daily tasks; CodeArts claims the daily ops welfare (claim → confirm → read back, with automatic runs limited to 6 writes per day and 10 minutes apart); OfficeAce claims all of the day's rewards (daily check-in + newcomer gift) in one call). With 'random offset N minutes', the accounts of a round run spread across their own window (clamped to 0:00-23:59 of the same day) instead of all at the same minute; if the window has already passed they all run immediately. Missed runs are caught up after startup so nothing is lost when the machine was off (turn off 'Startup catch-up' to wait for the window start instead). Every provider's check-in API is idempotent, so repeated runs never double-claim.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "At the scheduled time, auto check-in runs for the available accounts of the selected providers (WorkBuddy China uses the daily check-in API; International uses daily activity tasks — detect the campaign, claim the daily-activity reward, then keep the account alive with free models; Raccoon uses the desktop daily points flow; AutoClaw uses the official client's daily check-in task; Qoder China uses campaign claims, and accounts with no campaign assigned get a neutral notice; Qoder International needs a device risk-control identity first (generated by the UMID component of the local Qoder client / qodercli) to see the \"Daily 100 Credits\" campaign, and a missing component yields a clear explanation instead of an error; Trae claims SOLO's daily check-in points (reset at midnight by calendar day), and when the upstream has no campaign for the account or the credential has no device ID the result is \"not claimed + the specific reason\" instead of an error; Loomy awards first-login points once a day per account; KukuAI claims the \"Free points\" daily tasks; CodeArts claims that day's campaign welfare (claim → confirm → read back to verify; automatic runs are limited to 6 write attempts per day with a 10-minute gap); OfficeAce claims all of that day's rewards in one action (daily check-in + newcomer gift)). If the machine was off at the scheduled time, the missed run is made up automatically after it starts — nothing is skipped just because the machine was off. Every provider's check-in API is idempotent, so running it again never claims twice.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "At the scheduled time, auto check-in runs for the available accounts of the selected providers (WorkBuddy China uses the daily check-in API; International uses daily activity tasks — detect the campaign, claim the daily-activity reward, then keep the account alive with free models; Raccoon uses the desktop daily points flow; AutoClaw uses the official client's daily check-in task; Qoder China uses campaign claims, and accounts with no campaign assigned get a neutral notice; Qoder International needs a device risk-control identity first (generated by the UMID component of the local Qoder client / qodercli) to see the \"Daily 100 Credits\" campaign, and a missing component yields a clear explanation instead of an error; Trae claims SOLO's daily check-in points (reset at midnight by calendar day), and when the upstream has no campaign for the account or the credential has no device ID the result is \"not claimed + the specific reason\" instead of an error; Loomy awards first-login points once a day per account; KukuAI claims the \"Free points\" daily tasks; OfficeAce claims all of that day's rewards in one action (daily check-in + newcomer gift)). If the machine was off at the scheduled time, the missed run is made up automatically after it starts — nothing is skipped just because the machine was off. Every provider's check-in API is idempotent, so running it again never claims twice.", "到点时逐个签到,已勾 {n} / {total} 家": "Checked {n} of {total} — each is checked in at the scheduled time", "北京时间 · 错过时点开机后会自动补签": "Beijing time · missed runs are made up automatically after startup", "去领取": "Claim now", "另有 {n} 个账号不参与每日签到": "{n} more accounts are not part of daily check-in", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "Claim rewards of completed tasks only (idempotent; repeated clicks will not double-credit)", "可完成": "Can complete", "可派出": "Can send out", "可选 · 缺省显示时刻": "Optional · defaults to the time", "可领奖": "Can claim", "后端未返回定时签到数据": "Backend returned no schedule data", "后端未返回签到中心数据": "The backend did not return check-in center data", "启动补签": "Startup catch-up", "启动补签已关闭": "Startup catch-up disabled", "启动补签已开启": "Startup catch-up enabled", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "International check-in requires the UMID component to generate a device risk-control identity (not detected on this machine).", "在途": "Traveling", "填入缺省链": "Fill in default chain", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "Pick a time and the providers, then click Save; the name is optional (the time is shown when empty)", "失败 {n}": "{n} failed", "套餐明细": "Plan details", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "Install the Qoder client or qodercli to enable it (no need to restart the gateway).", "安装中…": "Installing…", "官方客户端的每日签到任务": "Official client's daily check-in task", "定时签到": "Scheduled check-in", "定时签到已关闭": "Scheduled check-in disabled", "尚未查询": "Not queried yet", "尚未查询任务状态": "Task status not queried yet", "巡检一次": "Run one round", "已保存:{label}": "Saved: {label}", "已保存:保活模型链": "Saved: Keep-alive model chain", "已保存:定时条目": "Saved: schedule", "已删除定时条目": "Schedule deleted", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "Activity reported (streak lit up), but the campaign is not active (nothing to claim this time)", "已抽 {n} 次": "Drew {n} times", "已有结果 {checked} / 共 {total} 个账号": "Results for {checked} / {total} accounts", "已签": "Checked in", "已领 {claimed}/{total} · 累计 {earned} 积分": "Claimed {claimed}/{total} · {earned} points earned", "已领养": "Adopted", "已领取": "Claimed", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "Claim \"Daily 100 Credits\" with a device risk-control identity · requires the UMID component", "开学季执行失败:{error}": "School-season run failed: {error}", "开学季执行完成:{message}": "School-season run completed: {message}", "开学季活动": "School-season event", "开着:启用的条目按各自时刻执行": "On: enabled schedules run at their own times", "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "On: schedules not yet run today catch up right after startup, ignoring the random window", "待签": "Not checked in", "待领新手福利": "Starter rewards to claim", "总开关": "Master switch", "总开关已关闭 · 在「定时签到」页打开": "Master switch is off · enable it on the \"Scheduled check-in\" tab", "成功 {n}": "{n} succeeded", "成长任务": "Growth tasks", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "Growth tasks finished ({done} succeeded, {failed} failed): credits +{credit}, energy +{energy}", "成长任务执行失败:{error}": "Growth task run failed: {error}", "执行失败:{error}": "Run failed: {error}", "执行并抽奖": "Run & draw", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "Run school-season tasks and spend all draw chances (share / chat / expert events)", "把缺省链填进清单,再点「保存」生效": "Puts the default chain into the list; click Save to apply", "抽奖机会 {n} 次": "{n} draw chances", "按住拖动调整顺序": "Press and drag to reorder", "按住拖动,调整这个模型在链里的顺序": "Press and drag to change this model's position in the chain", "按序逐个尝试,共 {n} 个": "{n} models, tried in order", "按结果筛选": "Filter by outcome", "探测 + 领取 + 保活 · 与定时签到同一套组合": "Detect + claim + keep-alive · same combo as scheduled check-in", "探测活动并领取日活奖励 · 不做保活": "Detect the campaign and claim the daily-activity reward · no keep-alive", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "Accept + light up + claim (only tasks with verified recipes)", "搜账号 / 收益 / 错误 / 触发原因": "Search account / gain / error / trigger reason", "收起新建": "Close new entry", "新建定时条目": "New scheduled entry", "新手福利": "Starter rewards", "新手福利有 {n} 项领取失败,可重试": "{n} starter reward(s) failed to claim — you can retry", "无": "None", "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "No dedicated check-in API · hits the login-info endpoint once a day per account (which grants the daily Magicubes)", "无独立签到接口 · 每天替账号打一次首次登录积分": "No dedicated check-in API · awards first-login points once a day per account", "无账号": "No accounts", "暂不可领": "Not claimable yet", "暂不支持": "Not supported yet", "暂无启用的条目 · 点此添加": "No enabled schedules · click to add one", "有未保存的改动": "Unsaved changes", "未勾选提供商": "No provider selected", "未开启": "Off", "未解锁": "Locked", "未领养(领养需先完成当日对话量)": "Not adopted (adoption requires the daily chat quota first)", "未领取": "Not claimed", "本地台账里今天还没领过;活动期内每天发一份新套餐": "No claim recorded locally for today yet; a new plan is issued every day during the event", "本地台账里今天(北京时间)领过的套餐:{plans}": "Plans claimed today (Beijing time) according to the local record: {plans}", "条启用": "enabled", "查询于 {time}": "Queried at {time}", "查询任务": "Query tasks", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "Query the task tree, then light up / claim in one click (includes school-season and cat travel)", "查询失败:{error}": "Query failed: {error}", "桌面端每日积分链路": "Desktop daily points flow", "正在读取定时签到数据…": "Loading schedule data…", "正在读取签到数据…": "Loading check-in data…", "每天 {time}": "Daily at {time}", "每天 {time} · {scope}": "Daily {time} · {scope}", "每天 {time} · 随机前后 {n} 分钟 · {scope}": "Daily {time} ± {n} min · {scope}", "每天时刻": "Daily time", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "One row per account per check-in run · outcomes and gains as recorded by the backend", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "Daily activity tasks · a web-app conversation lights up the daily activity, only claims add points · the two can run separately", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "Daily sign-in points · claims member activities along the way · guest accounts have no points system (skipped)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "Daily welfare · claim → confirm → read back to verify · resets on the Beijing calendar day", "每日签到": "Daily check-in", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "Each schedule has its own time and scope · same-day dedup per entry · missed runs are made up after startup", "每账号一条明细 · 点此查看「签到记录」": "One row per account · open \"Check-in records\"", "没有可领套餐的账号(ZCode 未添加)。": "No accounts with claimable plans (ZCode not added).", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "No accounts with claimable rewards (CodeArts / ZCode not added).", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "No accounts support growth tasks (WorkBuddy CN required).", "没有支持新手福利的账号": "No accounts support starter rewards", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "No accounts support starter rewards — currently Loomy, Raccoon and CodeArts.", "没有符合筛选条件的签到记录": "No check-in records match the current filters", "没有需要执行的任务": "Nothing to run", "活动福利": "Event rewards", "活动(campaign)领取 · 每天 10:00 刷新": "Campaign claims · refreshed daily at 10:00", "活跃上报与保活均未成功,且活动未开启": "Both the activity report and keep-alive failed, and the campaign is not active", "活跃上报完成,但保活未成功且活动未开启": "Activity reported, but keep-alive failed and the campaign is not active", "活跃上报完成,但活动未开启": "Activity reported, but the campaign is not active", "活跃上报成功": "Activity reported", "活跃保活失败": "Keep-alive failed", "活跃保活完成": "Keep-alive complete", "活跃保活完成,但活动未开启": "Keep-alive complete, but the campaign is not active", "活跃保活完成,但活跃上报失败且活动未开启": "Keep-alive complete, but the activity report failed and the campaign is not active", "添加条目": "Add schedule", "添加模型": "Add model", "清单为空 —— 保存后恢复缺省链": "The list is empty — saving restores the default chain", "清单里已经有「{name}」": "The list already contains \"{name}\"", "清空失败:{error}": "Clear failed: {error}", "清空签到记录": "Clear check-in records", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "Click \"Plan details\" to see which plans you got and when they take effect; you can claim again every day during the event", "点击行展开账号明细 · 单账号签到不受范围限制": "Click a row to expand account details · single-account check-in is not limited by scope", "独立链路 · 只提供手动入口 · 不进自动签到": "Separate flow · manual entry only · not part of auto check-in", "猫猫旅行": "Cat travel", "猫猫旅行失败:{error}": "Cat travel failed: {error}", "猫猫旅行失败:{message}": "Cat travel failed: {message}", "猫猫旅行:{message}": "Cat travel: {message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "Keep the account active with free models and a web-app conversation · no rewards claimed", "确定删除「{name}」?删除后到点不再执行。": "Delete \"{name}\"? It will no longer run at its scheduled time.", "确定清空全部签到记录?清空后无法恢复。": "Clear ALL check-in records? This cannot be undone.", "确定清空当前筛选出的签到记录?清空后无法恢复。": "Clear the filtered check-in records? This cannot be undone.", "移除 {name}": "Remove {name}", "立即全部签到": "Check in all now", "签到": "Check in", "签到中…": "Checking in…", "签到中心分区": "Check-in center sections", "签到失败:{error}": "Check-in failed: {error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "Check-in complete: {succeeded}/{total} succeeded{active}, {failed} failed", "签到成功": "Check-in succeeded", "签到提供商": "Check-in providers", "签到范围": "Check-in scope", "签到触发时刻": "Check-in trigger time", "签到记录": "Check-in records", "签到记录时间范围": "Check-in records time range", "签到记录表": "Check-in records table", "累计签到记录": "Total check-in records", "结算于 {time}": "Settled at {time}", "能量 {n}": "Energy {n}", "腾讯每日签到接口 · 仅国内版": "Tencent daily check-in API · China edition only", "至少勾一家才能保存(不勾等于这条条目不签到)": "Select at least one provider to save (an empty scope means this entry checks in nothing)", "读取定时签到数据失败:{error}": "Failed to load schedule data: {error}", "读取签到数据失败:{error}": "Failed to load check-in data: {error}", "读取签到记录失败:{error}": "Failed to load check-in records: {error}", "跳过 {n}": "{n} skipped", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "Campaign delivery (claim → confirm → read back to verify) · these are plan bonus points", "还没执行过": "Never run yet", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "No schedules yet — click \"Add schedule\" to create one, or check in manually on the \"Check-in center\" tab.", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "No check-in records yet — details appear here after a manual check-in or a scheduled run.", "连登 {n} 天": "{n}-day streak", "部分": "Partial", "重签": "Check in again", "重试": "Retry", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "Limited-time trial plan · claim requires a slider CAPTCHA · view and claim one by one", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "Limited-time trial plan (start-plan), one per day during the campaign · claim requires a slider CAPTCHA", "随机前后": "Random offset", "需真实操作": "Requires real action", "非活动期": "Event inactive", "项": "items", "领取": "Claim", "领取中": "Claiming", "领取中…": "Claiming…", "领取失败": "Claim failed", "领取失败:{error}": "Claim failed: {error}", "(共 {n} 个账号)": " ({n} accounts total)", "(能量 / 连登读数本次未取到)": "(Energy / streak readings unavailable this time)", ",日活保活 {n} 个": ", {n} kept alive" }); diff --git a/desktop-tauri/ui/i18n/ja/add-account.js b/desktop-tauri/ui/i18n/ja/add-account.js index 25ce3406..dae2188a 100644 --- a/desktop-tauri/ui/i18n/ja/add-account.js +++ b/desktop-tauri/ui/i18n/ja/add-account.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:ja/add-account —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · モデル {head}{rest}", " 等 {n} 个": " など {n} 個", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "1// で始まる Google refresh token(refresh_token=… の行をそのまま貼り付けても可)", "11 位大陆手机号": "11 桁の中国本土の携帯番号", "1~64 个字符,账号列表里按它分组显示": "1~64 文字、アカウント一覧ではこれでグループ表示されます", "6 位数字": "6 桁の数字", "

  • 没有可自动领的活动
  • ": "
  • 自動で受け取れるイベントはありません
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    受け取るのはプラン特典ポイントで、特典モデルの token プールは増えません;", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "Anthropic 互換エンドポイントは https://api.deepseek.com/anthropic です(プロトコルを anthropic に切り替えるときにこれを入力)", "Anthropic 协议填根地址,不要带 /v1": "Anthropic プロトコルではルートアドレスを入力し、/v1 は付けないでください", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw 中国版", "AutoClaw 国际版": "AutoClaw 国際版", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS は必須です;**完全な Cookie** を貼り付けてください(Cookie エディターのワンクリック書き出しで構いません)—— このうち **PTOKEN は必ず残してください**。ゲートウェイはこれを使って Baidu から KukuAI の業務セッショントークンを発行してもらうため、欠けるとモデル更新時に「未ログイン」と表示されます。Cookie ヘッダー全体、Cookie エディターが書き出した JSON 配列、または {BDUSS, STOKEN} オブジェクトに対応しています。KukuAI には更新の仕組みがないため、ログイン状態の期限が切れたら貼り直せば済みます。", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=…(または Cookie エディターが書き出した JSON)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "CatPaw の X-Passport-Token(ログイン状態 Cookie)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Cline Pass の API Key は app.cline.bot で取得します(サブスクリプション制)。エンドポイントは OpenAI 互換で、モデル一覧は Cline コンソールが正となります。モデル名はモデル管理で接頭辞なしの名前のまま追加します(例:glm-5.2 / kimi-k2.7-code / deepseek-v4-pro)。上流はクライアントの形態を検証するため、必要なクライアントリクエストヘッダーはこのカードにあらかじめ設定されています", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT(3 段のドット区切り)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT(ドット区切り 3 パート。Bearer 行全体や data.bin の中身を貼っても可)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT(3 つのドット区切り部分。chatglm_token=… の行をそのまま貼っても可)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode 国際版", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM のマネージドエンドポイント。Key は integrate.api.nvidia.com で申請します", "OfficeAce 果办": "OfficeAce", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken は Accio のログイン認証情報です(長い不透明な token 文字列で、JWT ではありません);refreshToken は任意で、入力すると期限切れ時に自動更新できます。{label}アカウントの認証情報を入力してください —— {siteNote}(最も簡単な方法:上の「ウェブログイン」を使えば token を手動で探す必要はありません。)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken は Trae の Cloud-IDE-JWT(3 段のドット区切り)です。refreshToken は期限切れ時の自動更新に使用します(本家の refreshToken は 1 回ごとに交換され、一度更新すると古いものは無効になります。そのため 2 つのプログラムで同じアカウントを同時に更新しないでください)。
    手動で貼り付ける場合は machineId / deviceId も一緒に入力してください:アップストリームはこれらをログイン時にアップロードされたデバイス公開鍵と紐付けてデバイスを判定するため、根拠なく別のペアにすると 2xxxx 系のデバイスバインディング拒否に当たります。
    この 3 つがない場合の正道は上の「ウェブログイン」を使うことです;コンテナ / リモートデプロイ形態では案内に従ってアドレスバーのコールバックアドレスを貼り付けてください。", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "monkeycode_ai_session の値(Cookie 全体をそのまま貼り付けても可)", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken は任意で、入力すると期限切れ時に自動更新できます;どちらも小浣熊クライアントのログイン状態ファイルから取得できます。", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken は任意で、入力すると自動更新できます;どちらもクライアントのログイン状態ファイルから取得できます。同じ Cline アカウントはどちらのプールでも使え、ここでは {label} に分類されます。", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token は enc: プレフィックスに対応しています(Windows では自動復号)。refreshToken を入力しないと自動更新できません。", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "token はログイン状態 Cookie です;CatPaw には更新の仕組みがないため、期限切れ後はクライアントで再ログインが必要です。", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "user_ で始まる API Key(Authorization: Bearer … の行をそのまま貼り付けても可)", "{label} 网页登录的打开方式": "{label} のウェブログインの開き方", "{label} 账号地区": "{label} アカウントの地域", "{label} 账号的添加方式": "{label} アカウントの追加方法", "{name} 不是合法 JSON:{reason}": "{name} は有効な JSON ではありません:{reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name} には JSON オブジェクトを貼り付けてください(例:{sample})", "{n} 个账号": "{n} 個のアカウント", "{n} 个账号,点击添加": "{n} 個のアカウント、クリックして追加", "{seconds}s 后重发": "{seconds} 秒後に再送", "✅ {label}账号已添加": "✅ {label} アカウントを追加しました", "✅ {label}账号已添加{name}": "✅ {label} アカウントを追加しました{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ cc-switch から {n} 個のプロバイダーをインポートしました", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ カスタムプロバイダー「{name}」を作成し、アカウントを追加しました", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ カスタムプロバイダー「{name}」を削除しました{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ 既存アカウント{name}を更新しました(同じ API Key は 1 件のみ保持し、再追加はマージされます)", "✅ 登录成功,{edition}账号已加入列表": "✅ ログインに成功し、{edition}アカウントをリストに追加しました", "✅ 领取成功:{planId}{period}": "✅ 受け取りに成功しました:{planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " 同じプロバイダーに複数の key を置くことができ、優先度に従ってローテーションされます。", "「{name}」的账号添加功能还在开发中,敬请期待。": "「{name}」のアカウント追加機能は開発中です。ご期待ください。", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "1 つの Key で複数のプロバイダーのモデルを利用できます。モデル名は「ベンダー/モデル」の完全名を指定します(例:deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "アップストリームが認証不要の場合は空欄にし、下の項目にチェックを入れてください(空欄かつ未チェックでは認証情報未設定として扱われます)", "上游信息": "アップストリーム情報", "不可领({status})": "受け取り不可({status})", "不支持导入": "インポートに対応していません", "不是有效的凭证文件:内容要是一个 JSON 对象": "有効な認証情報ファイルではありません:内容は JSON オブジェクトである必要があります", "不是有效的凭证文件:需要包含 accessToken 与 uid": "有効な認証情報ファイルではありません:accessToken と uid が必要です", "不是自定义提供商": "カスタムプロバイダーではありません", "不需要 Key:转发与拉取模型都不发送鉴权头": "Key は不要:転送とモデル取得のいずれも認証ヘッダーを送信しません", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "ログイン不要です。下のボタンを押すと、ゲートウェイが智谱清言からゲスト資格情報を直接取得してアカウント一覧に追加します(先にメモ名を入力しても構いません)。ゲスト資格情報はそのまま会話に使え、無料枠は上流がデバイス単位で発行します。

    注意:ゲストアカウントにはポイント体系がありません。会員ポイント・毎日ログインポイント・アクティビティ受け取りの各インターフェースはすべてログインが必要なため、これらの機能はゲストではスキップされます(アカウントページのポイントや签到センターには数値が表示されません)。ポイントが必要な場合は「資格情報を入力」でログイン済みアカウントのトークンを貼り付けるか、「デスクトップのログイン状態をインポート」してください。", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "両版のアカウントは同時に保存でき、それぞれ独自のモデルカタログを持ちます(中国版と国際版は別々のプロバイダーで、個別に有効化とマッピングができます)。", "中国版": "中国版", "今天没有需要领的活动(都已到账)": "本日受け取る必要のあるイベントはありません(すべて付与済み)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "本日(北京時間 {day})は {attempts} 回試行済み、あと {left} 回試せます{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "別のマシン(または OfficeAce デスクトップ版の models.json)から次の 3 項目を取り出して貼り付けてください:モデルゲートウェイのベース URL(baseUrl、https://modelgw-…/v2 の形式)と modelAppKey / modelAppSecret。この 3 項目だけで転送できます(ゲートウェイ認証情報は無期限)。コントロールプレーンの一時認証情報(accessKeyId など)は任意で、空欄の場合は残高照会と自動更新が使えませんが、転送には影響しません。", "从本机导入桌面端登录态": "本機からデスクトップ版のログイン状態をインポート", "任务镜像 id": "タスクイメージ id", "余额查询": "残高照会", "使用 Google 账号登录": "Google アカウントでログイン", "使用 Zai 账号登录": "Zai アカウントでログイン", "使用个人访问令牌(PAT)": "個人アクセストークン(PAT)を使用", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "無料モデルでは Key の入力は不要です(既定で「このアップストリームは認証不要」がチェックされ、ゲートウェイは自動的に匿名認証情報を使用します);有料モデルでは Zen の API Key を入力します。無料枠のアップストリームは公式クライアントの形態しか受け付けないため、「OpenCode 公式クライアントの偽装」が既定で有効になっています", "内嵌窗口": "内蔵ウィンドウ", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "内蔵ウィンドウで開きます;ウィンドウを閉じると待機をキャンセルします(Google アカウントが拒否された場合はシステムブラウザをお使いください)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "内蔵ウィンドウで開きます;完了後は自動でリストに追加され、ウィンドウを閉じると待機をキャンセルします", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "内蔵ウィンドウで開きます。読み取りが完了すると自動で一覧に追加され、ウィンドウを閉じると待機を中止します", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "内蔵ウィンドウは新しい環境を使うため、複数のアカウントが互いに影響しません;ウィンドウを閉じると待機をキャンセルします", "内嵌窗口(推荐)": "内蔵ウィンドウ(推奨)", "准备验证…": "認証を準備中…", "凭据 JSON": "認証情報 JSON", "凭证文件在哪?": "認証情報ファイルの場所は?", "创建并添加账号": "作成してアカウントを追加", "创建这个提供商,并同时建立它的第一个账号。": "このプロバイダーを作成し、同時にその最初のアカウントを作成します。", "删除功能不可用(脚本未就绪)": "削除機能は利用できません(スクリプト未準備)", "删除失败:{reason}": "削除に失敗しました:{reason}", "删除此提供商": "このプロバイダーを削除", "及 {n} 个账号": "、および {n} 個のアカウント", "发送中…": "送信中…", "发送失败:{message}": "送信に失敗しました:{message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "送信は未確認です:ログインウィンドウが開きました。表示されたウィンドウで手動でログインを完了してください", "取消失败:{message}": "キャンセルに失敗しました:{message}", "取消等待": "待機をキャンセル", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "「内蔵ウィンドウ」でのみサードパーティの入り口を復元できます:システムブラウザではログインページを変更できないためです", "可选": "任意", "可选(cloudaicompanionProject):留空由网关自动发现": "任意(cloudaicompanionProject):空欄の場合はゲートウェイが自動検出します", "可选,展示用": "任意、表示用", "可选,没有则无法自动续期": "任意、ないと自動更新できません", "可选,留空使用凭据里的 user_name": "任意、空欄の場合は認証情報の user_name を使用", "可选,留空使用账号姓名、邮箱或令牌指纹": "任意、空欄の場合はアカウントの氏名、メールアドレス、またはトークンフィンガープリントを使用", "可选,留空使用账号昵称或邮箱": "任意、空欄の場合はアカウントのニックネームまたはメールアドレスを使用", "可选,留空则用 key 尾号": "任意、空欄の場合は key の末尾を使用", "可选,留空则用 userId": "任意、空欄の場合は userId を使用", "可选,留空则用上游返回的账号名或账号 id": "任意、空欄の場合はアップストリームが返したアカウント名またはアカウント id を使用", "可选,留空则用凭证里的账号名": "任意、空欄の場合は認証情報のアカウント名を使用", "可选,留空则用文件里的昵称": "任意。空欄の場合はファイル内のニックネームを使用", "可选,留空则用登录名或 uid": "任意、空欄の場合はログイン名または uid を使用", "可选,留空则用脱敏手机号": "任意、空欄の場合はマスク済み電話番号を使用", "可选,留空则用脱敏手机号或 userId": "任意、空欄の場合はマスク済み電話番号または userId を使用", "可选,留空则用账号 uk": "任意、空欄の場合はアカウントの uk を使用", "可选,留空则用账号昵称": "任意。空欄ならアカウントのニックネームを使用", "可选,留空则用账号昵称或 userId": "任意。空欄の場合はアカウントのニックネームまたは userId を使用", "可选,留空则用邮箱或令牌尾号": "任意、空欄の場合はメールアドレスまたはトークンの末尾を使用", "可选,留空用「OfficeAce 果办」": "任意、空欄の場合は「OfficeAce」を使用", "可选,留空自动生成": "任意、空欄の場合は自動生成", "可选,留空自动用昵称": "任意、空欄の場合はニックネームを自動使用", "可选,给这个访客账号起个备注名": "任意。このゲストアカウントのメモ名", "可选,续期时带上": "任意、更新時に一緒に送信されます", "可选,讯飞侧 userid": "任意、iFlytek 側の userid", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "任意;会話の開始に必須です。空欄の場合はゲートウェイがこのアカウントの既存タスクから自動検出します。見つからない場合は後で手動で補ってください。", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "任意;アカウントのメールアドレスで、表示と身元識別に使用します(新しいトークンに替えても同じアカウントとして認識されます)", "可选;UUID 形态,与凭据同生共死": "任意;UUID 形式で、認証情報と一体で管理されます", "可选;填了才能到期自动续期": "任意;入力すると期限切れ時に自動更新できます", "可选;用于去重与展示名(留空时网关会问一次上游)": "任意;重複排除と表示名に使用します(空欄の場合、ゲートウェイがアップストリームに一度問い合わせます)", "可选;用于生成账号 id 与展示名": "任意;アカウント id と表示名の生成に使用します", "可选;纯数字串(上游只收 8–24 位数字)": "任意;数字のみの文字列(アップストリームは 8–24 桁の数字のみ受け付けます)", "可领取": "受け取り可能", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "同じプロバイダーに API Key ありのアカウントと認証不要アカウントを混在でき、それぞれの規則でルーティングされます。認証不要アカウントも複数併存でき、それぞれ別の送信プロキシを設定できます", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "同じアドレスでプロトコルを anthropic に変えると、その Claude 互換エンドポイントを使用します。転送には OpenCode Go の API Key が必須です(サブスクリプション制;モデルカタログの取得に Key は不要ですが、リクエストを送るとアップストリームが 401「Missing API key」を返します)", "响应为空": "応答が空です", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "SenseNova の OpenAI 互換エンドポイント。残高照会はコンソールのアカウント / パスワードを使います(下の「残高照会」の節を参照)", "国内版": "中国版", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "中国版と**国際版は 2 組の独立したアカウントとプラン**で、認証情報と受け取ったプランはどちらも共用できません。", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "中国版のログインページには Google / GitHub の入り口がありません(WeChat / 電話番号 / メールアドレスでログインします)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "中国版のログインサイトは www.accio-ai.com で、国際版とは別のサイトです。", "国内版(WorkBuddy)": "中国版(WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "中国版サイトは https://api.siliconflow.cn/v1", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "中国版サイト(minimaxi.com);OpenAI 互換アドレスは https://api.minimaxi.com/v1", "国际版": "国際版", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "国際版 z.ai の Coding プラン;OpenAI 互換アドレスは https://api.z.ai/api/coding/paas/v4", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "国際版と中国版は**2 組の独立したアカウント**です(同じアカウント体系の 2 つのサイト)。認証情報は共用できません。", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "国際版と中国版はアカウント体系が独立しています。国際版の認証情報を入力してください。refreshToken を入力しないと自動更新できません。", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "国際版のログインページは既定でメールアドレスログインのみ表示されます。チェックすると Google / GitHub / X の入り口が復元されます", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "国際版の推論サイトは api.z.ai で、中国版とは別のサイトです;プランもそれぞれ独立しています。", "国际版(WorkBuddy AI)": "国際版(WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "国際版サイトの Coding プラン;OpenAI 互換アドレスは https://api.minimax.io/v1", "在 cc-switch 里找到": "cc-switch で", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "内蔵ウィンドウで公式ログインを完了してください。成功すると自動でアカウント一覧に追加されます。", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "{label} の Qoder アカウント設定 → Integrations で PAT を生成してください(Google / GitHub のトークンは入力しないでください)。2 つの地域のアカウントと認証情報は共用できません。", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "開いた公式認可ページで WeChat の QR コードを読み取ってログインします(ページに QR コードが直接表示されます)。読み取りに成功すると自動でアカウント一覧に追加されます。", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "開いたウィンドウで Baidu アカウントを使って KukuAI 本体サイトにログインしてください(SMS 認証コード / QR コードのいずれも可)。ログインに成功すると自動でアカウント一覧に追加されます。ゲートウェイは Baidu から KukuAI の業務セッショントークンを発行してもらいます(本機に KukuAI クライアントがインストールされている必要があります)。", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "開いたウィンドウで Google アカウントにログインしてください(Antigravity の認可ページ)。認可が完了すると自動でアカウントリストに追加されます。", "在浏览器中打开登录页": "ブラウザでログインページを開く", "地区": "地域", "填写凭证": "認証情報を入力", "填写凭证添加": "認証情報を入力して追加", "备注名": "ラベル名", "套餐": "プラン", "如:智谱 GLM": "例:Zhipu GLM", "完成登录后自动加入账号列表,昵称取自上游。": "ログイン完了後は自動でアカウント一覧に追加されます。ニックネームはアップストリームから取得します。", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "公式クライアントの認証情報ディレクトリ:Windows は C:\\Users\\<ユーザー名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth、macOS は ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "公式が付与を確認済み", "导入": "インポート", "导入中…": "インポート中…", "导入凭证文件": "認証情報ファイルのインポート", "导入失败": "インポートに失敗しました", "导入失败:{reason}": "インポートに失敗しました:{reason}", "导入所选": "選択項目をインポート", "导入所选({n})": "選択項目をインポート({n})", "导入桌面端登录态": "デスクトップ版のログイン状態をインポート", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "内蔵ウィンドウを開きます;認可が完了すると自動でアカウント一覧に追加されます。ウィンドウを閉じると待機をキャンセルします。認可ページの最後に zcode:// リンクを開けない旨の表示が出ることがありますが、これは正常です —— 結果はサーバー側で記録済みです", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "内蔵ウィンドウを開きます;認可が完了すると自動でアカウント一覧に追加されます。リモートパネルではコールバックアドレスを貼り付けられます。ウィンドウを閉じると待機をキャンセルします。リンクの有効期限は 5 分で、タイムアウトまたは未クリックの場合は無効になります(再発行できます)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "内蔵ウィンドウを開きます;ログイン完了後は自動でアカウント一覧に追加されます。ウィンドウを閉じると待機をキャンセルします", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "システムの既定ブラウザで認可ページを開きます(ブラウザでログイン済みの Trae アカウントが再利用されます);同一マシンでは完了後に自動追加され、Docker / リモートパネルでは案内に従ってアドレスバーのコールバックアドレスを貼り付けてください。", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "システムの既定ブラウザで認可ページを開きます(ブラウザでログイン済みの ZCode アカウントが再利用されます);認可完了後は自動でアカウント一覧に追加されます。ページの最後に zcode:// リンクを開けない旨の表示が出ることがありますが、正常な動作です", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "システムの既定ブラウザで認可ページを開きます(ブラウザでログイン済みの Huawei Cloud アカウントが再利用されます);認可コードはゲートウェイがクラウドをポーリングして取得するため、ブラウザがどのマシンで動いていても関係ありません。完了後は自動でアカウント一覧に追加されます", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "システムの既定ブラウザで認可ページを開きます(ブラウザでログイン済みの Huawei Cloud アカウントが再利用されます);ブラウザとゲートウェイが別のマシンにある場合は、上の説明に従って最終的なコールバックアドレスをパネルに貼り付けてください", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "システムの既定ブラウザでログインページを開きます(ブラウザでログイン済みの Accio アカウントが再利用されます);ログイン完了後は自動でアカウント一覧に追加され、ポップアップを閉じると待機をキャンセルします", "小米 MiMo Token Plan 套餐(新加坡站)": "小米 MiMo Token Plan プラン(シンガポールサイト)", "已到账": "付与済み", "已取消登录等待": "ログイン待ちをキャンセルしました", "已取消领取": "受け取りをキャンセルしました", "已取消验证码": "認証をキャンセルしました", "已填写手机号,正在发送验证码…": "電話番号を入力しました。認証コードを送信中…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "認証不要を宣言済み:アカウントは通常どおりルーティングされ、送信時に認証ヘッダーは一切付きません", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "{ok} 個をインポートしました。失敗 {fail} 個(失敗した項目にはリスト内でマークが付いています)", "已建过 · {n} 个账号,点击继续添加": "作成済み · {n} 個のアカウント、クリックして追加", "已建过,点击继续添加账号": "作成済み、クリックしてアカウントを追加", "已打开官方登录页,请在窗口中完成登录…": "公式ログインページを開きました。ウィンドウでログインを完了してください…", "已点发送,等待短信…": "送信しました。SMS を待っています…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "システムの既定ブラウザでログインページを開きました。ブラウザでログインを完了してください…", "已领取,等官方确认": "受け取り済み、公式の確認待ち", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "現在のシェルバージョンは AutoClaw のウェブログインに対応していません。アプリを更新してください", "当前没有可领取的套餐(活动尚未开始)": "現在受け取り可能なプランはありません(イベントはまだ開始されていません)", "当前环境不支持领取(桥接方法缺失)": "現在の環境では受け取りに対応していません(ブリッジメソッドがありません)", "必填,CatPaw 账号标识": "必須、CatPaw アカウントの識別子", "恢复 Google / GitHub 入口": "Google / GitHub の入り口を復元", "手机号": "電話番号", "手机验证码登录": "SMS 認証コードログイン", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "Trae SOLO の公式認可ページ(trae.cn)を開き、あなたの Trae アカウントでログインしてください:認可が完了すると公式ページから本機の一時ポートにリダイレクトされます;同一マシンでのデプロイでは自動受信し、Docker / リモートパネルでは案内に従ってアドレスバーのコールバックアドレスをコピーしてください。", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "Accio {label}の公式ログインページ({site})を開き、あなたの Accio アカウントでログインしてください:ログインに成功すると公式ページから本機にリダイレクトされます;同一マシンでは自動完了し、Docker / リモートパネルでは案内に従ってコールバックアドレスを貼り付けてください(認可コードは本機からゲートウェイに渡されるだけで、画面に平文 token は表示されません)。", "打开 Accio {label}登录页": "Accio {label} のログインページを開く", "打开 Antigravity 网页登录": "Antigravity のウェブログインを開く", "打开 CatPaw 网页登录": "CatPaw のウェブログインを開く", "打开 Cline 授权页": "Cline の認可ページを開く", "打开 CodeArts 授权页": "CodeArts の認可ページを開く", "打开 Qoder 网页登录": "Qoder のウェブログインを開く", "打开 Trae 授权页": "Trae の認可ページを開く", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "ZCode {label}の公式認可ページを開き、あなたのアカウントでログインしてください。認可結果は ZCode サーバー側で記録され、ゲートウェイがバックグラウンドで自動的に認証情報を取得してアカウント一覧に追加します。", "打开 ZCode {label}授权页": "ZCode {label} の認可ページを開く", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "Huawei Cloud CodeArts の公式認可ページを開いてログインします:ログイン完了後、公式ページからブラウザがゲートウェイ自身の /oauth/callback に戻され、ゲートウェイはワンタイム認可コードで一時認証情報を取得し、アカウント一覧に追加します。
    ゲートウェイが別のマシンで動作している場合は、ウェブ画面でアドレスバーの最終的なコールバックアドレスをそのままパネルに貼り付けるよう案内されます。", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "Huawei Cloud の認可ページを開いてログインしてください:完了すると、ゲートウェイがクラウドをポーリングして認可コードを取得し、アカウント一覧に追加します(OfficeAce デスクトップ版は不要で、コールバック URL を手動で貼り戻す必要もありません)。", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "公式認可ページを開いてデバイスコード認可を完了します。ログインするのは {label}({site})のアカウントです。", "打开授权页": "認可ページを開く", "打开授权页完成确认,账号自动加入 {label}{note}": "認可ページを開いて確認を完了すると、アカウントが自動で {label} に追加されます{note}", "打开方式": "開き方", "打开网页登录": "ウェブログインを開く", "探测失败:{message}": "検出に失敗しました:{message}", "接入一个兼容上游": "互換アップストリームを接続", "提交中…": "送信中…", "搜索提供商": "プロバイダーを検索", "搜索提供商…": "プロバイダーを検索…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "公式プラグイン / CLIProxyAPI が保存した認証情報 JSON をまるごと貼り付けてください({\"codearts_provider_credential\":{…}} の形。フラットなものでも可)。
    必須:access_key_id、secret_access_key、security_token。自動更新を効かせるには refresh_token と oauth_context も一緒に貼り付ける必要があります —— 一時認証情報は約 1 時間で期限切れになり、この半分が欠けると更新できず、再ログインするしかありません。", "文件是{edition}凭证,已按该版本导入": "ファイルは{edition}の認証情報のため、そのバージョンでインポートしました", "新建自定义提供商": "カスタムプロバイダーを新規作成", "方案:{label}": "方式:{label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "平文 JWT または auth.json 内の enc: 暗号化値(自動復号)", "明文 JWT(国际版账号的 access token)": "平文 JWT(国際版アカウントの access token)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "Zhipu bigmodel.cn の Coding プラン。Key は open.bigmodel.cn/usercenter/apikeys で取得します", "未知错误": "不明なエラー", "未能获取授权地址,请重试": "認可アドレスを取得できませんでした。再試行してください", "未能读取 cc-switch 数据": "cc-switch のデータを読み取れませんでした", "未领取成功": "受け取りに失敗しました", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "ローカル Ollama、OpenCode Zen の無料枠などのアップストリームではチェックを入れてください。入れないとアカウントを使用できません", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "本家には**互いに代替できない** 2 つの認証情報があり、使いたい機能に応じて入力してください。少なくともどちらか一方は必須です:コーディングプラン API Key は推論の転送用({site} を叩きます)とウィンドウクォータの照会用(N 時間ごと / 週ごとの残り割合);jwt はプランの受け取りと残高照会用(zcode.z.ai の billing ゲートウェイを叩きます。公式名称は Coding Plan JWT で、3 段のドット区切り文字列です)。残高はどちらでも照会できますが、読み取れる内容が異なります:jwt は残高バケットとプランの有効期限、API Key はウィンドウクォータを読み取ります;受け取りは jwt のみ、転送は API Key のみです。{label}アカウントの認証情報を入力してください —— {plan}(最も簡単な方法:上の「ウェブログイン」を使うこと —— この API Key を代わりに交換してくれ、2 つの認証情報をまとめて取得できます。)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "本機の Ollama の OpenAI 互換エンドポイント。API Key は不要です(既定で「このアップストリームは認証不要」がチェック済みで、認証ヘッダーは一切送信されません)", "本次未确认到账": "今回は付与が確認できませんでした", "条可导入": "件がインポート可能", "条配置,其中": "件の設定、うち", "桌面运行时不可用(Tauri 未初始化)": "デスクトップランタイムが利用できません(Tauri が未初期化)", "模型网关基址": "モデルゲートウェイのベース URL", "正在打开百度登录页…": "Baidu のログインページを開いています…", "正在扫描本机 cc-switch…": "本機の cc-switch をスキャンしています…", "正在换发访客凭证…": "ゲスト資格情報を発行中…", "正在添加…": "追加中…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "{name} のログイン完了を待っています;完了またはキャンセルしないと新しいログインを開始できません", "每周": "毎週", "每日": "毎日", "每月": "毎月", "没有则无法自动续期": "ないと自動更新できません", "没有匹配「{keyword}」的提供商": "「{keyword}」に一致するプロバイダーはありません", "添加 {name} 账号": "{name} アカウントを追加", "添加中…": "追加中…", "添加到 ": "追加先 ", "添加失败:{reason}": "追加に失敗しました:{reason}", "添加小浣熊账号": "小浣熊アカウントを追加", "添加方式": "追加方法", "添加访客账号": "ゲストアカウントを追加", "添加账号": "アカウントを追加", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "Volcano Engine Coding プラン;汎用推論エンドポイントは https://ark.cn-beijing.volces.com/api/v3", "点击添加账号": "クリックしてアカウントを追加", "点开即预填,填 Key 接入": "開くと自動入力済み、Key を入力して接続", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "ボタンを押すとまずスライダー認証(公式の不正対策)を 1 回行い、その後ログインページが開きます。ログイン完了で自動的にアカウントが追加されます。
    これが国際版公式の唯一のログイン方式です。すでにクライアントでログイン済みの場合は、「デスクトップ版のログイン状態をインポート」を使う方が速いです。", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "AutoClaw アカウントに紐付けられた電話番号でログインします:「コードを取得」をクリックし、SMS を受け取ったら下の欄に入力してログインしてください。認証コードは本機から直接公式 API に送信され、画面に token は表示されません。", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "CatPaw アカウントでログインを完了します(Meituan passport)。成功すると自動でアカウント一覧に追加されます。", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "Loomy アカウントに紐付けられた電話番号でログインします:「コードを取得」をクリックして入力するだけです。本家で最も手軽な入り口です。", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "転送用。apiKey.secret の 2 段ドット区切り形式です(未入力の場合、このアカウントは転送できません)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "プランの受け取りと残高照会用。未入力の場合、このアカウントは受け取りと残高照会ができません", "用户 ID": "ユーザー ID", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "紐付けられた電話番号でログインします:「コードを取得」をクリックして入力するだけです。これが中国版公式の唯一のログイン方式です。", "留空则用提供商名称": "空欄の場合はプロバイダー名を使用", "登录 / 添加 {name} 账号": "ログイン / {name} アカウントを追加", "登录 session(一长串)": "ログイン session(長い文字列)", "登录中…": "ログイン中…", "登录失败:{message}": "ログインに失敗しました:{message}", "登录已结束": "ログインは終了しました", "登录并添加": "ログインして追加", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "ログイン状態ファイルのパス:~/.box-agent/config/auth.json(Windows:C:\\Users\\<ユーザー名>\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "カスタムプロバイダー「{name}」を削除しますか?このプロバイダー配下の {count} 個のアカウントも同時に削除され、削除後は元に戻せません。", "等待 Accio {label}登录完成…": "Accio {label} のログイン完了を待っています…", "等待 CatPaw 登录完成…": "CatPaw のログイン完了を待っています…", "等待 Cline 授权确认…": "Cline の認可確認を待っています…", "等待 CodeArts 登录完成…": "CodeArts のログイン完了を待っています…", "等待 Google 授权完成…": "Google の認可完了を待っています…", "等待 KukuAI 登录完成…": "KukuAI のログイン完了を待っています…", "等待 OfficeAce 登录完成…": "OfficeAce のログイン完了を待っています…", "等待 OrcaTerm 登录完成…": "OrcaTerm のログイン完了を待っています…", "等待 Qoder 授权完成…": "Qoder の認可完了を待っています…", "等待 Trae 授权完成…": "Trae の認可完了を待っています…", "等待 ZCode {label}授权完成…": "ZCode {label} の認可完了を待っています…", "等待小浣熊登录完成…": "小浣熊のログイン完了を待っています…", "等待登录完成…": "ログインの完了を待っています…", "等待网页登录…": "ウェブログインを待っています…", "粘贴 API Key": "API Key を貼り付け", "粘贴 Accio 的 accessToken": "Accio の accessToken を貼り付け", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Antigravity の Google refresh token を貼り付け(1// で始まる;refresh_token= を含む行全体をそのまま貼り付けても可)。
    これはウェブログイン以外の手動入り口です(例:ログイン済みの公式 IDE からエクスポート)。refresh token は期限切れにならず、access token の期限切れはゲートウェイが自動で更新します;トークンを紛失すると Google の認可をやり直すしかないため、大切に保管してください。", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Command Code の API Key を貼り付け(user_ で始まる;公式 CLI の ~/.commandcode/auth.json またはウェブの studio から取得)。行全体 / 引用符付き / Bearer プレフィックス付きのまま貼り付けても構いません。ゲートウェイが自動で裸の key に剥がします。key は期限切れにならず、更新用 API もありません。無効になったら取得し直してください;追加時にゲートウェイが軽量な死活確認を 1 回行いますが、失敗しても追加には影響しません。", "粘贴 Cookie": "Cookie を貼り付け", "粘贴 Google refresh token": "Google refresh token を貼り付け", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "OrcaTerm の OAuth accessToken(ドット区切り 3 パートの JWT。デスクトップクライアントの data.bin か Web 版の Cookie ot_session から取得)を貼り付けます。Bearer / ot_session= を含む行をそのまま貼ってもよく、ゲートウェイが裸のトークンに剥がします。追加後はゲートウェイが自動で更新するため(上流に更新 API があります)、2 時間の有効期限を手動で追う必要はありません。", "粘贴 Qoder 个人访问令牌(pt-…)": "Qoder の個人アクセストークン(pt-…)を貼り付け", "粘贴 accessToken": "accessToken を貼り付け", "粘贴 access_token(一长串 JWT)": "access_token(長い JWT)を貼り付け", "粘贴 session cookie": "session cookie を貼り付け", "粘贴 token / refreshToken": "token / refreshToken を貼り付け", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "workos:… で始まるトークンを貼り付け(プレフィックスがなくても自動で補われます)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "智谱清言のアクセストークン(3 つのドット区切り部分からなる JWT)を貼り付けてください。取得方法:ブラウザで chatglm.cn を開いてログインし、開発者ツールの Application → Cookies から chatglm_token の値をコピーします(chatglm_token=…; の行をそのまま貼っても可)。貼り付けたあと上流に対して一度検証し、通った場合のみアカウントを保存します。ログイン済みアカウントではポイントと签到の機能が使え、以降はゲートウェイが自動で更新します(上流に更新インターフェースがあります)。", "粘贴登录凭据": "ログイン認証情報を貼り付け", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "貼り付けるのはログイン session です(同時にモデルゲートウェイの token でもあります)。Loomy には更新用 API がなく、session の有効期間は約 14 日です。期限切れ後は再ログインしてください。", "粘贴网关凭据": "ゲートウェイ認証情報を貼り付け", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "ウェブのログイン状態 cookie monkeycode_ai_session の値を貼り付け(ブラウザーで Cookie 全体をコピーしてそのまま貼り付けても可。ゲートウェイが値を自動で取り出します)。
    {siteNote}
    MonkeyCode には更新用 API がありません:session の有効期間は約 30 日(ハードリミット)で、期限切れ後はウェブに再ログインして貼り付け直せば済みます。", "粘贴访问令牌": "アクセストークンを貼り付け", "系统浏览器": "システムブラウザ", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "システムブラウザは既存のログイン状態を再利用できます(国際版で推奨);内蔵ウィンドウの方がクリーンです。", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "システムブラウザで開く(ログイン済みの Cline アカウントを再利用);完了後は自動でリストに追加されます", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "システムブラウザで開きます(ログイン済みの Google アカウントを再利用);完了後は自動でリストに追加されます", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "システムブラウザで開く(ログイン済みの Zai / Google アカウントを再利用);完了後は自動でリストに追加されます", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "システムブラウザで開く(ログイン済みの Meituan アカウントを再利用);完了後は自動でリストに追加されます", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "システムブラウザで開く(ログイン済みアカウントを再利用);完了後は自動でリストに追加されます", "系统默认浏览器": "システムの既定ブラウザ", "编码套餐 API Key": "コーディングプラン API Key", "网关 Secret": "ゲートウェイシークレット", "网页登录": "ウェブログイン", "网页登录的打开方式": "ウェブログインの開き方", "网页登录(Zai / Google)": "ウェブログイン(Zai / Google)", "自定义": "カスタム", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "自前のアグリゲーションパネル:自分のサイトアドレスを入力。残高照会はこのアカウントの API キーで {base}/v1/usage を叩きます。追加設定不要", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "自前のアグリゲーションパネル:自分のサイトアドレスを入力。残高照会には別途 NewAPI の個人アクセストークンが必要です(下の「残高照会」の節を参照)", "获取风控配置失败,将直接尝试领取:{message}": "不正対策設定の取得に失敗しました。そのまま受け取りを試みます:{message}", "获取验证码": "コードを取得", "访客模式": "ゲストモード", "访客模式(免登录)": "ゲストモード(ログイン不要)", "该上游无需鉴权(不发送鉴权头)": "このアップストリームは認証不要(認証ヘッダーを送信しません)", "该提供商": "このプロバイダー", "该提供商账号添加功能即将上线": "このプロバイダーのアカウント追加機能は近日公開予定です", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "このカスタムプロバイダーは存在しません(削除された可能性があります)。更新してから再試行してください", "请先选择一个自定义提供商": "先にカスタムプロバイダーを選択してください", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "表示されたスライダーで認証を完了してください(公式が求める不正対策ステップ)", "请填写 11 位大陆手机号": "11 桁の中国本土の携帯番号を入力してください", "请填写 6 位数字验证码": "6 桁の認証コードを入力してください", "请填写 Base URL": "Base URL を入力してください", "请填写 {label}": "{label} を入力してください", "请填写名称": "名前を入力してください", "请完成验证…": "認証を完了してください…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "%APPDATA%/AutoClaw/auth.json を読み込んで復号します。Windows のみ", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "~/.cline/data/settings/providers.json を読み込みます。Cline クライアントでログイン済みである必要があります", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "~/.meituan-catpaw/auth.json を読み込みます。CatPaw クライアントでログイン済みである必要があります", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "本機の KukuAI クライアントのログイン状態を読み込みます(%APPDATA%\\baidugenflowpro\\Network\\Cookies)。KukuAI クライアントでログイン済みである必要があります", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "ローカルの OrcaTerm クライアントのログイン状態(%APPDATA%\\com.orcaterm-desktop.app\\data.bin)を読み取ります。OrcaTerm クライアントでのログインが必要です", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "本機の智谱清言クライアントのログイン状態を読み取ります(%APPDATA%\\chatglm\\Network\\Cookies)。クライアントでログイン済みである必要があります", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "このマシンの公式クライアント(Tencent WorkBuddy / WorkBuddy AI)で現在ログイン中のアカウントを読み取ります:認証情報ディレクトリ内の最新のログイン状態ファイルを自動で特定します(このマシンの公式クライアントにログイン済みである必要があります)。インポート後はゲートウェイが自動で更新するため、2 時間の有効期限に合わせて手動でトークンを交換する必要はありません。", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "本機クライアントの現在のログイン状態を読み込みます(平文 Cookie、復号不要)。クライアントの実行中は Cookies ファイルが排他占有されるため、インポート前に KukuAI クライアントを終了してください。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。クライアントで再ログインしたら「Token を更新」をクリックして同期してください。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。クライアントで再ログインしたら再インポートしてください。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。Zai / Google でクライアントにログインしているユーザーはこちらを使ってください。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。これは {label} に分類されます。", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "ローカルクライアントが現在ログインしている OAuth トークンを読み取ります(平文 JSON、復号不要)。インポート後はゲートウェイが自動で更新するため、クライアントの 2 時間の有効期限に合わせて手動で切り替える必要はありません。", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "本機クライアントの現在のログイン状態を読み取ります。クライアントの Cookies は DPAPI 暗号化(Chromium os_crypt)されているため、Windows でのみ利用できます。クライアントの起動中はこのファイルを読めないことがあるので、クライアントを終了してから再試行してください(「資格情報を入力」でトークンを貼り付ける方法でも構いません)。", "账号信息": "アカウント情報", "账号信息不完整,请刷新后重试": "アカウント情報が不完全です。更新してから再試行してください", "账号已添加,但请留意:{warning}": "アカウントを追加しましたが、ご注意ください:{warning}", "账号版本": "アカウントバージョン", "账号类型": "アカウント種別", "账号:{name}
    ": "アカウント:{name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "Inference Providers ルートを使用します。Key は hf.co/settings/tokens で作成します", "还没有账号": "アカウントはまだありません", "这一家当前不支持网页登录,请改用填写凭证": "このプロバイダーは現在ウェブログインに対応していません。認証情報の入力に切り替えてください", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "このアカウントには現在自動で受け取れるイベントがありません(自動で受け取るのは毎日ログインで付与されるポイントのみです)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "このクォータは「イベントプラン」の経路を使用します:転送時にコーディングプランの期限切れが表示された場合は、", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "ここには中国サイト(monkeycode-ai.com)のアカウントを入力します:中国サイトの session を貼り付けてください。国際サイト(monkeycode-ai.net)は別のプロバイダーで、アカウントも別です。両者の認証情報は共用できません。", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "ここには国際サイト(monkeycode-ai.net)のアカウントを入力します:国際サイトの session を貼り付けてください。中国サイト(monkeycode-ai.com)は別のプロバイダーで、アカウントも別です。両者の認証情報は共用できません。", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "CatPaw クライアントのログイン状態ファイル auth.json を選択します(Windows:C:\\Users\\<ユーザー名>\\.meituan-catpaw\\auth.json、macOS / Linux:~/.meituan-catpaw/auth.json)。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります(本機クライアントに依存しません)。", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Cline クライアントのログイン状態ファイル providers.json を選択します(Windows:C:\\Users\\<ユーザー名>\\.cline\\data\\settings\\providers.json、macOS / Linux:~/.cline/data/settings/providers.json)。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります(本機クライアントに依存しません)。この項目は {label} に登録されます。", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "KukuAI クライアントの Cookies ファイルを選択します(%APPDATA%\\baidugenflowpro\\Network\\Cookies):これは**バイナリ**の SQLite データベースです(拡張子なし、JSON ではありません)。インポート時は選択したファイルのコピーを読み、実行中のクライアントと占有を争いません。したがって**クライアントを終了する必要はありません**。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります。", "选择凭证文件导入": "認証情報ファイルからインポート", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "公式クライアントのログイン状態の認証情報ファイル(workbuddy-desktop.info / workbuddy-desktop-ai.info)または wb2api がエクスポートしたアカウント JSON(ネスト / フラット形式どちらも可)を選択してください。", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "小浣熊クライアントのログイン状態ファイル auth.json を選択します(Windows:C:\\Users\\<ユーザー名>\\.box-agent\\config\\auth.json、macOS / Linux:~/.box-agent/config/auth.json)。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります(本機クライアントに依存しません)。", "选择提供商": "プロバイダーを選択", "选择的文件不是合法 JSON": "選択したファイルは有効な JSON ではありません", "选择要添加账号的提供商": "アカウントを追加するプロバイダーを選択", "重新扫描": "再スキャン", "鉴权": "認証", "阿里云 Token Plan 套餐(国际站)": "Alibaba Cloud Token Plan プラン(国際版サイト)", "阿里云百炼 Coding 套餐(国内站)": "Alibaba Cloud Model Studio Coding プラン(中国版サイト)", "阿里云百炼 Coding 套餐(国际站)": "Alibaba Cloud Model Studio Coding プラン(国際版サイト)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "Alibaba Cloud Model Studio モデルサービス(国際版サイト、OpenAI 互換モード)", "需要图形验证码:登录窗口已弹出,请填写后继续": "画像認証が必要です:ログインウィンドウが開きました。入力して続行してください", "预置 API": "プリセット API", "领取 CodeArts 每日福利": "CodeArts の毎日特典を受け取る", "领取失败:{message}": "受け取りに失敗しました:{message}", "领取并让官方确认": "受け取って公式の確認を待つ", "风控验证配置不完整,请稍后重试": "不正対策認証の設定が不完全です。しばらくしてから再試行してください", "验证码": "認証コード", "验证码已发送。收到后填入下方并点「登录并添加」": "認証コードを送信しました。受け取ったら下の欄に入力し、「ログインして追加」をクリックしてください", "验证码已发送,请查看手机短信": "認証コードを送信しました。携帯の SMS をご確認ください", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "認証コードを送信しました。携帯の SMS をご確認ください。下の欄に入力して「ログインして追加」をクリックすると、ログインが完了します", "验证码已发送,请查看短信": "認証コードを送信しました。SMS をご確認ください", "验证码校验失败,请重试": "認証コードの検証に失敗しました。再試行してください", "验证码校验超时,请重试": "認証コードの検証がタイムアウトしました。再試行してください", "验证码组件不可用,请重试": "認証コンポーネントが利用できません。再試行してください", "验证码组件初始化超时,请重试": "認証コンポーネントの初期化がタイムアウトしました。再試行してください", "验证码组件加载失败,请检查网络后重试": "認証コンポーネントの読み込みに失敗しました。ネットワークを確認して再試行してください", "验证码组件加载异常,请重试": "認証コンポーネントの読み込みでエラーが発生しました。再試行してください", "验证码组件加载超时,请检查网络后重试": "認証コンポーネントの読み込みがタイムアウトしました。ネットワークを確認して再試行してください", "验证码组件未加载,请重启应用后重试": "認証コンポーネントが読み込まれていません。アプリを再起動してから再試行してください", "(免费额度池,模型名带 cline-free/ 前缀)。": "(無料枠プール、モデル名に cline-free/ プレフィックスが付きます)。", "(其中 {n} 把恢复为不限制)": "(うち {n} 個は無制限に戻ります)", "(必填)": "(必須)", "(有效期 {window})": "(有効期間 {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": "(サブスクプール、モデル名に cline-pass/ プレフィックスが付きます。アカウントに対応するサブスクリプションが必要です)。", ",下一次最快 {minutes} 分钟后": "、次回は最短 {minutes} 分後", ",并从 {n} 把 Key 的可用提供商里移除": "、Key {n} 個を利用可能なプロバイダーからも除外しました" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · モデル {head}{rest}", " 等 {n} 个": " など {n} 個", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "1// で始まる Google refresh token(refresh_token=… の行をそのまま貼り付けても可)", "11 位大陆手机号": "11 桁の中国本土の携帯番号", "1~64 个字符,账号列表里按它分组显示": "1~64 文字、アカウント一覧ではこれでグループ表示されます", "6 位数字": "6 桁の数字", "

  • 没有可自动领的活动
  • ": "
  • 自動で受け取れるイベントはありません
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    受け取るのはプラン特典ポイントで、特典モデルの token プールは増えません;", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "Anthropic 互換エンドポイントは https://api.deepseek.com/anthropic です(プロトコルを anthropic に切り替えるときにこれを入力)", "Anthropic 协议填根地址,不要带 /v1": "Anthropic プロトコルではルートアドレスを入力し、/v1 は付けないでください", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw 中国版", "AutoClaw 国际版": "AutoClaw 国際版", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS は必須です;**完全な Cookie** を貼り付けてください(Cookie エディターのワンクリック書き出しで構いません)—— このうち **PTOKEN は必ず残してください**。ゲートウェイはこれを使って Baidu から KukuAI の業務セッショントークンを発行してもらうため、欠けるとモデル更新時に「未ログイン」と表示されます。Cookie ヘッダー全体、Cookie エディターが書き出した JSON 配列、または {BDUSS, STOKEN} オブジェクトに対応しています。KukuAI には更新の仕組みがないため、ログイン状態の期限が切れたら貼り直せば済みます。", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=…(または Cookie エディターが書き出した JSON)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "CatPaw の X-Passport-Token(ログイン状態 Cookie)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Cline Pass の API Key は app.cline.bot で取得します(サブスクリプション制)。エンドポイントは OpenAI 互換で、モデル一覧は Cline コンソールが正となります。モデル名はモデル管理で接頭辞なしの名前のまま追加します(例:glm-5.2 / kimi-k2.7-code / deepseek-v4-pro)。上流はクライアントの形態を検証するため、必要なクライアントリクエストヘッダーはこのカードにあらかじめ設定されています", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT(3 段のドット区切り)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT(ドット区切り 3 パート。Bearer 行全体や data.bin の中身を貼っても可)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT(3 つのドット区切り部分。chatglm_token=… の行をそのまま貼っても可)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode 国際版", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM のマネージドエンドポイント。Key は integrate.api.nvidia.com で申請します", "OfficeAce 果办": "OfficeAce", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken は Accio のログイン認証情報です(長い不透明な token 文字列で、JWT ではありません);refreshToken は任意で、入力すると期限切れ時に自動更新できます。{label}アカウントの認証情報を入力してください —— {siteNote}(最も簡単な方法:上の「ウェブログイン」を使えば token を手動で探す必要はありません。)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken は Trae の Cloud-IDE-JWT(3 段のドット区切り)です。refreshToken は期限切れ時の自動更新に使用します(本家の refreshToken は 1 回ごとに交換され、一度更新すると古いものは無効になります。そのため 2 つのプログラムで同じアカウントを同時に更新しないでください)。
    手動で貼り付ける場合は machineId / deviceId も一緒に入力してください:アップストリームはこれらをログイン時にアップロードされたデバイス公開鍵と紐付けてデバイスを判定するため、根拠なく別のペアにすると 2xxxx 系のデバイスバインディング拒否に当たります。
    この 3 つがない場合の正道は上の「ウェブログイン」を使うことです;コンテナ / リモートデプロイ形態では案内に従ってアドレスバーのコールバックアドレスを貼り付けてください。", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "monkeycode_ai_session の値(Cookie 全体をそのまま貼り付けても可)", "ms- 开头的 API 令牌": "ms- で始まる API トークン", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken は任意で、入力すると期限切れ時に自動更新できます;どちらも小浣熊クライアントのログイン状態ファイルから取得できます。", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken は任意で、入力すると自動更新できます;どちらもクライアントのログイン状態ファイルから取得できます。同じ Cline アカウントはどちらのプールでも使え、ここでは {label} に分類されます。", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token は enc: プレフィックスに対応しています(Windows では自動復号)。refreshToken を入力しないと自動更新できません。", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "token はログイン状態 Cookie です;CatPaw には更新の仕組みがないため、期限切れ後はクライアントで再ログインが必要です。", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "user_ で始まる API Key(Authorization: Bearer … の行をそのまま貼り付けても可)", "{label} 网页登录的打开方式": "{label} のウェブログインの開き方", "{label} 账号地区": "{label} アカウントの地域", "{label} 账号的添加方式": "{label} アカウントの追加方法", "{name} 不是合法 JSON:{reason}": "{name} は有効な JSON ではありません:{reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name} には JSON オブジェクトを貼り付けてください(例:{sample})", "{n} 个账号": "{n} 個のアカウント", "{n} 个账号,点击添加": "{n} 個のアカウント、クリックして追加", "{seconds}s 后重发": "{seconds} 秒後に再送", "✅ {label}账号已添加": "✅ {label} アカウントを追加しました", "✅ {label}账号已添加{name}": "✅ {label} アカウントを追加しました{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ cc-switch から {n} 個のプロバイダーをインポートしました", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ カスタムプロバイダー「{name}」を作成し、アカウントを追加しました", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ カスタムプロバイダー「{name}」を削除しました{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ 既存アカウント{name}を更新しました(同じ API Key は 1 件のみ保持し、再追加はマージされます)", "✅ 登录成功,{edition}账号已加入列表": "✅ ログインに成功し、{edition}アカウントをリストに追加しました", "✅ 领取成功:{planId}{period}": "✅ 受け取りに成功しました:{planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " 同じプロバイダーに複数の key を置くことができ、優先度に従ってローテーションされます。", "「{name}」的账号添加功能还在开发中,敬请期待。": "「{name}」のアカウント追加機能は開発中です。ご期待ください。", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "1 つの Key で複数のプロバイダーのモデルを利用できます。モデル名は「ベンダー/モデル」の完全名を指定します(例:deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "アップストリームが認証不要の場合は空欄にし、下の項目にチェックを入れてください(空欄かつ未チェックでは認証情報未設定として扱われます)", "上游信息": "アップストリーム情報", "不可领({status})": "受け取り不可({status})", "不支持导入": "インポートに対応していません", "不是有效的凭证文件:内容要是一个 JSON 对象": "有効な認証情報ファイルではありません:内容は JSON オブジェクトである必要があります", "不是有效的凭证文件:需要包含 accessToken 与 uid": "有効な認証情報ファイルではありません:accessToken と uid が必要です", "不是自定义提供商": "カスタムプロバイダーではありません", "不需要 Key:转发与拉取模型都不发送鉴权头": "Key は不要:転送とモデル取得のいずれも認証ヘッダーを送信しません", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "ログイン不要です。下のボタンを押すと、ゲートウェイが智谱清言からゲスト資格情報を直接取得してアカウント一覧に追加します(先にメモ名を入力しても構いません)。ゲスト資格情報はそのまま会話に使え、無料枠は上流がデバイス単位で発行します。

    注意:ゲストアカウントにはポイント体系がありません。会員ポイント・毎日ログインポイント・アクティビティ受け取りの各インターフェースはすべてログインが必要なため、これらの機能はゲストではスキップされます(アカウントページのポイントや签到センターには数値が表示されません)。ポイントが必要な場合は「資格情報を入力」でログイン済みアカウントのトークンを貼り付けるか、「デスクトップのログイン状態をインポート」してください。", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "両版のアカウントは同時に保存でき、それぞれ独自のモデルカタログを持ちます(中国版と国際版は別々のプロバイダーで、個別に有効化とマッピングができます)。", "中国版": "中国版", "今天没有需要领的活动(都已到账)": "本日受け取る必要のあるイベントはありません(すべて付与済み)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "本日(北京時間 {day})は {attempts} 回試行済み、あと {left} 回試せます{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "別のマシン(または OfficeAce デスクトップ版の models.json)から次の 3 項目を取り出して貼り付けてください:モデルゲートウェイのベース URL(baseUrl、https://modelgw-…/v2 の形式)と modelAppKey / modelAppSecret。この 3 項目だけで転送できます(ゲートウェイ認証情報は無期限)。コントロールプレーンの一時認証情報(accessKeyId など)は任意で、空欄の場合は残高照会と自動更新が使えませんが、転送には影響しません。", "从本机导入桌面端登录态": "本機からデスクトップ版のログイン状態をインポート", "任务镜像 id": "タスクイメージ id", "余额查询": "残高照会", "使用 Google 账号登录": "Google アカウントでログイン", "使用 Zai 账号登录": "Zai アカウントでログイン", "使用个人访问令牌(PAT)": "個人アクセストークン(PAT)を使用", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "無料モデルでは Key の入力は不要です(既定で「このアップストリームは認証不要」がチェックされ、ゲートウェイは自動的に匿名認証情報を使用します);有料モデルでは Zen の API Key を入力します。無料枠のアップストリームは公式クライアントの形態しか受け付けないため、「OpenCode 公式クライアントの偽装」が既定で有効になっています", "内嵌窗口": "内蔵ウィンドウ", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "内蔵ウィンドウで開きます;ウィンドウを閉じると待機をキャンセルします(Google アカウントが拒否された場合はシステムブラウザをお使いください)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "内蔵ウィンドウで開きます;完了後は自動でリストに追加され、ウィンドウを閉じると待機をキャンセルします", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "内蔵ウィンドウで開きます。読み取りが完了すると自動で一覧に追加され、ウィンドウを閉じると待機を中止します", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "内蔵ウィンドウは新しい環境を使うため、複数のアカウントが互いに影響しません;ウィンドウを閉じると待機をキャンセルします", "内嵌窗口(推荐)": "内蔵ウィンドウ(推奨)", "准备验证…": "認証を準備中…", "凭据 JSON": "認証情報 JSON", "凭证文件在哪?": "認証情報ファイルの場所は?", "创建并添加账号": "作成してアカウントを追加", "创建这个提供商,并同时建立它的第一个账号。": "このプロバイダーを作成し、同時にその最初のアカウントを作成します。", "删除功能不可用(脚本未就绪)": "削除機能は利用できません(スクリプト未準備)", "删除失败:{reason}": "削除に失敗しました:{reason}", "删除此提供商": "このプロバイダーを削除", "及 {n} 个账号": "、および {n} 個のアカウント", "发送中…": "送信中…", "发送失败:{message}": "送信に失敗しました:{message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "送信は未確認です:ログインウィンドウが開きました。表示されたウィンドウで手動でログインを完了してください", "取消失败:{message}": "キャンセルに失敗しました:{message}", "取消等待": "待機をキャンセル", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "「内蔵ウィンドウ」でのみサードパーティの入り口を復元できます:システムブラウザではログインページを変更できないためです", "可选": "任意", "可选(cloudaicompanionProject):留空由网关自动发现": "任意(cloudaicompanionProject):空欄の場合はゲートウェイが自動検出します", "可选,展示用": "任意、表示用", "可选,没有则无法自动续期": "任意、ないと自動更新できません", "可选,留空使用凭据里的 user_name": "任意、空欄の場合は認証情報の user_name を使用", "可选,留空使用账号姓名、邮箱或令牌指纹": "任意、空欄の場合はアカウントの氏名、メールアドレス、またはトークンフィンガープリントを使用", "可选,留空使用账号昵称或邮箱": "任意、空欄の場合はアカウントのニックネームまたはメールアドレスを使用", "可选,留空则用 key 尾号": "任意、空欄の場合は key の末尾を使用", "可选,留空则用 userId": "任意、空欄の場合は userId を使用", "可选,留空则用上游账号昵称": "任意。空欄の場合は上流アカウントのニックネームを使用", "可选,留空则用上游返回的账号名或账号 id": "任意、空欄の場合はアップストリームが返したアカウント名またはアカウント id を使用", "可选,留空则用凭证里的账号名": "任意、空欄の場合は認証情報のアカウント名を使用", "可选,留空则用文件里的昵称": "任意。空欄の場合はファイル内のニックネームを使用", "可选,留空则用登录名或 uid": "任意、空欄の場合はログイン名または uid を使用", "可选,留空则用脱敏手机号": "任意、空欄の場合はマスク済み電話番号を使用", "可选,留空则用脱敏手机号或 userId": "任意、空欄の場合はマスク済み電話番号または userId を使用", "可选,留空则用账号 uk": "任意、空欄の場合はアカウントの uk を使用", "可选,留空则用账号昵称": "任意。空欄ならアカウントのニックネームを使用", "可选,留空则用账号昵称或 userId": "任意。空欄の場合はアカウントのニックネームまたは userId を使用", "可选,留空则用邮箱或令牌尾号": "任意、空欄の場合はメールアドレスまたはトークンの末尾を使用", "可选,留空用「OfficeAce 果办」": "任意、空欄の場合は「OfficeAce」を使用", "可选,留空自动生成": "任意、空欄の場合は自動生成", "可选,留空自动用昵称": "任意、空欄の場合はニックネームを自動使用", "可选,给这个访客账号起个备注名": "任意。このゲストアカウントのメモ名", "可选,续期时带上": "任意、更新時に一緒に送信されます", "可选,讯飞侧 userid": "任意、iFlytek 側の userid", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "任意;会話の開始に必須です。空欄の場合はゲートウェイがこのアカウントの既存タスクから自動検出します。見つからない場合は後で手動で補ってください。", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "任意;アカウントのメールアドレスで、表示と身元識別に使用します(新しいトークンに替えても同じアカウントとして認識されます)", "可选;UUID 形态,与凭据同生共死": "任意;UUID 形式で、認証情報と一体で管理されます", "可选;填了才能到期自动续期": "任意;入力すると期限切れ時に自動更新できます", "可选;用于去重与展示名(留空时网关会问一次上游)": "任意;重複排除と表示名に使用します(空欄の場合、ゲートウェイがアップストリームに一度問い合わせます)", "可选;用于生成账号 id 与展示名": "任意;アカウント id と表示名の生成に使用します", "可选;纯数字串(上游只收 8–24 位数字)": "任意;数字のみの文字列(アップストリームは 8–24 桁の数字のみ受け付けます)", "可领取": "受け取り可能", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "同じプロバイダーに API Key ありのアカウントと認証不要アカウントを混在でき、それぞれの規則でルーティングされます。認証不要アカウントも複数併存でき、それぞれ別の送信プロキシを設定できます", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "同じアドレスでプロトコルを anthropic に変えると、その Claude 互換エンドポイントを使用します。転送には OpenCode Go の API Key が必須です(サブスクリプション制;モデルカタログの取得に Key は不要ですが、リクエストを送るとアップストリームが 401「Missing API key」を返します)", "响应为空": "応答が空です", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "SenseNova の OpenAI 互換エンドポイント。残高照会はコンソールのアカウント / パスワードを使います(下の「残高照会」の節を参照)", "国内版": "中国版", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "中国版と**国際版は 2 組の独立したアカウントとプラン**で、認証情報と受け取ったプランはどちらも共用できません。", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "中国版のログインページには Google / GitHub の入り口がありません(WeChat / 電話番号 / メールアドレスでログインします)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "中国版のログインサイトは www.accio-ai.com で、国際版とは別のサイトです。", "国内版(WorkBuddy)": "中国版(WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "中国版サイトは https://api.siliconflow.cn/v1", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "中国版サイト(minimaxi.com);OpenAI 互換アドレスは https://api.minimaxi.com/v1", "国际版": "国際版", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "国際版 z.ai の Coding プラン;OpenAI 互換アドレスは https://api.z.ai/api/coding/paas/v4", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "国際版と中国版は**2 組の独立したアカウント**です(同じアカウント体系の 2 つのサイト)。認証情報は共用できません。", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "国際版と中国版はアカウント体系が独立しています。国際版の認証情報を入力してください。refreshToken を入力しないと自動更新できません。", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "国際版のログインページは既定でメールアドレスログインのみ表示されます。チェックすると Google / GitHub / X の入り口が復元されます", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "国際版の推論サイトは api.z.ai で、中国版とは別のサイトです;プランもそれぞれ独立しています。", "国际版(WorkBuddy AI)": "国際版(WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "国際版サイトの Coding プラン;OpenAI 互換アドレスは https://api.minimax.io/v1", "在 cc-switch 里找到": "cc-switch で", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "内蔵ウィンドウで公式ログインを完了してください。成功すると自動でアカウント一覧に追加されます。", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "{label} の Qoder アカウント設定 → Integrations で PAT を生成してください(Google / GitHub のトークンは入力しないでください)。2 つの地域のアカウントと認証情報は共用できません。", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "開いた公式認可ページで WeChat の QR コードを読み取ってログインします(ページに QR コードが直接表示されます)。読み取りに成功すると自動でアカウント一覧に追加されます。", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "開いたウィンドウで Baidu アカウントを使って KukuAI 本体サイトにログインしてください(SMS 認証コード / QR コードのいずれも可)。ログインに成功すると自動でアカウント一覧に追加されます。ゲートウェイは Baidu から KukuAI の業務セッショントークンを発行してもらいます(本機に KukuAI クライアントがインストールされている必要があります)。", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "開いたウィンドウで Google アカウントにログインしてください(Antigravity の認可ページ)。認可が完了すると自動でアカウントリストに追加されます。", "在浏览器中打开登录页": "ブラウザでログインページを開く", "地区": "地域", "填写凭证": "認証情報を入力", "填写凭证添加": "認証情報を入力して追加", "备注名": "ラベル名", "套餐": "プラン", "如:智谱 GLM": "例:Zhipu GLM", "完成登录后自动加入账号列表,昵称取自上游。": "ログイン完了後は自動でアカウント一覧に追加されます。ニックネームはアップストリームから取得します。", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "公式クライアントの認証情報ディレクトリ:Windows は C:\\Users\\<ユーザー名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth、macOS は ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "公式が付与を確認済み", "导入": "インポート", "导入中…": "インポート中…", "导入凭证文件": "認証情報ファイルのインポート", "导入失败": "インポートに失敗しました", "导入失败:{reason}": "インポートに失敗しました:{reason}", "导入所选": "選択項目をインポート", "导入所选({n})": "選択項目をインポート({n})", "导入桌面端登录态": "デスクトップ版のログイン状態をインポート", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "内蔵ウィンドウを開きます;認可が完了すると自動でアカウント一覧に追加されます。ウィンドウを閉じると待機をキャンセルします。認可ページの最後に zcode:// リンクを開けない旨の表示が出ることがありますが、これは正常です —— 結果はサーバー側で記録済みです", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "内蔵ウィンドウを開きます;認可が完了すると自動でアカウント一覧に追加されます。リモートパネルではコールバックアドレスを貼り付けられます。ウィンドウを閉じると待機をキャンセルします。リンクの有効期限は 5 分で、タイムアウトまたは未クリックの場合は無効になります(再発行できます)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "内蔵ウィンドウを開きます;ログイン完了後は自動でアカウント一覧に追加されます。ウィンドウを閉じると待機をキャンセルします", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "システムの既定ブラウザで認可ページを開きます(ブラウザでログイン済みの Trae アカウントが再利用されます);同一マシンでは完了後に自動追加され、Docker / リモートパネルでは案内に従ってアドレスバーのコールバックアドレスを貼り付けてください。", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "システムの既定ブラウザで認可ページを開きます(ブラウザでログイン済みの ZCode アカウントが再利用されます);認可完了後は自動でアカウント一覧に追加されます。ページの最後に zcode:// リンクを開けない旨の表示が出ることがありますが、正常な動作です", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "システムの既定ブラウザで認可ページを開きます(ブラウザでログイン済みの Huawei Cloud アカウントが再利用されます);認可コードはゲートウェイがクラウドをポーリングして取得するため、ブラウザがどのマシンで動いていても関係ありません。完了後は自動でアカウント一覧に追加されます", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "システムの既定ブラウザで認可ページを開きます(ブラウザでログイン済みの Huawei Cloud アカウントが再利用されます);ブラウザとゲートウェイが別のマシンにある場合は、上の説明に従って最終的なコールバックアドレスをパネルに貼り付けてください", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "システムの既定ブラウザでログインページを開きます(ブラウザでログイン済みの Accio アカウントが再利用されます);ログイン完了後は自動でアカウント一覧に追加され、ポップアップを閉じると待機をキャンセルします", "小米 MiMo Token Plan 套餐(新加坡站)": "小米 MiMo Token Plan プラン(シンガポールサイト)", "已到账": "付与済み", "已取消登录等待": "ログイン待ちをキャンセルしました", "已取消领取": "受け取りをキャンセルしました", "已取消验证码": "認証をキャンセルしました", "已填写手机号,正在发送验证码…": "電話番号を入力しました。認証コードを送信中…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "認証不要を宣言済み:アカウントは通常どおりルーティングされ、送信時に認証ヘッダーは一切付きません", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "{ok} 個をインポートしました。失敗 {fail} 個(失敗した項目にはリスト内でマークが付いています)", "已建过 · {n} 个账号,点击继续添加": "作成済み · {n} 個のアカウント、クリックして追加", "已建过,点击继续添加账号": "作成済み、クリックしてアカウントを追加", "已打开官方登录页,请在窗口中完成登录…": "公式ログインページを開きました。ウィンドウでログインを完了してください…", "已点发送,等待短信…": "送信しました。SMS を待っています…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "システムの既定ブラウザでログインページを開きました。ブラウザでログインを完了してください…", "已领取,等官方确认": "受け取り済み、公式の確認待ち", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "現在のシェルバージョンは AutoClaw のウェブログインに対応していません。アプリを更新してください", "当前没有可领取的套餐(活动尚未开始)": "現在受け取り可能なプランはありません(イベントはまだ開始されていません)", "当前环境不支持领取(桥接方法缺失)": "現在の環境では受け取りに対応していません(ブリッジメソッドがありません)", "必填,CatPaw 账号标识": "必須、CatPaw アカウントの識別子", "恢复 Google / GitHub 入口": "Google / GitHub の入り口を復元", "手机号": "電話番号", "手机验证码登录": "SMS 認証コードログイン", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "Trae SOLO の公式認可ページ(trae.cn)を開き、あなたの Trae アカウントでログインしてください:認可が完了すると公式ページから本機の一時ポートにリダイレクトされます;同一マシンでのデプロイでは自動受信し、Docker / リモートパネルでは案内に従ってアドレスバーのコールバックアドレスをコピーしてください。", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "Accio {label}の公式ログインページ({site})を開き、あなたの Accio アカウントでログインしてください:ログインに成功すると公式ページから本機にリダイレクトされます;同一マシンでは自動完了し、Docker / リモートパネルでは案内に従ってコールバックアドレスを貼り付けてください(認可コードは本機からゲートウェイに渡されるだけで、画面に平文 token は表示されません)。", "打开 Accio {label}登录页": "Accio {label} のログインページを開く", "打开 Antigravity 网页登录": "Antigravity のウェブログインを開く", "打开 CatPaw 网页登录": "CatPaw のウェブログインを開く", "打开 Cline 授权页": "Cline の認可ページを開く", "打开 CodeArts 授权页": "CodeArts の認可ページを開く", "打开 Qoder 网页登录": "Qoder のウェブログインを開く", "打开 Trae 授权页": "Trae の認可ページを開く", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "ZCode {label}の公式認可ページを開き、あなたのアカウントでログインしてください。認可結果は ZCode サーバー側で記録され、ゲートウェイがバックグラウンドで自動的に認証情報を取得してアカウント一覧に追加します。", "打开 ZCode {label}授权页": "ZCode {label} の認可ページを開く", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "Huawei Cloud CodeArts の公式認可ページを開いてログインします:ログイン完了後、公式ページからブラウザがゲートウェイ自身の /oauth/callback に戻され、ゲートウェイはワンタイム認可コードで一時認証情報を取得し、アカウント一覧に追加します。
    ゲートウェイが別のマシンで動作している場合は、ウェブ画面でアドレスバーの最終的なコールバックアドレスをそのままパネルに貼り付けるよう案内されます。", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "Huawei Cloud の認可ページを開いてログインしてください:完了すると、ゲートウェイがクラウドをポーリングして認可コードを取得し、アカウント一覧に追加します(OfficeAce デスクトップ版は不要で、コールバック URL を手動で貼り戻す必要もありません)。", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "公式認可ページを開いてデバイスコード認可を完了します。ログインするのは {label}({site})のアカウントです。", "打开授权页": "認可ページを開く", "打开授权页完成确认,账号自动加入 {label}{note}": "認可ページを開いて確認を完了すると、アカウントが自動で {label} に追加されます{note}", "打开方式": "開き方", "打开网页登录": "ウェブログインを開く", "探测失败:{message}": "検出に失敗しました:{message}", "接入一个兼容上游": "互換アップストリームを接続", "提交中…": "送信中…", "搜索提供商": "プロバイダーを検索", "搜索提供商…": "プロバイダーを検索…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "公式プラグイン / CLIProxyAPI が保存した認証情報 JSON をまるごと貼り付けてください({\"codearts_provider_credential\":{…}} の形。フラットなものでも可)。
    必須:access_key_id、secret_access_key、security_token。自動更新を効かせるには refresh_token と oauth_context も一緒に貼り付ける必要があります —— 一時認証情報は約 1 時間で期限切れになり、この半分が欠けると更新できず、再ログインするしかありません。", "文件是{edition}凭证,已按该版本导入": "ファイルは{edition}の認証情報のため、そのバージョンでインポートしました", "新建自定义提供商": "カスタムプロバイダーを新規作成", "方案:{label}": "方式:{label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "平文 JWT または auth.json 内の enc: 暗号化値(自動復号)", "明文 JWT(国际版账号的 access token)": "平文 JWT(国際版アカウントの access token)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "Zhipu bigmodel.cn の Coding プラン。Key は open.bigmodel.cn/usercenter/apikeys で取得します", "未知错误": "不明なエラー", "未能获取授权地址,请重试": "認可アドレスを取得できませんでした。再試行してください", "未能读取 cc-switch 数据": "cc-switch のデータを読み取れませんでした", "未领取成功": "受け取りに失敗しました", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "ローカル Ollama、OpenCode Zen の無料枠などのアップストリームではチェックを入れてください。入れないとアカウントを使用できません", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "本家には**互いに代替できない** 2 つの認証情報があり、使いたい機能に応じて入力してください。少なくともどちらか一方は必須です:コーディングプラン API Key は推論の転送用({site} を叩きます)とウィンドウクォータの照会用(N 時間ごと / 週ごとの残り割合);jwt はプランの受け取りと残高照会用(zcode.z.ai の billing ゲートウェイを叩きます。公式名称は Coding Plan JWT で、3 段のドット区切り文字列です)。残高はどちらでも照会できますが、読み取れる内容が異なります:jwt は残高バケットとプランの有効期限、API Key はウィンドウクォータを読み取ります;受け取りは jwt のみ、転送は API Key のみです。{label}アカウントの認証情報を入力してください —— {plan}(最も簡単な方法:上の「ウェブログイン」を使うこと —— この API Key を代わりに交換してくれ、2 つの認証情報をまとめて取得できます。)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "本機の Ollama の OpenAI 互換エンドポイント。API Key は不要です(既定で「このアップストリームは認証不要」がチェック済みで、認証ヘッダーは一切送信されません)", "本次未确认到账": "今回は付与が確認できませんでした", "条可导入": "件がインポート可能", "条配置,其中": "件の設定、うち", "桌面运行时不可用(Tauri 未初始化)": "デスクトップランタイムが利用できません(Tauri が未初期化)", "模型网关基址": "モデルゲートウェイのベース URL", "正在打开百度登录页…": "Baidu のログインページを開いています…", "正在扫描本机 cc-switch…": "本機の cc-switch をスキャンしています…", "正在换发访客凭证…": "ゲスト資格情報を発行中…", "正在添加…": "追加中…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "{name} のログイン完了を待っています;完了またはキャンセルしないと新しいログインを開始できません", "每周": "毎週", "每日": "毎日", "每月": "毎月", "没有则无法自动续期": "ないと自動更新できません", "没有匹配「{keyword}」的提供商": "「{keyword}」に一致するプロバイダーはありません", "添加 {name} 账号": "{name} アカウントを追加", "添加中…": "追加中…", "添加到 ": "追加先 ", "添加失败:{reason}": "追加に失敗しました:{reason}", "添加小浣熊账号": "小浣熊アカウントを追加", "添加方式": "追加方法", "添加访客账号": "ゲストアカウントを追加", "添加账号": "アカウントを追加", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "Volcano Engine Coding プラン;汎用推論エンドポイントは https://ark.cn-beijing.volces.com/api/v3", "点击添加账号": "クリックしてアカウントを追加", "点开即预填,填 Key 接入": "開くと自動入力済み、Key を入力して接続", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "ボタンを押すとまずスライダー認証(公式の不正対策)を 1 回行い、その後ログインページが開きます。ログイン完了で自動的にアカウントが追加されます。
    これが国際版公式の唯一のログイン方式です。すでにクライアントでログイン済みの場合は、「デスクトップ版のログイン状態をインポート」を使う方が速いです。", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "AutoClaw アカウントに紐付けられた電話番号でログインします:「コードを取得」をクリックし、SMS を受け取ったら下の欄に入力してログインしてください。認証コードは本機から直接公式 API に送信され、画面に token は表示されません。", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "CatPaw アカウントでログインを完了します(Meituan passport)。成功すると自動でアカウント一覧に追加されます。", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "Loomy アカウントに紐付けられた電話番号でログインします:「コードを取得」をクリックして入力するだけです。本家で最も手軽な入り口です。", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "転送用。apiKey.secret の 2 段ドット区切り形式です(未入力の場合、このアカウントは転送できません)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "プランの受け取りと残高照会用。未入力の場合、このアカウントは受け取りと残高照会ができません", "用户 ID": "ユーザー ID", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "紐付けられた電話番号でログインします:「コードを取得」をクリックして入力するだけです。これが中国版公式の唯一のログイン方式です。", "留空则用提供商名称": "空欄の場合はプロバイダー名を使用", "登录 / 添加 {name} 账号": "ログイン / {name} アカウントを追加", "登录 session(一长串)": "ログイン session(長い文字列)", "登录中…": "ログイン中…", "登录失败:{message}": "ログインに失敗しました:{message}", "登录已结束": "ログインは終了しました", "登录并添加": "ログインして追加", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "ログイン状態ファイルのパス:~/.box-agent/config/auth.json(Windows:C:\\Users\\<ユーザー名>\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "カスタムプロバイダー「{name}」を削除しますか?このプロバイダー配下の {count} 個のアカウントも同時に削除され、削除後は元に戻せません。", "等待 Accio {label}登录完成…": "Accio {label} のログイン完了を待っています…", "等待 CatPaw 登录完成…": "CatPaw のログイン完了を待っています…", "等待 Cline 授权确认…": "Cline の認可確認を待っています…", "等待 CodeArts 登录完成…": "CodeArts のログイン完了を待っています…", "等待 Google 授权完成…": "Google の認可完了を待っています…", "等待 KukuAI 登录完成…": "KukuAI のログイン完了を待っています…", "等待 OfficeAce 登录完成…": "OfficeAce のログイン完了を待っています…", "等待 OrcaTerm 登录完成…": "OrcaTerm のログイン完了を待っています…", "等待 Qoder 授权完成…": "Qoder の認可完了を待っています…", "等待 Trae 授权完成…": "Trae の認可完了を待っています…", "等待 ZCode {label}授权完成…": "ZCode {label} の認可完了を待っています…", "等待小浣熊登录完成…": "小浣熊のログイン完了を待っています…", "等待登录完成…": "ログインの完了を待っています…", "等待网页登录…": "ウェブログインを待っています…", "粘贴 API Key": "API Key を貼り付け", "粘贴 API 令牌": "API トークンを貼り付け", "粘贴 Accio 的 accessToken": "Accio の accessToken を貼り付け", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Antigravity の Google refresh token を貼り付け(1// で始まる;refresh_token= を含む行全体をそのまま貼り付けても可)。
    これはウェブログイン以外の手動入り口です(例:ログイン済みの公式 IDE からエクスポート)。refresh token は期限切れにならず、access token の期限切れはゲートウェイが自動で更新します;トークンを紛失すると Google の認可をやり直すしかないため、大切に保管してください。", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Command Code の API Key を貼り付け(user_ で始まる;公式 CLI の ~/.commandcode/auth.json またはウェブの studio から取得)。行全体 / 引用符付き / Bearer プレフィックス付きのまま貼り付けても構いません。ゲートウェイが自動で裸の key に剥がします。key は期限切れにならず、更新用 API もありません。無効になったら取得し直してください;追加時にゲートウェイが軽量な死活確認を 1 回行いますが、失敗しても追加には影響しません。", "粘贴 Cookie": "Cookie を貼り付け", "粘贴 Google refresh token": "Google refresh token を貼り付け", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "OrcaTerm の OAuth accessToken(ドット区切り 3 パートの JWT。デスクトップクライアントの data.bin か Web 版の Cookie ot_session から取得)を貼り付けます。Bearer / ot_session= を含む行をそのまま貼ってもよく、ゲートウェイが裸のトークンに剥がします。追加後はゲートウェイが自動で更新するため(上流に更新 API があります)、2 時間の有効期限を手動で追う必要はありません。", "粘贴 Qoder 个人访问令牌(pt-…)": "Qoder の個人アクセストークン(pt-…)を貼り付け", "粘贴 accessToken": "accessToken を貼り付け", "粘贴 access_token(一长串 JWT)": "access_token(長い JWT)を貼り付け", "粘贴 session cookie": "session cookie を貼り付け", "粘贴 token / refreshToken": "token / refreshToken を貼り付け", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "workos:… で始まるトークンを貼り付け(プレフィックスがなくても自動で補われます)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "智谱清言のアクセストークン(3 つのドット区切り部分からなる JWT)を貼り付けてください。取得方法:ブラウザで chatglm.cn を開いてログインし、開発者ツールの Application → Cookies から chatglm_token の値をコピーします(chatglm_token=…; の行をそのまま貼っても可)。貼り付けたあと上流に対して一度検証し、通った場合のみアカウントを保存します。ログイン済みアカウントではポイントと签到の機能が使え、以降はゲートウェイが自動で更新します(上流に更新インターフェースがあります)。", "粘贴登录凭据": "ログイン認証情報を貼り付け", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "貼り付けるのはログイン session です(同時にモデルゲートウェイの token でもあります)。Loomy には更新用 API がなく、session の有効期間は約 14 日です。期限切れ後は再ログインしてください。", "粘贴网关凭据": "ゲートウェイ認証情報を貼り付け", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "ウェブのログイン状態 cookie monkeycode_ai_session の値を貼り付け(ブラウザーで Cookie 全体をコピーしてそのまま貼り付けても可。ゲートウェイが値を自動で取り出します)。
    {siteNote}
    MonkeyCode には更新用 API がありません:session の有効期間は約 30 日(ハードリミット)で、期限切れ後はウェブに再ログインして貼り付け直せば済みます。", "粘贴访问令牌": "アクセストークンを貼り付け", "系统浏览器": "システムブラウザ", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "システムブラウザは既存のログイン状態を再利用できます(国際版で推奨);内蔵ウィンドウの方がクリーンです。", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "システムブラウザで開く(ログイン済みの Cline アカウントを再利用);完了後は自動でリストに追加されます", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "システムブラウザで開きます(ログイン済みの Google アカウントを再利用);完了後は自動でリストに追加されます", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "システムブラウザで開く(ログイン済みの Zai / Google アカウントを再利用);完了後は自動でリストに追加されます", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "システムブラウザで開く(ログイン済みの Meituan アカウントを再利用);完了後は自動でリストに追加されます", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "システムブラウザで開く(ログイン済みアカウントを再利用);完了後は自動でリストに追加されます", "系统默认浏览器": "システムの既定ブラウザ", "编码套餐 API Key": "コーディングプラン API Key", "网关 Secret": "ゲートウェイシークレット", "网页登录": "ウェブログイン", "网页登录的打开方式": "ウェブログインの開き方", "网页登录(Zai / Google)": "ウェブログイン(Zai / Google)", "自定义": "カスタム", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "自前のアグリゲーションパネル:自分のサイトアドレスを入力。残高照会はこのアカウントの API キーで {base}/v1/usage を叩きます。追加設定不要", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "自前のアグリゲーションパネル:自分のサイトアドレスを入力。残高照会には別途 NewAPI の個人アクセストークンが必要です(下の「残高照会」の節を参照)", "获取风控配置失败,将直接尝试领取:{message}": "不正対策設定の取得に失敗しました。そのまま受け取りを試みます:{message}", "获取验证码": "コードを取得", "访客模式": "ゲストモード", "访客模式(免登录)": "ゲストモード(ログイン不要)", "该上游无需鉴权(不发送鉴权头)": "このアップストリームは認証不要(認証ヘッダーを送信しません)", "该提供商": "このプロバイダー", "该提供商账号添加功能即将上线": "このプロバイダーのアカウント追加機能は近日公開予定です", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "このカスタムプロバイダーは存在しません(削除された可能性があります)。更新してから再試行してください", "请先选择一个自定义提供商": "先にカスタムプロバイダーを選択してください", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "表示されたスライダーで認証を完了してください(公式が求める不正対策ステップ)", "请填写 11 位大陆手机号": "11 桁の中国本土の携帯番号を入力してください", "请填写 6 位数字验证码": "6 桁の認証コードを入力してください", "请填写 Base URL": "Base URL を入力してください", "请填写 {label}": "{label} を入力してください", "请填写名称": "名前を入力してください", "请完成验证…": "認証を完了してください…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "%APPDATA%/AutoClaw/auth.json を読み込んで復号します。Windows のみ", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "~/.cline/data/settings/providers.json を読み込みます。Cline クライアントでログイン済みである必要があります", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "~/.meituan-catpaw/auth.json を読み込みます。CatPaw クライアントでログイン済みである必要があります", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "本機の KukuAI クライアントのログイン状態を読み込みます(%APPDATA%\\baidugenflowpro\\Network\\Cookies)。KukuAI クライアントでログイン済みである必要があります", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "ローカルの OrcaTerm クライアントのログイン状態(%APPDATA%\\com.orcaterm-desktop.app\\data.bin)を読み取ります。OrcaTerm クライアントでのログインが必要です", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "本機の智谱清言クライアントのログイン状態を読み取ります(%APPDATA%\\chatglm\\Network\\Cookies)。クライアントでログイン済みである必要があります", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "このマシンの公式クライアント(Tencent WorkBuddy / WorkBuddy AI)で現在ログイン中のアカウントを読み取ります:認証情報ディレクトリ内の最新のログイン状態ファイルを自動で特定します(このマシンの公式クライアントにログイン済みである必要があります)。インポート後はゲートウェイが自動で更新するため、2 時間の有効期限に合わせて手動でトークンを交換する必要はありません。", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "本機クライアントの現在のログイン状態を読み込みます(平文 Cookie、復号不要)。クライアントの実行中は Cookies ファイルが排他占有されるため、インポート前に KukuAI クライアントを終了してください。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。クライアントで再ログインしたら「Token を更新」をクリックして同期してください。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。クライアントで再ログインしたら再インポートしてください。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。Zai / Google でクライアントにログインしているユーザーはこちらを使ってください。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "本機クライアントの現在のログイン状態を読み込みます。毎回リアルタイムで読み取ります(この記録を削除してもクライアントのログイン状態には影響しません)。これは {label} に分類されます。", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "ローカルクライアントが現在ログインしている OAuth トークンを読み取ります(平文 JSON、復号不要)。インポート後はゲートウェイが自動で更新するため、クライアントの 2 時間の有効期限に合わせて手動で切り替える必要はありません。", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "本機クライアントの現在のログイン状態を読み取ります。クライアントの Cookies は DPAPI 暗号化(Chromium os_crypt)されているため、Windows でのみ利用できます。クライアントの起動中はこのファイルを読めないことがあるので、クライアントを終了してから再試行してください(「資格情報を入力」でトークンを貼り付ける方法でも構いません)。", "账号信息": "アカウント情報", "账号信息不完整,请刷新后重试": "アカウント情報が不完全です。更新してから再試行してください", "账号已添加,但请留意:{warning}": "アカウントを追加しましたが、ご注意ください:{warning}", "账号版本": "アカウントバージョン", "账号类型": "アカウント種別", "账号:{name}
    ": "アカウント:{name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "Inference Providers ルートを使用します。Key は hf.co/settings/tokens で作成します", "还没有账号": "アカウントはまだありません", "这一家当前不支持网页登录,请改用填写凭证": "このプロバイダーは現在ウェブログインに対応していません。認証情報の入力に切り替えてください", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "このアカウントには現在自動で受け取れるイベントがありません(自動で受け取るのは毎日ログインで付与されるポイントのみです)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "このクォータは「イベントプラン」の経路を使用します:転送時にコーディングプランの期限切れが表示された場合は、", "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "ここには中国サイト(modelscope.cn)のアカウントを入力します。中国サイトのトークンを貼り付けてください。国際サイト(modelscope.ai)は別の provider・別のアカウントで、両者のトークンに互換性はありません。", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "ここには中国サイト(monkeycode-ai.com)のアカウントを入力します:中国サイトの session を貼り付けてください。国際サイト(monkeycode-ai.net)は別のプロバイダーで、アカウントも別です。両者の認証情報は共用できません。", "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "ここには国際サイト(modelscope.ai)のアカウントを入力します。国際サイトのトークンを貼り付けてください。中国サイト(modelscope.cn)は別の provider・別のアカウントで、両者のトークンに互換性はありません。", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "ここには国際サイト(monkeycode-ai.net)のアカウントを入力します:国際サイトの session を貼り付けてください。中国サイト(monkeycode-ai.com)は別のプロバイダーで、アカウントも別です。両者の認証情報は共用できません。", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "CatPaw クライアントのログイン状態ファイル auth.json を選択します(Windows:C:\\Users\\<ユーザー名>\\.meituan-catpaw\\auth.json、macOS / Linux:~/.meituan-catpaw/auth.json)。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります(本機クライアントに依存しません)。", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Cline クライアントのログイン状態ファイル providers.json を選択します(Windows:C:\\Users\\<ユーザー名>\\.cline\\data\\settings\\providers.json、macOS / Linux:~/.cline/data/settings/providers.json)。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります(本機クライアントに依存しません)。この項目は {label} に登録されます。", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "KukuAI クライアントの Cookies ファイルを選択します(%APPDATA%\\baidugenflowpro\\Network\\Cookies):これは**バイナリ**の SQLite データベースです(拡張子なし、JSON ではありません)。インポート時は選択したファイルのコピーを読み、実行中のクライアントと占有を争いません。したがって**クライアントを終了する必要はありません**。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります。", "选择凭证文件导入": "認証情報ファイルからインポート", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "公式クライアントのログイン状態の認証情報ファイル(workbuddy-desktop.info / workbuddy-desktop-ai.info)または wb2api がエクスポートしたアカウント JSON(ネスト / フラット形式どちらも可)を選択してください。", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "小浣熊クライアントのログイン状態ファイル auth.json を選択します(Windows:C:\\Users\\<ユーザー名>\\.box-agent\\config\\auth.json、macOS / Linux:~/.box-agent/config/auth.json)。インポート後は認証情報がゲートウェイ側に保存され、単独で転送できるようになります(本機クライアントに依存しません)。", "选择提供商": "プロバイダーを選択", "选择的文件不是合法 JSON": "選択したファイルは有効な JSON ではありません", "选择要添加账号的提供商": "アカウントを追加するプロバイダーを選択", "重新扫描": "再スキャン", "鉴权": "認証", "阿里云 Token Plan 套餐(国际站)": "Alibaba Cloud Token Plan プラン(国際版サイト)", "阿里云百炼 Coding 套餐(国内站)": "Alibaba Cloud Model Studio Coding プラン(中国版サイト)", "阿里云百炼 Coding 套餐(国际站)": "Alibaba Cloud Model Studio Coding プラン(国際版サイト)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "Alibaba Cloud Model Studio モデルサービス(国際版サイト、OpenAI 互換モード)", "需要图形验证码:登录窗口已弹出,请填写后继续": "画像認証が必要です:ログインウィンドウが開きました。入力して続行してください", "预置 API": "プリセット API", "领取 CodeArts 每日福利": "CodeArts の毎日特典を受け取る", "领取失败:{message}": "受け取りに失敗しました:{message}", "领取并让官方确认": "受け取って公式の確認を待つ", "风控验证配置不完整,请稍后重试": "不正対策認証の設定が不完全です。しばらくしてから再試行してください", "验证码": "認証コード", "验证码已发送。收到后填入下方并点「登录并添加」": "認証コードを送信しました。受け取ったら下の欄に入力し、「ログインして追加」をクリックしてください", "验证码已发送,请查看手机短信": "認証コードを送信しました。携帯の SMS をご確認ください", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "認証コードを送信しました。携帯の SMS をご確認ください。下の欄に入力して「ログインして追加」をクリックすると、ログインが完了します", "验证码已发送,请查看短信": "認証コードを送信しました。SMS をご確認ください", "验证码校验失败,请重试": "認証コードの検証に失敗しました。再試行してください", "验证码校验超时,请重试": "認証コードの検証がタイムアウトしました。再試行してください", "验证码组件不可用,请重试": "認証コンポーネントが利用できません。再試行してください", "验证码组件初始化超时,请重试": "認証コンポーネントの初期化がタイムアウトしました。再試行してください", "验证码组件加载失败,请检查网络后重试": "認証コンポーネントの読み込みに失敗しました。ネットワークを確認して再試行してください", "验证码组件加载异常,请重试": "認証コンポーネントの読み込みでエラーが発生しました。再試行してください", "验证码组件加载超时,请检查网络后重试": "認証コンポーネントの読み込みがタイムアウトしました。ネットワークを確認して再試行してください", "验证码组件未加载,请重启应用后重试": "認証コンポーネントが読み込まれていません。アプリを再起動してから再試行してください", "(免费额度池,模型名带 cline-free/ 前缀)。": "(無料枠プール、モデル名に cline-free/ プレフィックスが付きます)。", "(其中 {n} 把恢复为不限制)": "(うち {n} 個は無制限に戻ります)", "(必填)": "(必須)", "(有效期 {window})": "(有効期間 {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": "(サブスクプール、モデル名に cline-pass/ プレフィックスが付きます。アカウントに対応するサブスクリプションが必要です)。", ",下一次最快 {minutes} 分钟后": "、次回は最短 {minutes} 分後", ",并从 {n} 把 Key 的可用提供商里移除": "、Key {n} 個を利用可能なプロバイダーからも除外しました" }); diff --git a/desktop-tauri/ui/i18n/ja/checkin.js b/desktop-tauri/ui/i18n/ja/checkin.js index 2b2ba23f..636908e7 100644 --- a/desktop-tauri/ui/i18n/ja/checkin.js +++ b/desktop-tauri/ui/i18n/ja/checkin.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:ja/checkin —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "SOLO の checkin_credits 受け取り · 自然日 0 時に更新", "UMID 组件安装失败:{error}": "UMID コンポーネントのインストールに失敗しました:{error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy 中国版 · タスクツリーを照会してワンクリックで点灯/受け取り · 新学期イベントとねこ旅行を含む · 行をクリックで詳細", "WorkBuddy 国际版保活模型,按顺序回退": "WorkBuddy 国際版のキープアライブ用モデル(順番にフォールバック)", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "WorkBuddy国際版のデイリーアクティビティ用の無料モデル · 全体で1つの設定、スケジュールとは無関係", "{date}(每天 {time})": "{date}(毎日 {time})", "{label} ×{count}({reason})": "{label} ×{count}({reason})", "{n} 项可完成": "完了可能 {n} 件", "{n} 项待领": "{n} 件受け取り待ち", "{total} 账号 · {done} 已签": "{total} アカウント · {done} チェックイン済み", "{total} 项任务 · {pending} 项可完成": "タスク {total} 件 · 完了可能 {pending} 件", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ UMID コンポーネントをインストールしました。次回のチェックインで国際版の積分を受け取れます", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ 定期チェックインを有効にしました", "✅ 开学季任务执行完成": "✅ 新学期タスクの実行が完了しました", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ 成長タスク完了:クレジット +{credit} エネルギー +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ 初心者ボーナスの受け取りが完了しました。累計 {n} 積分", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ チェックイン完了:{succeeded}/{total} 件のアカウントが受け取りに成功{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "「キープアライブモデルチェーン」は、WorkBuddy国際版のデイリーアクティビティでアカウントを活性化し続けるための無料モデルです。順に試し、最初の成功で止まります。空で送信すると既定({defaults})に戻します。当日の重複排除+冪等な受け取り:再実行しても「受取済み」が返るだけで、ポイントが二重に加算されることはありません。", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "「キープアライブモデルチェーン」は、WorkBuddy国際版のデイリーアクティビティでアカウントを活性化し続けるための無料モデルです。順に試し、最初の成功で止まります。リストを空にして保存すると既定のチェーン(現在の既定:{defaults})に戻ります。当日の重複排除+冪等な受け取り:再実行しても「受取済み」が返るだけで、ポイントが二重に加算されることはありません。", "「免费领积分」的每日任务 · 逐个领取": "「無料積分受け取り」のデイリータスク · 1 つずつ受け取る", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "一度きりの特典 · チェックイン後に自動で照会して受け取り、受け取り済みは本機に記録し以降はアップストリームに問い合わせません · 行をクリックしてタスク一覧を展開", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "その日の報酬を一度にまとめて受け取ります(毎日チェックイン+新規特典) · 冪等性はアップストリームが保証", "一键安装组件": "ワンクリックでインストール", "一键完成": "一括完了", "一键领取({n})": "一括受け取り({n})", "上次执行:{line}": "前回実行:{line}", "上次签到时间": "前回のチェックイン時刻", "上次领取 {time} · 领取需通过滑块验证码": "前回の受け取り {time} · 受け取りにはスライダー認証が必要", "下次 {date}": "次回 {date}", "下次 {date} · 点此管理条目": "次回 {date} · クリックしてスケジュールを管理", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "デイリーチェックインの対象外:{list}。CodeArts の一度きりの特典は下の「初心者ボーナス」に、CodeArts と ZCode の日次/プラン特典の受け取りは「アクティビティ特典」にあります。", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "デイリーチェックインの対象外:{list}。CodeArts の一度きりの特典は下の「初心者ボーナス」、CodeArts のデイリー特典はすぐ上の「デイリーチェックイン」にあります。ZCode のプラン受け取りは「アクティビティ特典」です。", "与国内版同一套任务接口 · 站点不同": "中国版と同じタスク API · サイトが異なる", "今天已领 {n} 份": "本日 {n} 件受け取り済み", "今天未领": "本日は未受取", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "本日(北京時間 {day})受け取り済み · 公式に {n} 件の到着を確認 · 明日また受け取れます", "今日已执行": "本日実行済み", "今日已派出": "本日は出発済み", "今日已领取": "本日受け取り済み", "今日签到": "本日のチェックイン", "今日签到进度": "本日のチェックイン進捗", "从清单里移除": "リストから削除", "保活": "キープアライブ", "保活 {n}": "キープアライブ {n}", "保活+领取": "キープアライブ+受け取り", "保活中…": "キープアライブ中…", "保活模型链": "キープアライブモデルチェーン", "全选": "すべて選択", "全部 {n} 家": "全 {n} 社", "全部完成": "すべて完了", "全部查询": "一括クエリ", "全部结果": "すべての結果", "全部账号均可签到": "すべてのアカウントがチェックイン可能", "全部领取": "すべて受け取り済み", "关着:所有条目都不执行": "オフ:どのスケジュールも実行されません", "删除失败:{error}": "削除に失敗しました:{error}", "删除定时条目": "スケジュールを削除", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると、チェックを入れたプロバイダーの利用可能なアカウントを自動でチェックインします(WorkBuddy 国内版は毎日チェックイン API、国際版はデイリーアクティブクエスト:イベントを探し、デイリーアクティブ報酬を受け取り、無料モデルでキープアライブし、Web チャネルでセッションを張って日次アクティブを点灯。小浣熊はデスクトップの日次ポイント経路。AutoClaw は公式クライアントの毎日チェックインタスク。Qoder 中国版はイベント受領で、イベントを付与されていないアカウントは中立的な通知を受け取ります。Qoder 国際版はデバイスのリスク管理 ID(ローカル Qoder クライアント / qodercli の UMID コンポーネントが生成)を持たないと「毎日 100 Credits」イベントが表示されず、コンポーネントがなければエラーではなく明確な説明が返ります。Trae は SOLO の毎日チェックインポイントを受け取り(0 時リセット)、上流がイベントを用意していない、または認証情報にデバイス ID がない場合は「未受領 + 理由」が返ります。Loomy は毎日 1 回初回ログインポイントを付け、KukuAI は「無料ポイント」の日次タスクを受け取り、CodeArts は当日の運営特典を受け取ります(受領 → 確認 → 再読で検証。自動実行は 1 日 6 回 / 10 分間隔の書き込みレート制限内)。OfficeAce はその日の特典を一括で受け取ります(毎日チェックイン + 新規特典))。時刻を逃しても起動時に自動で追補するため、電源が入っていなくても取りこぼしません。各社のチェックイン API は冪等で、繰り返しても二重受け取りにはなりません。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると、チェックしたプロバイダーの利用可能なアカウントを自動でチェックインします(WorkBuddy 中国版はデイリーチェックイン API、国際版はデイリーアクティブタスク:イベントを検出して日活報酬を受け取り、無料モデルでキープアライブ。小浣熊はデスクトップ版のデイリー積分経路。AutoClaw は公式クライアントのデイリーチェックインタスク。Qoder 中国版はイベント受け取りで、イベントが配信されていないアカウントには中立的な案内が出ます。Qoder 国際版はデバイスリスク制御 ID(本機の Qoder クライアント / qodercli の UMID コンポーネントで生成)を付けて初めて「毎日 100 Credits」イベントが見えるようになり、コンポーネントが欠けている場合はエラーではなく明確な説明が出ます。Trae は SOLO のデイリーチェックイン積分を受け取り(自然日 0 時にリセット)、アップストリームがそのアカウントにイベントを開いていない場合や認証情報にデバイス ID がない場合は、エラーではなく「未受け取り + 具体的な理由」が返ります。Loomy は毎日アカウントの初回ログイン積分を 1 回付与します。KukuAI は「無料積分受け取り」のデイリータスクを消化します;CodeArts はその日の運営特典を受け取ります(受け取り → 確認 → 読み戻し検証。自動実行は 1 日 6 回・間隔 10 分の書き込み制限を受けます);OfficeAce はその日の報酬を一度の操作でまとめて受け取ります(毎日チェックイン+新規特典))。時刻を逃しても、起動後に自動で補完チェックインされ、当時電源が入っていなかったことを理由に漏れることはありません。各社のチェックイン API はすべて冪等なので、繰り返し実行しても二重に受け取ることはありません。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると、チェックしたプロバイダーの利用可能なアカウントを自動でチェックインします(WorkBuddy 中国版はデイリーチェックイン API、国際版はデイリーアクティブタスク:イベントを検出して日活報酬を受け取り、無料モデルでキープアライブ。小浣熊はデスクトップ版のデイリー積分経路。AutoClaw は公式クライアントのデイリーチェックインタスク。Qoder 中国版はイベント受け取りで、イベントが配信されていないアカウントには中立的な案内が出ます。Qoder 国際版はデバイスリスク制御 ID(本機の Qoder クライアント / qodercli の UMID コンポーネントで生成)を付けて初めて「毎日 100 Credits」イベントが見えるようになり、コンポーネントが欠けている場合はエラーではなく明確な説明が出ます。Trae は SOLO のデイリーチェックイン積分を受け取り(自然日 0 時にリセット)、アップストリームがそのアカウントにイベントを開いていない場合や認証情報にデバイス ID がない場合は、エラーではなく「未受け取り + 具体的な理由」が返ります。Loomy は毎日アカウントの初回ログイン積分を 1 回付与します。KukuAI は「無料積分受け取り」のデイリータスクを消化します;OfficeAce はその日の報酬を一度の操作でまとめて受け取ります(毎日チェックイン+新規特典))。時刻を逃しても、起動後に自動で補完チェックインされ、当時電源が入っていなかったことを理由に漏れることはありません。各社のチェックイン API はすべて冪等なので、繰り返し実行しても二重に受け取ることはありません。", "到点时逐个签到,已勾 {n} / {total} 家": "定刻に 1 社ずつチェックインします。選択 {n} / {total} 社", "北京时间 · 错过时点开机后会自动补签": "北京時間 · 起動時に自動で補完します", "去领取": "受け取りへ", "另有 {n} 个账号不参与每日签到": "ほかにデイリーチェックインの対象外のアカウントが {n} 件", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "完了済みタスクの報酬のみ受け取り(冪等・連打しても二重加算されません)", "可完成": "完了可能", "可派出": "出発可能", "可选 · 缺省显示时刻": "任意 · 未指定では時刻を表示", "可领奖": "受け取り可能", "后端未返回定时签到数据": "バックエンドがスケジュールデータを返しませんでした", "后端未返回签到中心数据": "バックエンドがチェックインセンターのデータを返しませんでした", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "国際版のチェックインには、UMID コンポーネントで生成するデバイスリスク制御 ID が必要です(本機では検出されませんでした)。", "在途": "旅行中", "填入缺省链": "既定のチェーンを入力", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "時刻と範囲を決めて「保存」を押してください。名前は空欄でも構いません(空欄なら時刻を表示)", "失败 {n}": "失敗 {n}", "套餐明细": "プラン明細", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "Qoder クライアントまたは qodercli をインストールすれば利用できます(ゲートウェイの再起動は不要)。", "安装中…": "インストール中…", "官方客户端的每日签到任务": "公式クライアントのデイリーチェックインタスク", "定时签到": "定期チェックイン", "定时签到已关闭": "定期チェックインを無効にしました", "尚未查询": "未照会", "尚未查询任务状态": "タスク状態は未クエリ", "巡检一次": "1 回実行", "已保存:{label}": "保存しました:{label}", "已保存:保活模型链": "保存しました:キープアライブモデルチェーン", "已保存:定时条目": "保存しました:スケジュール", "已删除定时条目": "スケジュールを削除しました", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "アクティビティを報告しました(連続ログイン達成)が、キャンペーンは未実施です(今回の報酬はなし)", "已抽 {n} 次": "{n} 回抽選しました", "已有结果 {checked} / 共 {total} 个账号": "結果あり {checked} / 全 {total} アカウント", "已签": "チェックイン済み", "已领 {claimed}/{total} · 累计 {earned} 积分": "受け取り済み {claimed}/{total} · 累計 {earned} 積分", "已领养": "飼い主になりました", "已领取": "受け取り済み", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "デバイスリスク制御 ID を付けて「毎日 100 Credits」を受け取り · UMID コンポーネントが必要", "开学季执行失败:{error}": "新学期の実行に失敗:{error}", "开学季执行完成:{message}": "新学期の実行が完了:{message}", "开学季活动": "新学期イベント", "开着:启用的条目按各自时刻执行": "オン:有効なスケジュールがそれぞれの時刻に実行されます", "待签": "未チェックイン", "待领新手福利": "受け取り待ちの初心者ボーナス", "总开关": "マスタースイッチ", "总开关已关闭 · 在「定时签到」页打开": "マスタースイッチがオフです · 「定期チェックイン」タブで有効化してください", "成功 {n}": "成功 {n}", "成长任务": "成長タスク", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "成長タスク完了(成功 {done} 件・失敗 {failed} 件):クレジット +{credit} エネルギー +{energy}", "成长任务执行失败:{error}": "成長タスクの実行に失敗:{error}", "执行失败:{error}": "実行に失敗しました:{error}", "执行并抽奖": "実行して抽選", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "新学期タスクを実行し、抽選回数を使い切る(シェア/会話/エキスパートイベント)", "把缺省链填进清单,再点「保存」生效": "既定のチェーンを一覧に入れます。「保存」で反映されます", "抽奖机会 {n} 次": "抽選チャンス {n} 回", "按住拖动调整顺序": "押したままドラッグで並べ替え", "按住拖动,调整这个模型在链里的顺序": "押したままドラッグして、チェーン内でのこのモデルの順序を変更します", "按序逐个尝试,共 {n} 个": "順番に試行、計 {n} 件", "按结果筛选": "結果で絞り込み", "探测 + 领取 + 保活 · 与定时签到同一套组合": "検出 + 受け取り + キープアライブ · 定期チェックインと同じ組み合わせ", "探测活动并领取日活奖励 · 不做保活": "イベントを検出して日活報酬を受け取り · キープアライブは行わない", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "受注+点灯+受け取り(実測で検証済みのタスクのみ処理)", "搜账号 / 收益 / 错误 / 触发原因": "アカウント / 収益 / エラー / トリガー理由を検索", "收起新建": "新規入力を閉じる", "新建定时条目": "新しい定時エントリ", "新手福利": "初心者ボーナス", "新手福利有 {n} 项领取失败,可重试": "初心者ボーナスで {n} 件の受け取りに失敗しました。再試行できます", "无": "なし", "无独立签到接口 · 每天替账号打一次首次登录积分": "専用のチェックイン API なし · 毎日アカウントの初回ログイン積分を 1 回付与", "无账号": "アカウントなし", "暂不可领": "受け取り不可", "暂不支持": "未対応", "暂无启用的条目 · 点此添加": "有効なスケジュールがありません · クリックして追加", "有未保存的改动": "未保存の変更があります", "未勾选提供商": "プロバイダー未選択", "未开启": "未有効", "未解锁": "未解禁", "未领养(领养需先完成当日对话量)": "未飼育(飼育には当日の会話量の達成が先に必要)", "未领取": "未受け取り", "本地台账里今天还没领过;活动期内每天发一份新套餐": "ローカルの記録では本日まだ受け取っていません。キャンペーン期間中は毎日新しいプランが 1 件配布されます", "本地台账里今天(北京时间)领过的套餐:{plans}": "ローカル記録で本日(北京時間)受け取ったプラン:{plans}", "条启用": "件有効", "查询于 {time}": "{time} にクエリ", "查询任务": "タスクをクエリ", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "タスクツリーを照会してワンクリックで点灯/受け取り(新学期・ねこ旅行を含む)", "查询失败:{error}": "クエリに失敗しました:{error}", "桌面端每日积分链路": "デスクトップ版のデイリー積分経路", "正在读取定时签到数据…": "定期チェックインデータを読み込み中…", "正在读取签到数据…": "チェックインデータを読み込み中…", "每天 {time}": "毎日 {time}", "每天 {time} · {scope}": "毎日 {time} · {scope}", "每天时刻": "毎日の時刻", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "チェックイン1回ごとに · アカウントごとに1行 · 結果と収益はバックエンドの記録が正", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "毎日のアクティブタスク · Webチャネルの会話で日活を達成、ポイントは受け取りで加算 · 両方は別々に実行可能", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "毎日ログインポイント · あわせて会員アクティビティを受け取り · ゲストアカウントはポイント体系なし(スキップ)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "デイリー特典 · 受け取り → 確認 → 読み戻し検証 · 北京時間の自然日でリセット", "每日签到": "デイリーチェックイン", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "スケジュールごとに時刻と範囲 · 当日はそれぞれ重複排除 · 起動時に自動補完", "每账号一条明细 · 点此查看「签到记录」": "アカウントごとに1行 · 「チェックイン記録」を開く", "没有可领套餐的账号(ZCode 未添加)。": "受け取れるプランのあるアカウントがありません(ZCode 未追加)。", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "受け取れる特典のあるアカウントがありません(CodeArts / ZCode が未追加)。", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "成長タスクに対応するアカウントがありません(WorkBuddy 中国版が必要)。", "没有支持新手福利的账号": "初心者ボーナスに対応するアカウントがありません", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "初心者ボーナスに対応するアカウントがありません —— 現在は Loomy、小浣熊、CodeArts の 3 社です。", "没有符合筛选条件的签到记录": "絞り込み条件に一致するチェックイン記録がありません", "没有需要执行的任务": "実行するタスクはありません", "活动福利": "イベント特典", "活动(campaign)领取 · 每天 10:00 刷新": "イベント(campaign)の受け取り · 毎日 10:00 に更新", "活跃上报与保活均未成功,且活动未开启": "アクティビティの報告とキープアライブの両方に失敗し、キャンペーンも未実施です", "活跃上报完成,但保活未成功且活动未开启": "アクティビティの報告は完了しましたが、キープアライブに失敗し、キャンペーンも未実施です", "活跃上报完成,但活动未开启": "アクティビティを報告しましたが、キャンペーンは未実施です", "活跃上报成功": "アクティビティの報告に成功しました", "活跃保活失败": "アクティブのキープアライブに失敗しました", "活跃保活完成": "アクティブのキープアライブが完了しました", "活跃保活完成,但活动未开启": "アクティブのキープアライブは完了しましたが、イベントが有効ではありません", "活跃保活完成,但活跃上报失败且活动未开启": "キープアライブは完了しましたが、アクティビティの報告に失敗し、キャンペーンも未実施です", "添加条目": "スケジュールを追加", "添加模型": "モデルを追加", "清单为空 —— 保存后恢复缺省链": "リストが空です — 保存すると既定のチェーンに戻ります", "清单里已经有「{name}」": "リストに「{name}」はすでにあります", "清空失败:{error}": "クリアに失敗しました:{error}", "清空签到记录": "チェックイン記録をクリア", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "「プラン明細」で受け取ったプランと有効になる時期を確認できます。キャンペーン期間中は毎日また受け取れます", "点击行展开账号明细 · 单账号签到不受范围限制": "行をクリックしてアカウントの詳細を展開 · 単一アカウントのチェックインは範囲の制限を受けません", "独立链路 · 只提供手动入口 · 不进自动签到": "独立した経路 · 手動入口のみ · 自動チェックインには含まれない", "猫猫旅行": "ねこ旅行", "猫猫旅行失败:{error}": "ねこ旅行に失敗:{error}", "猫猫旅行失败:{message}": "ねこ旅行に失敗:{message}", "猫猫旅行:{message}": "ねこ旅行:{message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "無料モデルとWebチャネルの会話でアカウントのアクティブ状態を維持 · 報酬は受け取らない", "确定删除「{name}」?删除后到点不再执行。": "「{name}」を削除しますか?削除後は予定時刻に実行されません。", "确定清空全部签到记录?清空后无法恢复。": "すべてのチェックイン記録をクリアしますか?クリア後は復元できません。", "确定清空当前筛选出的签到记录?清空后无法恢复。": "現在の絞り込みに一致するチェックイン記録をクリアしますか?クリア後は復元できません。", "移除 {name}": "{name} を削除", "立即全部签到": "今すぐ一括チェックイン", "签到": "チェックイン", "签到中…": "チェックイン中…", "签到中心分区": "チェックインセンターのセクション", "签到失败:{error}": "チェックインに失敗しました:{error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "チェックイン完了:{succeeded}/{total} 成功{active}、{failed} 件失敗", "签到成功": "チェックインに成功しました", "签到提供商": "チェックインプロバイダー", "签到范围": "チェックイン範囲", "签到触发时刻": "チェックイン実行時刻", "签到记录": "チェックイン記録", "签到记录时间范围": "チェックイン記録の時間範囲", "签到记录表": "チェックイン記録テーブル", "累计签到记录": "累計チェックイン記録", "结算于 {time}": "{time} に確定", "能量 {n}": "エネルギー {n}", "腾讯每日签到接口 · 仅国内版": "Tencent のデイリーチェックイン API · 中国版のみ", "至少勾一家才能保存(不勾等于这条条目不签到)": "保存するには 1 社以上選択してください(未選択=このエントリは何もチェックインしません)", "读取定时签到数据失败:{error}": "定期チェックインデータの読み込みに失敗しました:{error}", "读取签到数据失败:{error}": "チェックインデータの読み込みに失敗しました:{error}", "读取签到记录失败:{error}": "チェックイン記録の読み込みに失敗しました:{error}", "跳过 {n}": "スキップ {n}", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "運営イベントの受け渡し(受け取り → 確認 → 読み戻しで検証)· 受け取るのはプラン特典積分", "还没执行过": "まだ実行されていません", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "スケジュールがまだありません —— 「スケジュールを追加」で作成するか、「チェックインセンター」で手動チェックインしてください。", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "チェックイン記録はまだありません —— 手動チェックインまたは定期実行の後に、明細がここに表示されます。", "连登 {n} 天": "連続ログイン {n} 日", "部分": "一部", "重签": "再チェックイン", "重试": "再試行", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "期間限定お試しプラン · 受け取りにはスライダー認証が必要 · 1 件ずつ確認して受け取り", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "期間限定体験プラン(start-plan)。開催期間中は毎日 1 件 · 受け取りにはスライダー認証が必要", "需真实操作": "実際の操作が必要", "非活动期": "イベント期間外", "项": "件", "领取": "受け取る", "领取中": "受け取り中", "领取中…": "受け取り中…", "领取失败": "受け取りに失敗", "领取失败:{error}": "受け取りに失敗しました:{error}", "(共 {n} 个账号)": "(全 {n} アカウント)", "(能量 / 连登读数本次未取到)": "(エネルギー/連続ログインの数値は今回取得できませんでした)", ",日活保活 {n} 个": "、日活キープアライブ {n} 件" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "SOLO の checkin_credits 受け取り · 自然日 0 時に更新", "UMID 组件安装失败:{error}": "UMID コンポーネントのインストールに失敗しました:{error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy 中国版 · タスクツリーを照会してワンクリックで点灯/受け取り · 新学期イベントとねこ旅行を含む · 行をクリックで詳細", "WorkBuddy 国际版保活模型,按顺序回退": "WorkBuddy 国際版のキープアライブ用モデル(順番にフォールバック)", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "WorkBuddy国際版のデイリーアクティビティ用の無料モデル · 全体で1つの設定、スケジュールとは無関係", "{date}(每天 {time})": "{date}(毎日 {time})", "{label} ×{count}({reason})": "{label} ×{count}({reason})", "{n} 项可完成": "完了可能 {n} 件", "{n} 项待领": "{n} 件受け取り待ち", "{total} 账号 · {done} 已签": "{total} アカウント · {done} チェックイン済み", "{total} 项任务 · {pending} 项可完成": "タスク {total} 件 · 完了可能 {pending} 件", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ UMID コンポーネントをインストールしました。次回のチェックインで国際版の積分を受け取れます", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ 定期チェックインを有効にしました", "✅ 开学季任务执行完成": "✅ 新学期タスクの実行が完了しました", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ 成長タスク完了:クレジット +{credit} エネルギー +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ 初心者ボーナスの受け取りが完了しました。累計 {n} 積分", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ チェックイン完了:{succeeded}/{total} 件のアカウントが受け取りに成功{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "「キープアライブモデルチェーン」は、WorkBuddy国際版のデイリーアクティビティでアカウントを活性化し続けるための無料モデルです。順に試し、最初の成功で止まります。空で送信すると既定({defaults})に戻します。当日の重複排除+冪等な受け取り:再実行しても「受取済み」が返るだけで、ポイントが二重に加算されることはありません。", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "「キープアライブモデルチェーン」は、WorkBuddy国際版のデイリーアクティビティでアカウントを活性化し続けるための無料モデルです。順に試し、最初の成功で止まります。リストを空にして保存すると既定のチェーン(現在の既定:{defaults})に戻ります。当日の重複排除+冪等な受け取り:再実行しても「受取済み」が返るだけで、ポイントが二重に加算されることはありません。", "「免费领积分」的每日任务 · 逐个领取": "「無料積分受け取り」のデイリータスク · 1 つずつ受け取る", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "一度きりの特典 · チェックイン後に自動で照会して受け取り、受け取り済みは本機に記録し以降はアップストリームに問い合わせません · 行をクリックしてタスク一覧を展開", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "その日の報酬を一度にまとめて受け取ります(毎日チェックイン+新規特典) · 冪等性はアップストリームが保証", "一键安装组件": "ワンクリックでインストール", "一键完成": "一括完了", "一键领取({n})": "一括受け取り({n})", "上次执行:{line}": "前回実行:{line}", "上次签到时间": "前回のチェックイン時刻", "上次领取 {time} · 领取需通过滑块验证码": "前回の受け取り {time} · 受け取りにはスライダー認証が必要", "下次 {date}": "次回 {date}", "下次 {date} · 点此管理条目": "次回 {date} · クリックしてスケジュールを管理", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "デイリーチェックインの対象外:{list}。CodeArts の一度きりの特典は下の「初心者ボーナス」に、CodeArts と ZCode の日次/プラン特典の受け取りは「アクティビティ特典」にあります。", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "デイリーチェックインの対象外:{list}。CodeArts の一度きりの特典は下の「初心者ボーナス」、CodeArts のデイリー特典はすぐ上の「デイリーチェックイン」にあります。ZCode のプラン受け取りは「アクティビティ特典」です。", "与国内版同一套任务接口 · 站点不同": "中国版と同じタスク API · サイトが異なる", "与国内版同一套链路 · 站点不同、令牌不通用": "中国版と同じフロー · サイトが異なり、トークンに互換性なし", "今天已领 {n} 份": "本日 {n} 件受け取り済み", "今天未领": "本日は未受取", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "本日(北京時間 {day})受け取り済み · 公式に {n} 件の到着を確認 · 明日また受け取れます", "今日已执行": "本日実行済み", "今日已派出": "本日は出発済み", "今日已领取": "本日受け取り済み", "今日签到": "本日のチェックイン", "今日签到进度": "本日のチェックイン進捗", "从清单里移除": "リストから削除", "保活": "キープアライブ", "保活 {n}": "キープアライブ {n}", "保活+领取": "キープアライブ+受け取り", "保活中…": "キープアライブ中…", "保活模型链": "キープアライブモデルチェーン", "全选": "すべて選択", "全部 {n} 家": "全 {n} 社", "全部完成": "すべて完了", "全部查询": "一括クエリ", "全部结果": "すべての結果", "全部账号均可签到": "すべてのアカウントがチェックイン可能", "全部领取": "すべて受け取り済み", "关着:开机后等到窗口起点再签,随机窗口当天生效": "オフ:起動後はウィンドウ開始まで待ち、当日からランダムウィンドウを適用", "关着:所有条目都不执行": "オフ:どのスケジュールも実行されません", "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "分 · ウィンドウ内で各アカウントをランダムな時刻に実行、0 = 定刻に即実行", "删除失败:{error}": "削除に失敗しました:{error}", "删除定时条目": "スケジュールを削除", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると選択プロバイダーの利用可能なアカウントをサインインします(WorkBuddy 中国版は毎日チェックイン API、国際版はデイリーアクティブタスク:アクティビティ検出・日次報酬受取・無料モデルでキープアライブと Web セッションで連続日数を点灯。小浣熊はデスクトップの毎日ポイント経路、AutoClaw は公式クライアントの毎日サインインタスク、Qoder 中国版はキャンペーン受取でキャンペーン未配信のアカウントには中立の案内を表示、Qoder 国際版はデバイス風控身分(ローカルの Qoder クライアント / qodercli の UMID コンポーネントが生成)が必要で、コンポーネント欠如時はエラーではなく明確な説明を表示。Trae は SOLO の毎日チェックインクレジット(現地 0 時リセット)を受け取り、上流がアカウントにキャンペーンを出していない場合や資格情報にデバイス ID がない場合はエラーではなく「未受取 + 理由」を返します。Loomy は毎日初回ログインポイントを 1 回呼び、KukuAI は「無料ポイント」の毎日タスクを受け取り、CodeArts は当日の運営特典(受取 → 確認 → 読み戻し、自動実行は 1 日 6 回・10 分間隔の書き込み制限あり)を受け取り、OfficeAce はその日の全報酬(毎日チェックイン + 新規特典)を 1 回で受け取ります)。「ランダム幅 N 分」を設定すると、その回のアカウントは各自のウィンドウ内(当日 0:00〜23:59 にクランプ)に分散して実行され、同じ 1 分に集中しません。ウィンドウを過ぎている場合は全員すぐに実行します。逃した回は起動後にキャッチアップするので、電源が入っていなかったことで失われることはありません(「起動時キャッチアップ」をオフにするとウィンドウ開始まで待つ動作になります)。各プロバイダーのチェックイン API は冪等で、繰り返し実行しても二重取得にはなりません。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると、チェックしたプロバイダーの利用可能なアカウントを自動でチェックインします(WorkBuddy 中国版はデイリーチェックイン API、国際版はデイリーアクティブタスク:イベントを検出して日活報酬を受け取り、無料モデルでキープアライブ。小浣熊はデスクトップ版のデイリー積分経路。AutoClaw は公式クライアントのデイリーチェックインタスク。Qoder 中国版はイベント受け取りで、イベントが配信されていないアカウントには中立的な案内が出ます。Qoder 国際版はデバイスリスク制御 ID(本機の Qoder クライアント / qodercli の UMID コンポーネントで生成)を付けて初めて「毎日 100 Credits」イベントが見えるようになり、コンポーネントが欠けている場合はエラーではなく明確な説明が出ます。Trae は SOLO のデイリーチェックイン積分を受け取り(自然日 0 時にリセット)、アップストリームがそのアカウントにイベントを開いていない場合や認証情報にデバイス ID がない場合は、エラーではなく「未受け取り + 具体的な理由」が返ります。Loomy は毎日アカウントの初回ログイン積分を 1 回付与します。KukuAI は「無料積分受け取り」のデイリータスクを消化します;CodeArts はその日の運営特典を受け取ります(受け取り → 確認 → 読み戻し検証。自動実行は 1 日 6 回・間隔 10 分の書き込み制限を受けます);OfficeAce はその日の報酬を一度の操作でまとめて受け取ります(毎日チェックイン+新規特典))。時刻を逃しても、起動後に自動で補完チェックインされ、当時電源が入っていなかったことを理由に漏れることはありません。各社のチェックイン API はすべて冪等なので、繰り返し実行しても二重に受け取ることはありません。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "時刻になると、チェックしたプロバイダーの利用可能なアカウントを自動でチェックインします(WorkBuddy 中国版はデイリーチェックイン API、国際版はデイリーアクティブタスク:イベントを検出して日活報酬を受け取り、無料モデルでキープアライブ。小浣熊はデスクトップ版のデイリー積分経路。AutoClaw は公式クライアントのデイリーチェックインタスク。Qoder 中国版はイベント受け取りで、イベントが配信されていないアカウントには中立的な案内が出ます。Qoder 国際版はデバイスリスク制御 ID(本機の Qoder クライアント / qodercli の UMID コンポーネントで生成)を付けて初めて「毎日 100 Credits」イベントが見えるようになり、コンポーネントが欠けている場合はエラーではなく明確な説明が出ます。Trae は SOLO のデイリーチェックイン積分を受け取り(自然日 0 時にリセット)、アップストリームがそのアカウントにイベントを開いていない場合や認証情報にデバイス ID がない場合は、エラーではなく「未受け取り + 具体的な理由」が返ります。Loomy は毎日アカウントの初回ログイン積分を 1 回付与します。KukuAI は「無料積分受け取り」のデイリータスクを消化します;OfficeAce はその日の報酬を一度の操作でまとめて受け取ります(毎日チェックイン+新規特典))。時刻を逃しても、起動後に自動で補完チェックインされ、当時電源が入っていなかったことを理由に漏れることはありません。各社のチェックイン API はすべて冪等なので、繰り返し実行しても二重に受け取ることはありません。", "到点时逐个签到,已勾 {n} / {total} 家": "定刻に 1 社ずつチェックインします。選択 {n} / {total} 社", "北京时间 · 错过时点开机后会自动补签": "北京時間 · 起動時に自動で補完します", "去领取": "受け取りへ", "另有 {n} 个账号不参与每日签到": "ほかにデイリーチェックインの対象外のアカウントが {n} 件", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "完了済みタスクの報酬のみ受け取り(冪等・連打しても二重加算されません)", "可完成": "完了可能", "可派出": "出発可能", "可选 · 缺省显示时刻": "任意 · 未指定では時刻を表示", "可领奖": "受け取り可能", "后端未返回定时签到数据": "バックエンドがスケジュールデータを返しませんでした", "后端未返回签到中心数据": "バックエンドがチェックインセンターのデータを返しませんでした", "启动补签": "起動時キャッチアップ", "启动补签已关闭": "起動時キャッチアップを無効にしました", "启动补签已开启": "起動時キャッチアップを有効にしました", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "国際版のチェックインには、UMID コンポーネントで生成するデバイスリスク制御 ID が必要です(本機では検出されませんでした)。", "在途": "旅行中", "填入缺省链": "既定のチェーンを入力", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "時刻と範囲を決めて「保存」を押してください。名前は空欄でも構いません(空欄なら時刻を表示)", "失败 {n}": "失敗 {n}", "套餐明细": "プラン明細", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "Qoder クライアントまたは qodercli をインストールすれば利用できます(ゲートウェイの再起動は不要)。", "安装中…": "インストール中…", "官方客户端的每日签到任务": "公式クライアントのデイリーチェックインタスク", "定时签到": "定期チェックイン", "定时签到已关闭": "定期チェックインを無効にしました", "尚未查询": "未照会", "尚未查询任务状态": "タスク状態は未クエリ", "巡检一次": "1 回実行", "已保存:{label}": "保存しました:{label}", "已保存:保活模型链": "保存しました:キープアライブモデルチェーン", "已保存:定时条目": "保存しました:スケジュール", "已删除定时条目": "スケジュールを削除しました", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "アクティビティを報告しました(連続ログイン達成)が、キャンペーンは未実施です(今回の報酬はなし)", "已抽 {n} 次": "{n} 回抽選しました", "已有结果 {checked} / 共 {total} 个账号": "結果あり {checked} / 全 {total} アカウント", "已签": "チェックイン済み", "已领 {claimed}/{total} · 累计 {earned} 积分": "受け取り済み {claimed}/{total} · 累計 {earned} 積分", "已领养": "飼い主になりました", "已领取": "受け取り済み", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "デバイスリスク制御 ID を付けて「毎日 100 Credits」を受け取り · UMID コンポーネントが必要", "开学季执行失败:{error}": "新学期の実行に失敗:{error}", "开学季执行完成:{message}": "新学期の実行が完了:{message}", "开学季活动": "新学期イベント", "开着:启用的条目按各自时刻执行": "オン:有効なスケジュールがそれぞれの時刻に実行されます", "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "オン:起動後、本日未実行のスケジュールをランダムウィンドウを無視して即補完", "待签": "未チェックイン", "待领新手福利": "受け取り待ちの初心者ボーナス", "总开关": "マスタースイッチ", "总开关已关闭 · 在「定时签到」页打开": "マスタースイッチがオフです · 「定期チェックイン」タブで有効化してください", "成功 {n}": "成功 {n}", "成长任务": "成長タスク", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "成長タスク完了(成功 {done} 件・失敗 {failed} 件):クレジット +{credit} エネルギー +{energy}", "成长任务执行失败:{error}": "成長タスクの実行に失敗:{error}", "执行失败:{error}": "実行に失敗しました:{error}", "执行并抽奖": "実行して抽選", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "新学期タスクを実行し、抽選回数を使い切る(シェア/会話/エキスパートイベント)", "把缺省链填进清单,再点「保存」生效": "既定のチェーンを一覧に入れます。「保存」で反映されます", "抽奖机会 {n} 次": "抽選チャンス {n} 回", "按住拖动调整顺序": "押したままドラッグで並べ替え", "按住拖动,调整这个模型在链里的顺序": "押したままドラッグして、チェーン内でのこのモデルの順序を変更します", "按序逐个尝试,共 {n} 个": "順番に試行、計 {n} 件", "按结果筛选": "結果で絞り込み", "探测 + 领取 + 保活 · 与定时签到同一套组合": "検出 + 受け取り + キープアライブ · 定期チェックインと同じ組み合わせ", "探测活动并领取日活奖励 · 不做保活": "イベントを検出して日活報酬を受け取り · キープアライブは行わない", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "受注+点灯+受け取り(実測で検証済みのタスクのみ処理)", "搜账号 / 收益 / 错误 / 触发原因": "アカウント / 収益 / エラー / トリガー理由を検索", "收起新建": "新規入力を閉じる", "新建定时条目": "新しい定時エントリ", "新手福利": "初心者ボーナス", "新手福利有 {n} 项领取失败,可重试": "初心者ボーナスで {n} 件の受け取りに失敗しました。再試行できます", "无": "なし", "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "専用のチェックイン API なし · 1 日 1 回アカウントの代わりにログイン情報エンドポイントを叩く(それが当日の魔粒)", "无独立签到接口 · 每天替账号打一次首次登录积分": "専用のチェックイン API なし · 毎日アカウントの初回ログイン積分を 1 回付与", "无账号": "アカウントなし", "暂不可领": "受け取り不可", "暂不支持": "未対応", "暂无启用的条目 · 点此添加": "有効なスケジュールがありません · クリックして追加", "有未保存的改动": "未保存の変更があります", "未勾选提供商": "プロバイダー未選択", "未开启": "未有効", "未解锁": "未解禁", "未领养(领养需先完成当日对话量)": "未飼育(飼育には当日の会話量の達成が先に必要)", "未领取": "未受け取り", "本地台账里今天还没领过;活动期内每天发一份新套餐": "ローカルの記録では本日まだ受け取っていません。キャンペーン期間中は毎日新しいプランが 1 件配布されます", "本地台账里今天(北京时间)领过的套餐:{plans}": "ローカル記録で本日(北京時間)受け取ったプラン:{plans}", "条启用": "件有効", "查询于 {time}": "{time} にクエリ", "查询任务": "タスクをクエリ", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "タスクツリーを照会してワンクリックで点灯/受け取り(新学期・ねこ旅行を含む)", "查询失败:{error}": "クエリに失敗しました:{error}", "桌面端每日积分链路": "デスクトップ版のデイリー積分経路", "正在读取定时签到数据…": "定期チェックインデータを読み込み中…", "正在读取签到数据…": "チェックインデータを読み込み中…", "每天 {time}": "毎日 {time}", "每天 {time} · {scope}": "毎日 {time} · {scope}", "每天 {time} · 随机前后 {n} 分钟 · {scope}": "毎日 {time} 前後 {n} 分 · {scope}", "每天时刻": "毎日の時刻", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "チェックイン1回ごとに · アカウントごとに1行 · 結果と収益はバックエンドの記録が正", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "毎日のアクティブタスク · Webチャネルの会話で日活を達成、ポイントは受け取りで加算 · 両方は別々に実行可能", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "毎日ログインポイント · あわせて会員アクティビティを受け取り · ゲストアカウントはポイント体系なし(スキップ)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "デイリー特典 · 受け取り → 確認 → 読み戻し検証 · 北京時間の自然日でリセット", "每日签到": "デイリーチェックイン", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "スケジュールごとに時刻と範囲 · 当日はそれぞれ重複排除 · 起動時に自動補完", "每账号一条明细 · 点此查看「签到记录」": "アカウントごとに1行 · 「チェックイン記録」を開く", "没有可领套餐的账号(ZCode 未添加)。": "受け取れるプランのあるアカウントがありません(ZCode 未追加)。", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "受け取れる特典のあるアカウントがありません(CodeArts / ZCode が未追加)。", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "成長タスクに対応するアカウントがありません(WorkBuddy 中国版が必要)。", "没有支持新手福利的账号": "初心者ボーナスに対応するアカウントがありません", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "初心者ボーナスに対応するアカウントがありません —— 現在は Loomy、小浣熊、CodeArts の 3 社です。", "没有符合筛选条件的签到记录": "絞り込み条件に一致するチェックイン記録がありません", "没有需要执行的任务": "実行するタスクはありません", "活动福利": "イベント特典", "活动(campaign)领取 · 每天 10:00 刷新": "イベント(campaign)の受け取り · 毎日 10:00 に更新", "活跃上报与保活均未成功,且活动未开启": "アクティビティの報告とキープアライブの両方に失敗し、キャンペーンも未実施です", "活跃上报完成,但保活未成功且活动未开启": "アクティビティの報告は完了しましたが、キープアライブに失敗し、キャンペーンも未実施です", "活跃上报完成,但活动未开启": "アクティビティを報告しましたが、キャンペーンは未実施です", "活跃上报成功": "アクティビティの報告に成功しました", "活跃保活失败": "アクティブのキープアライブに失敗しました", "活跃保活完成": "アクティブのキープアライブが完了しました", "活跃保活完成,但活动未开启": "アクティブのキープアライブは完了しましたが、イベントが有効ではありません", "活跃保活完成,但活跃上报失败且活动未开启": "キープアライブは完了しましたが、アクティビティの報告に失敗し、キャンペーンも未実施です", "添加条目": "スケジュールを追加", "添加模型": "モデルを追加", "清单为空 —— 保存后恢复缺省链": "リストが空です — 保存すると既定のチェーンに戻ります", "清单里已经有「{name}」": "リストに「{name}」はすでにあります", "清空失败:{error}": "クリアに失敗しました:{error}", "清空签到记录": "チェックイン記録をクリア", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "「プラン明細」で受け取ったプランと有効になる時期を確認できます。キャンペーン期間中は毎日また受け取れます", "点击行展开账号明细 · 单账号签到不受范围限制": "行をクリックしてアカウントの詳細を展開 · 単一アカウントのチェックインは範囲の制限を受けません", "独立链路 · 只提供手动入口 · 不进自动签到": "独立した経路 · 手動入口のみ · 自動チェックインには含まれない", "猫猫旅行": "ねこ旅行", "猫猫旅行失败:{error}": "ねこ旅行に失敗:{error}", "猫猫旅行失败:{message}": "ねこ旅行に失敗:{message}", "猫猫旅行:{message}": "ねこ旅行:{message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "無料モデルとWebチャネルの会話でアカウントのアクティブ状態を維持 · 報酬は受け取らない", "确定删除「{name}」?删除后到点不再执行。": "「{name}」を削除しますか?削除後は予定時刻に実行されません。", "确定清空全部签到记录?清空后无法恢复。": "すべてのチェックイン記録をクリアしますか?クリア後は復元できません。", "确定清空当前筛选出的签到记录?清空后无法恢复。": "現在の絞り込みに一致するチェックイン記録をクリアしますか?クリア後は復元できません。", "移除 {name}": "{name} を削除", "立即全部签到": "今すぐ一括チェックイン", "签到": "チェックイン", "签到中…": "チェックイン中…", "签到中心分区": "チェックインセンターのセクション", "签到失败:{error}": "チェックインに失敗しました:{error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "チェックイン完了:{succeeded}/{total} 成功{active}、{failed} 件失敗", "签到成功": "チェックインに成功しました", "签到提供商": "チェックインプロバイダー", "签到范围": "チェックイン範囲", "签到触发时刻": "チェックイン実行時刻", "签到记录": "チェックイン記録", "签到记录时间范围": "チェックイン記録の時間範囲", "签到记录表": "チェックイン記録テーブル", "累计签到记录": "累計チェックイン記録", "结算于 {time}": "{time} に確定", "能量 {n}": "エネルギー {n}", "腾讯每日签到接口 · 仅国内版": "Tencent のデイリーチェックイン API · 中国版のみ", "至少勾一家才能保存(不勾等于这条条目不签到)": "保存するには 1 社以上選択してください(未選択=このエントリは何もチェックインしません)", "读取定时签到数据失败:{error}": "定期チェックインデータの読み込みに失敗しました:{error}", "读取签到数据失败:{error}": "チェックインデータの読み込みに失敗しました:{error}", "读取签到记录失败:{error}": "チェックイン記録の読み込みに失敗しました:{error}", "跳过 {n}": "スキップ {n}", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "運営イベントの受け渡し(受け取り → 確認 → 読み戻しで検証)· 受け取るのはプラン特典積分", "还没执行过": "まだ実行されていません", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "スケジュールがまだありません —— 「スケジュールを追加」で作成するか、「チェックインセンター」で手動チェックインしてください。", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "チェックイン記録はまだありません —— 手動チェックインまたは定期実行の後に、明細がここに表示されます。", "连登 {n} 天": "連続ログイン {n} 日", "部分": "一部", "重签": "再チェックイン", "重试": "再試行", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "期間限定お試しプラン · 受け取りにはスライダー認証が必要 · 1 件ずつ確認して受け取り", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "期間限定体験プラン(start-plan)。開催期間中は毎日 1 件 · 受け取りにはスライダー認証が必要", "随机前后": "ランダム幅", "需真实操作": "実際の操作が必要", "非活动期": "イベント期間外", "项": "件", "领取": "受け取る", "领取中": "受け取り中", "领取中…": "受け取り中…", "领取失败": "受け取りに失敗", "领取失败:{error}": "受け取りに失敗しました:{error}", "(共 {n} 个账号)": "(全 {n} アカウント)", "(能量 / 连登读数本次未取到)": "(エネルギー/連続ログインの数値は今回取得できませんでした)", ",日活保活 {n} 个": "、日活キープアライブ {n} 件" }); diff --git a/desktop-tauri/ui/i18n/ko/add-account.js b/desktop-tauri/ui/i18n/ko/add-account.js index ef34db34..e6b45d87 100644 --- a/desktop-tauri/ui/i18n/ko/add-account.js +++ b/desktop-tauri/ui/i18n/ko/add-account.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:ko/add-account —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · 모델 {head}{rest}", " 等 {n} 个": " 등 {n}개", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "1//로 시작하는 Google refresh token (refresh_token=… 줄 전체를 붙여넣어도 됨)", "11 位大陆手机号": "11자리 중국 본토 휴대폰 번호", "1~64 个字符,账号列表里按它分组显示": "1~64자, 계정 목록에서 이 값을 기준으로 그룹화되어 표시됩니다", "6 位数字": "6자리 숫자", "

  • 没有可自动领的活动
  • ": "
  • 자동으로 수령할 수 있는 이벤트가 없습니다
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    수령하는 것은 플랜 증정 포인트이며, 혜택 모델의 token 풀은 늘지 않습니다;", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "Anthropic 호환 엔드포인트는 https://api.deepseek.com/anthropic입니다 (프로토콜을 anthropic으로 바꿀 때 입력합니다)", "Anthropic 协议填根地址,不要带 /v1": "Anthropic 프로토콜은 루트 주소를 입력하고 /v1은 붙이지 마세요", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw 중국판", "AutoClaw 国际版": "AutoClaw 국제판", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS는 필수입니다; **전체 Cookie**를 붙여넣으세요 (Cookie 편집기에서 원클릭 내보내기 가능) — 이 중 **PTOKEN은 반드시 남겨 두세요**. 게이트웨이가 이것을 사용해 Baidu에서 KukuAI 비즈니스 세션 토큰을 교환 발급받으며, 없으면 모델 갱신 시 「미로그인」 오류가 발생합니다. 전체 Cookie 헤더, Cookie 편집기에서 내보낸 JSON 배열, 또는 {BDUSS, STOKEN} 객체를 지원합니다. KukuAI에는 갱신 메커니즘이 없으므로 로그인 상태가 만료되면 다시 붙여넣으면 됩니다.", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=… (또는 Cookie 편집기에서 내보낸 JSON)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "CatPaw의 X-Passport-Token (로그인 상태 Cookie)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Cline Pass의 API Key는 app.cline.bot에서 발급받습니다(구독제). 엔드포인트는 OpenAI 호환이며, 모델 목록은 Cline 콘솔을 기준으로 하고, 모델 이름은 모델 관리에서 접두사 없는 이름 그대로 추가합니다(예: glm-5.2 / kimi-k2.7-code / deepseek-v4-pro). 업스트림이 클라이언트 형태를 검증하므로 필요한 클라이언트 요청 헤더는 이 카드에 미리 설정되어 있습니다", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT (3단 점 구분)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT(점 3개 구분. Bearer 전체 줄 또는 data.bin 내용을 붙여넣어도 됨)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT(점 3개로 구분된 형식. chatglm_token=… 줄을 그대로 붙여도 됩니다)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode 국제판", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM 관리형 엔드포인트, Key는 integrate.api.nvidia.com에서 신청합니다", "OfficeAce 果办": "OfficeAce", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken은 Accio의 로그인 자격 증명입니다 (길고 불투명한 token 문자열이며 JWT가 아닙니다); refreshToken은 선택이며, 입력하면 만료 시 자동 갱신됩니다. {label} 계정의 자격 증명을 입력하세요 — {siteNote} (가장 쉽게 얻는 방법: 위의 「웹 로그인」을 바로 사용하세요. token을 직접 찾을 필요가 없습니다.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken은 Trae의 Cloud-IDE-JWT이며(3단 점 구분), refreshToken은 만료 시 자동 갱신에 사용됩니다 (이 제공자는 refreshToken이 교환할 때마다 바뀝니다: 한 번 교환하면 이전 것은 무효가 되므로 두 프로그램에서 같은 계정을 동시에 갱신하지 마세요).
    수동으로 붙여넣을 때는 machineId / deviceId도 함께 입력하세요: 업스트림은 이를 로그인 시 업로드한 기기 공개 키와 묶어 기기를 판별하므로, 갑자기 새로운 값을 넣으면 2xxxx 계열 기기 바인딩 거부가 발생합니다.
    이 세 가지가 없을 때의 올바른 방법은 위의 「웹 로그인」이며, 컨테이너 / 원격 배포 환경에서는 안내에 따라 주소 표시줄의 콜백 주소를 붙여넣으면 됩니다.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "monkeycode_ai_session의 값 (전체 Cookie를 붙여넣어도 됨)", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken은 선택이며, 입력하면 만료 시 자동 갱신됩니다; 둘 다 小浣熊 클라이언트 로그인 상태 파일에서 얻을 수 있습니다.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken은 선택이며, 입력하면 자동 갱신됩니다; 둘 다 클라이언트 로그인 상태 파일에서 얻을 수 있습니다. 같은 Cline 계정은 두 풀 모두에서 사용할 수 있으며, 여기서는 {label}로 분류됩니다.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token은 enc: 접두사를 지원합니다 (Windows에서는 자동 복호화). refreshToken을 입력하지 않으면 자동 갱신할 수 없습니다.", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "token은 로그인 상태 Cookie입니다; CatPaw에는 갱신 메커니즘이 없어 만료 후 클라이언트에서 다시 로그인해야 합니다.", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "user_로 시작하는 API Key (Authorization: Bearer … 줄 전체를 붙여넣어도 됨)", "{label} 网页登录的打开方式": "{label} 웹 로그인을 여는 방식", "{label} 账号地区": "{label} 계정 지역", "{label} 账号的添加方式": "{label} 계정 추가 방식", "{name} 不是合法 JSON:{reason}": "{name}은(는) 올바른 JSON이 아닙니다: {reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name}에는 JSON 객체를 붙여넣어야 합니다 (예: {sample})", "{n} 个账号": "계정 {n}개", "{n} 个账号,点击添加": "계정 {n}개, 클릭하여 추가", "{seconds}s 后重发": "{seconds}초 후 재발송", "✅ {label}账号已添加": "✅ {label} 계정을 추가했습니다", "✅ {label}账号已添加{name}": "✅ {label} 계정을 추가했습니다{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ cc-switch에서 제공자 {n}개를 가져왔습니다", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ 커스텀 제공자 「{name}」을(를) 만들고 계정을 추가했습니다", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ 커스텀 제공자 「{name}」을(를) 삭제했습니다{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ 기존 계정{name}을(를) 업데이트했습니다(동일한 API Key는 하나만 유지되며 다시 추가하면 병합됩니다)", "✅ 登录成功,{edition}账号已加入列表": "✅ 로그인 성공, {edition} 계정을 목록에 추가했습니다", "✅ 领取成功:{planId}{period}": "✅ 수령 성공: {planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " 같은 제공자에 key를 여러 개 둘 수 있으며, 우선순위에 따라 로테이션됩니다.", "「{name}」的账号添加功能还在开发中,敬请期待。": "「{name}」의 계정 추가 기능은 아직 개발 중입니다. 기대해 주세요.", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "하나의 Key로 여러 제공자의 모델을 사용할 수 있으며, 모델 이름은 「벤더/모델」 전체 이름을 씁니다 (예: deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "업스트림이 인증을 요구하지 않으면 비워 두고 아래 항목을 체크하세요 (비워 두고 체크하지 않으면 자격 증명 미설정으로 간주됩니다)", "上游信息": "업스트림 정보", "不可领({status})": "수령 불가 ({status})", "不支持导入": "가져오기 미지원", "不是有效的凭证文件:内容要是一个 JSON 对象": "유효한 자격 증명 파일이 아닙니다. 내용은 JSON 객체여야 합니다", "不是有效的凭证文件:需要包含 accessToken 与 uid": "유효한 자격 증명 파일이 아닙니다. accessToken과 uid가 필요합니다", "不是自定义提供商": "커스텀 제공자가 아닙니다", "不需要 Key:转发与拉取模型都不发送鉴权头": "Key 불필요: 포워딩과 모델 조회 모두 인증 헤더를 보내지 않습니다", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "로그인이 필요 없습니다. 아래 버튼을 누르면 게이트웨이가 智谱清言에서 게스트 자격 증명을 직접 발급받아 계정 목록에 추가합니다(먼저 메모 이름을 입력해도 됩니다). 게스트 자격 증명은 바로 대화에 쓸 수 있고, 무료 할당량은 업스트림이 기기 단위로 발급합니다.

    주의: 게스트 계정에는 포인트 체계가 없습니다. 회원 포인트, 매일 로그인 포인트, 활동 수령 관련 인터페이스는 모두 로그인이 필요하므로 이러한 기능은 게스트에서 건너뜁니다(계정 페이지의 포인트와 签到 센터에 수치가 표시되지 않습니다). 포인트가 필요하면 \"자격 증명 입력\"으로 로그인된 계정 토큰을 붙여넣거나 \"데스크톱 로그인 상태 가져오기\"를 사용하세요.", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "두 판의 계정을 동시에 저장할 수 있으며 각각 별도의 모델 목록을 가집니다 (중국판과 국제판은 서로 다른 두 제공자로, 각각 활성화하고 매핑할 수 있습니다).", "中国版": "중국판", "今天没有需要领的活动(都已到账)": "오늘 수령할 이벤트가 없습니다 (모두 적립됨)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "오늘(베이징 시간 {day}) {attempts}회 시도했고, {left}회 더 시도할 수 있습니다{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "다른 컴퓨터(또는 OfficeAce 데스크톱 앱의 models.json)에서 다음 세 항목을 가져와 붙여넣으세요: 모델 게이트웨이 기본 주소(baseUrl, https://modelgw-…/v2 형태)와 modelAppKey / modelAppSecret. 이 세 항목만 있으면 전달할 수 있습니다(게이트웨이 자격 증명은 만료되지 않음). 제어 영역 임시 자격 증명(accessKeyId 등)은 선택이며, 비워 두면 잔액 조회와 자동 갱신을 쓸 수 없지만 전달에는 영향이 없습니다.", "从本机导入桌面端登录态": "이 컴퓨터에서 데스크톱 로그인 상태 가져오기", "任务镜像 id": "작업 이미지 id", "余额查询": "잔액 조회", "使用 Google 账号登录": "Google 계정으로 로그인", "使用 Zai 账号登录": "Zai 계정으로 로그인", "使用个人访问令牌(PAT)": "개인 액세스 토큰(PAT) 사용", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "무료 모델은 Key를 입력하지 않아도 됩니다 (기본적으로 「이 업스트림은 인증이 필요하지 않음」이 체크되어 있고, 게이트웨이가 자동으로 익명 자격 증명을 사용합니다); 유료 모델은 Zen의 API Key를 입력하세요. 무료 등급 업스트림은 공식 클라이언트 형태만 허용하므로 「OpenCode 공식 클라이언트로 위장」이 기본으로 켜져 있습니다", "内嵌窗口": "내장 창", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "내장 창으로 엽니다; 창을 닫으면 대기가 취소됩니다 (Google 계정이 거부되면 시스템 브라우저를 사용하세요)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "내장 창으로 엽니다; 완료하면 자동으로 목록에 추가되고, 창을 닫으면 대기가 취소됩니다", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "내장 창으로 열립니다. 스캔이 끝나면 자동으로 목록에 추가되며, 창을 닫으면 대기가 취소됩니다", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "내장 창은 새 환경을 사용하므로 여러 계정이 서로 영향을 주지 않습니다; 창을 닫으면 대기가 취소됩니다", "内嵌窗口(推荐)": "내장 창(권장)", "准备验证…": "인증 준비 중…", "凭据 JSON": "자격 증명 JSON", "凭证文件在哪?": "자격 증명 파일 위치는?", "创建并添加账号": "생성하고 계정 추가", "创建这个提供商,并同时建立它的第一个账号。": "이 제공자를 만들고 동시에 첫 계정을 생성합니다.", "删除功能不可用(脚本未就绪)": "삭제 기능을 사용할 수 없습니다 (스크립트가 준비되지 않음)", "删除失败:{reason}": "삭제 실패: {reason}", "删除此提供商": "이 제공자 삭제", "及 {n} 个账号": " 및 계정 {n}개", "发送中…": "전송 중…", "发送失败:{message}": "전송 실패: {message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "전송 미확인: 로그인 창이 열렸습니다. 열린 창에서 직접 로그인을 완료하세요", "取消失败:{message}": "취소 실패: {message}", "取消等待": "대기 취소", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "「내장 창」에서만 제3자 로그인 항목을 복원할 수 있습니다: 시스템 브라우저에서는 로그인 페이지를 수정할 수 없습니다", "可选": "선택", "可选(cloudaicompanionProject):留空由网关自动发现": "선택 (cloudaicompanionProject): 비워 두면 게이트웨이가 자동으로 찾습니다", "可选,展示用": "선택, 표시용", "可选,没有则无法自动续期": "선택, 없으면 자동 갱신 불가", "可选,留空使用凭据里的 user_name": "선택, 비워 두면 자격 증명의 user_name 사용", "可选,留空使用账号姓名、邮箱或令牌指纹": "선택, 비워 두면 계정 이름, 이메일 또는 토큰 지문 사용", "可选,留空使用账号昵称或邮箱": "선택, 비워 두면 계정 닉네임 또는 이메일 사용", "可选,留空则用 key 尾号": "선택, 비워 두면 key 끝자리 사용", "可选,留空则用 userId": "선택, 비워 두면 userId 사용", "可选,留空则用上游返回的账号名或账号 id": "선택, 비워 두면 업스트림이 반환한 계정 이름 또는 계정 id 사용", "可选,留空则用凭证里的账号名": "선택, 비워 두면 자격 증명의 계정 이름 사용", "可选,留空则用文件里的昵称": "선택 사항, 비워 두면 파일의 닉네임 사용", "可选,留空则用登录名或 uid": "선택, 비워 두면 로그인 이름 또는 uid 사용", "可选,留空则用脱敏手机号": "선택, 비워 두면 마스킹된 휴대폰 번호 사용", "可选,留空则用脱敏手机号或 userId": "선택, 비워 두면 마스킹된 휴대폰 번호 또는 userId 사용", "可选,留空则用账号 uk": "선택, 비워 두면 계정 uk 사용", "可选,留空则用账号昵称": "선택 사항. 비워 두면 계정 닉네임을 사용합니다", "可选,留空则用账号昵称或 userId": "선택 사항. 비워 두면 계정 닉네임 또는 userId 사용", "可选,留空则用邮箱或令牌尾号": "선택, 비워 두면 이메일 또는 토큰 끝자리 사용", "可选,留空用「OfficeAce 果办」": "선택, 비워 두면 「OfficeAce」 사용", "可选,留空自动生成": "선택, 비워 두면 자동 생성", "可选,留空自动用昵称": "선택, 비워 두면 닉네임 자동 사용", "可选,给这个访客账号起个备注名": "선택 사항. 이 게스트 계정의 메모 이름", "可选,续期时带上": "선택, 갱신 시 함께 전송", "可选,讯飞侧 userid": "선택, iFlytek 측 userid", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "선택; 대화 시작에 필요합니다. 비워 두면 게이트웨이가 이 계정의 기존 작업에서 자동으로 찾습니다. 찾지 못하면 나중에 직접 입력하면 됩니다.", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "선택; 계정 이메일로, 표시와 신원 식별에 사용됩니다 (새 토큰으로 바꿔도 같은 계정으로 인식됩니다)", "可选;UUID 形态,与凭据同生共死": "선택; UUID 형식이며 자격 증명과 함께 생성되고 함께 사라집니다", "可选;填了才能到期自动续期": "선택; 입력해야 만료 시 자동 갱신할 수 있습니다", "可选;用于去重与展示名(留空时网关会问一次上游)": "선택; 중복 제거와 표시 이름에 사용됩니다 (비워 두면 게이트웨이가 업스트림에 한 번 물어봅니다)", "可选;用于生成账号 id 与展示名": "선택; 계정 id와 표시 이름 생성에 사용됩니다", "可选;纯数字串(上游只收 8–24 位数字)": "선택; 숫자만 입력 (업스트림은 8–24자리 숫자만 허용)", "可领取": "수령 가능", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "한 제공사에 API Key 있는 계정과 인증 불필요 계정을 섞어 둘 수 있으며 각각의 규칙으로 라우팅됩니다. 인증 불필요 계정도 여러 개 둘 수 있고 각각 다른 아웃바운드 프록시를 설정할 수 있습니다", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "같은 주소에서 anthropic 프로토콜로 바꾸면 해당 Claude 호환 엔드포인트를 사용합니다. 포워딩에는 OpenCode Go의 API Key가 반드시 필요합니다 (구독제; 모델 목록 조회에는 Key가 필요 없지만, 요청을 보내면 업스트림이 401 「Missing API key」를 반환합니다)", "响应为空": "응답이 비어 있습니다", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "SenseNova 의 OpenAI 호환 엔드포인트. 잔액 조회는 콘솔 계정 / 비밀번호를 사용합니다 (아래 \"잔액 조회\" 단락 참조)", "国内版": "중국판", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "중국판과 **국제판은 서로 독립된 두 세트의 계정과 플랜**입니다. 자격 증명과 수령한 플랜은 서로 호환되지 않습니다.", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "중국판 로그인 페이지에는 Google / GitHub 항목이 없습니다 (WeChat / 휴대폰 번호 / 이메일로 로그인합니다)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "중국판의 로그인 사이트는 www.accio-ai.com이며, 국제판과 같은 사이트가 아닙니다.", "国内版(WorkBuddy)": "중국판 (WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "중국 사이트는 https://api.siliconflow.cn/v1입니다", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "중국 사이트 (minimaxi.com); OpenAI 호환 주소는 https://api.minimaxi.com/v1입니다", "国际版": "국제판", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "국제판 z.ai의 Coding 플랜; OpenAI 호환 주소는 https://api.z.ai/api/coding/paas/v4입니다", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "국제판과 중국판은 **서로 독립된 두 세트의 계정**입니다 (같은 계정 체계의 두 사이트). 자격 증명은 호환되지 않습니다.", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "국제판과 중국판은 계정 체계가 독립적입니다. 국제판의 자격 증명을 입력하세요. refreshToken을 입력하지 않으면 자동 갱신할 수 없습니다.", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "국제판 로그인 페이지는 기본적으로 이메일 로그인만 표시하며, 체크하면 Google / GitHub / X 항목이 복원됩니다", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "국제판의 추론 사이트는 api.z.ai이며 중국판과 다른 사이트입니다; 플랜도 각각 독립적입니다.", "国际版(WorkBuddy AI)": "국제판 (WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "국제 사이트 Coding 플랜; OpenAI 호환 주소는 https://api.minimax.io/v1입니다", "在 cc-switch 里找到": "cc-switch에서 찾은", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "내장 창에서 공식 로그인을 완료하면 성공 시 자동으로 계정 목록에 추가됩니다.", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "{label}의 Qoder 계정 설정 → Integrations에서 PAT를 생성하세요 (Google / GitHub 토큰을 입력하지 마세요). 두 지역의 계정과 자격 증명은 호환되지 않습니다.", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "열린 공식 인증 페이지에서 위챗 QR 코드를 스캔하여 로그인하세요(페이지에 QR 코드가 바로 표시됩니다). 스캔에 성공하면 계정이 자동으로 목록에 추가됩니다.", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "열린 창에서 Baidu 계정으로 KukuAI 메인 사이트에 로그인하세요 (SMS 인증 코드 / QR 스캔 모두 가능). 로그인에 성공하면 자동으로 계정 목록에 추가됩니다. 게이트웨이는 Baidu에서 KukuAI 비즈니스 세션 토큰을 교환 발급받습니다 (이 컴퓨터에 KukuAI 클라이언트가 설치되어 있어야 합니다).", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "열린 창에서 Google 계정으로 로그인하세요(Antigravity의 인가 페이지). 인가가 완료되면 자동으로 계정 목록에 추가됩니다.", "在浏览器中打开登录页": "브라우저에서 로그인 페이지 열기", "地区": "지역", "填写凭证": "자격 증명 입력", "填写凭证添加": "자격 증명 입력 후 추가", "备注名": "라벨명", "套餐": "플랜", "如:智谱 GLM": "예: Zhipu GLM", "完成登录后自动加入账号列表,昵称取自上游。": "로그인을 완료하면 자동으로 계정 목록에 추가되며, 닉네임은 업스트림에서 가져옵니다.", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "공식 클라이언트 자격 증명 디렉터리: Windows는 C:\\Users\\<사용자명>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth, macOS는 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "공식 적립 확인 완료", "导入": "가져오기", "导入中…": "가져오는 중…", "导入凭证文件": "자격 증명 파일 가져오기", "导入失败": "가져오기 실패", "导入失败:{reason}": "가져오기 실패: {reason}", "导入所选": "선택 항목 가져오기", "导入所选({n})": "선택 항목 가져오기({n})", "导入桌面端登录态": "데스크톱 로그인 상태 가져오기", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "내장 창이 열립니다; 인가가 완료되면 자동으로 계정 목록에 추가됩니다. 창을 닫으면 대기가 취소됩니다. 인가 페이지 마지막에 zcode:// 링크를 열 수 없다는 안내가 나올 수 있는데, 정상입니다 — 결과는 이미 서버 측에 기록되었습니다", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "내장 창이 열립니다; 인가가 완료되면 자동으로 계정 목록에 추가됩니다. 원격 패널에서는 콜백 주소를 붙여넣을 수 있습니다. 창을 닫으면 대기가 취소됩니다. 링크는 5분간 유효하며, 시간이 초과되거나 클릭하지 않으면 무효가 됩니다 (다시 시작할 수 있습니다)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "내장 창이 열립니다; 로그인이 완료되면 자동으로 계정 목록에 추가됩니다. 창을 닫으면 대기가 취소됩니다", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "시스템 기본 브라우저로 인가 페이지를 엽니다 (브라우저에 로그인된 Trae 계정을 재사용합니다); 같은 컴퓨터에서는 완료 시 자동으로 추가되며, Docker / 원격 패널에서는 안내에 따라 주소 표시줄의 콜백 주소를 붙여넣으세요.", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "시스템 기본 브라우저로 인가 페이지를 엽니다 (브라우저에 로그인된 ZCode 계정을 재사용합니다); 인가가 완료되면 자동으로 계정 목록에 추가됩니다. 페이지 마지막에 zcode:// 링크를 열 수 없다는 안내가 나올 수 있는데 정상입니다", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "시스템 기본 브라우저로 인가 페이지를 엽니다 (브라우저에 로그인된 Huawei Cloud 계정을 재사용합니다); 인가 코드는 게이트웨이가 클라우드를 폴링해 가져오므로 브라우저가 어느 컴퓨터에서 실행되는지는 상관없습니다. 완료하면 자동으로 계정 목록에 추가됩니다", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "시스템 기본 브라우저로 인가 페이지를 엽니다 (브라우저에 로그인된 Huawei Cloud 계정을 재사용합니다); 브라우저와 게이트웨이가 같은 컴퓨터에 있지 않다면 위 설명대로 최종 콜백 주소를 패널에 다시 붙여넣으세요", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "시스템 기본 브라우저로 로그인 페이지를 엽니다 (브라우저에 로그인된 Accio 계정을 재사용합니다); 로그인을 완료하면 자동으로 계정 목록에 추가되며, 팝업을 닫으면 대기가 취소됩니다", "小米 MiMo Token Plan 套餐(新加坡站)": "小米 MiMo Token Plan 플랜 (싱가포르 사이트)", "已到账": "적립 완료", "已取消登录等待": "로그인 대기를 취소했습니다", "已取消领取": "수령을 취소했습니다", "已取消验证码": "인증 코드를 취소했습니다", "已填写手机号,正在发送验证码…": "휴대폰 번호 입력 완료, 인증 코드 전송 중…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "인증 필요 없음으로 선언됨: 계정이 정상적으로 라우팅되며, 외부로 나갈 때 인증 헤더를 전혀 보내지 않습니다", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "가져오기 성공 {ok}개, 실패 {fail}개 (실패 항목은 목록에 표시해 두었습니다)", "已建过 · {n} 个账号,点击继续添加": "이미 생성됨 · 계정 {n}개, 클릭하여 추가", "已建过,点击继续添加账号": "이미 생성됨, 클릭하여 계정 추가", "已打开官方登录页,请在窗口中完成登录…": "공식 로그인 페이지를 열었습니다. 창에서 로그인을 완료하세요…", "已点发送,等待短信…": "전송을 눌렀습니다. SMS 대기 중…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "시스템 기본 브라우저로 로그인 페이지를 열었습니다. 브라우저에서 로그인을 완료하세요…", "已领取,等官方确认": "수령 완료, 공식 확인 대기 중", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "현재 앱 버전에서는 AutoClaw 웹 로그인을 지원하지 않습니다. 앱을 업데이트하세요", "当前没有可领取的套餐(活动尚未开始)": "현재 수령 가능한 플랜이 없습니다 (이벤트가 아직 시작되지 않았습니다)", "当前环境不支持领取(桥接方法缺失)": "현재 환경에서는 수령을 지원하지 않습니다 (브리지 메서드 없음)", "必填,CatPaw 账号标识": "필수, CatPaw 계정 식별자", "恢复 Google / GitHub 入口": "Google / GitHub 항목 복원", "手机号": "휴대폰 번호", "手机验证码登录": "SMS 인증 코드 로그인", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "Trae SOLO의 공식 인가 페이지(trae.cn)를 열고 Trae 계정으로 로그인하세요: 인가가 완료되면 공식 페이지가 이 컴퓨터의 임시 포트로 되돌아옵니다; 같은 컴퓨터 배포에서는 자동으로 수신하며, Docker / 원격 패널에서는 안내에 따라 주소 표시줄의 콜백 주소를 복사하세요.", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "Accio {label}의 공식 로그인 페이지({site})를 열고 Accio 계정으로 로그인하세요: 로그인에 성공하면 공식 페이지가 이 컴퓨터로 되돌아옵니다; 같은 컴퓨터에서는 자동으로 완료되며, Docker / 원격 패널에서는 안내에 따라 콜백 주소를 붙여넣으면 됩니다 (인가 코드는 이 컴퓨터에서만 게이트웨이에 전달되며, 화면에 평문 token이 표시되지 않습니다).", "打开 Accio {label}登录页": "Accio {label} 로그인 페이지 열기", "打开 Antigravity 网页登录": "Antigravity 웹 로그인 열기", "打开 CatPaw 网页登录": "CatPaw 웹 로그인 열기", "打开 Cline 授权页": "Cline 인가 페이지 열기", "打开 CodeArts 授权页": "CodeArts 인가 페이지 열기", "打开 Qoder 网页登录": "Qoder 웹 로그인 열기", "打开 Trae 授权页": "Trae 인가 페이지 열기", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "ZCode {label}의 공식 인가 페이지를 열고 계정으로 로그인하세요. 인가 결과는 ZCode 서버에 기록되며, 게이트웨이가 백그라운드에서 자격 증명을 자동으로 가져와 계정 목록에 추가합니다.", "打开 ZCode {label}授权页": "ZCode {label} 인가 페이지 열기", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "Huawei Cloud CodeArts의 공식 인가 페이지를 열어 로그인하세요: 로그인이 완료되면 공식 페이지가 브라우저를 게이트웨이 자체의 /oauth/callback으로 되돌립니다. 게이트웨이는 일회성 인가 코드를 임시 자격 증명으로 교환하고 계정 목록에 추가합니다.
    게이트웨이가 다른 컴퓨터에서 실행 중이면 웹 UI에서 주소 표시줄의 최종 콜백 주소를 패널에 그대로 붙여넣으라는 안내가 표시됩니다.", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "Huawei Cloud 인가 페이지를 열고 로그인하세요: 완료되면 게이트웨이가 클라우드를 폴링해 인가 코드를 가져와 계정 목록에 추가합니다 (OfficeAce 데스크톱 앱이 필요 없고, 콜백 URL을 수동으로 다시 붙여넣을 필요도 없습니다).", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "공식 인가 페이지를 열어 기기 코드 인가를 완료하세요. 로그인되는 계정은 {label} ({site}) 계정입니다.", "打开授权页": "인가 페이지 열기", "打开授权页完成确认,账号自动加入 {label}{note}": "인가 페이지를 열어 확인을 완료하면 계정이 {label}에 자동으로 추가됩니다{note}", "打开方式": "여는 방식", "打开网页登录": "웹 로그인 열기", "探测失败:{message}": "탐지 실패: {message}", "接入一个兼容上游": "호환 업스트림 연결", "提交中…": "제출 중…", "搜索提供商": "제공자 검색", "搜索提供商…": "제공자 검색…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "공식 플러그인 / CLIProxyAPI가 디스크에 기록한 자격 증명 JSON을 통째로 붙여넣으세요 (형식: {\"codearts_provider_credential\":{…}}, 평탄화된 형태도 가능).
    필수: access_key_id, secret_access_key, security_token.자동 갱신을 원하면 refresh_token과 oauth_context도 함께 붙여넣어야 합니다 — 임시 자격 증명은 약 1시간 후 만료되며, 이 부분이 없으면 갱신할 수 없어 다시 로그인해야 합니다.", "文件是{edition}凭证,已按该版本导入": "파일은 {edition} 자격 증명이며 해당 버전으로 가져왔습니다", "新建自定义提供商": "커스텀 제공자 새로 만들기", "方案:{label}": "방식: {label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "평문 JWT 또는 auth.json의 enc: 암호화 값 (자동 복호화)", "明文 JWT(国际版账号的 access token)": "평문 JWT (국제판 계정의 access token)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "Zhipu bigmodel.cn의 Coding 플랜, Key는 open.bigmodel.cn/usercenter/apikeys에서 발급합니다", "未知错误": "알 수 없는 오류", "未能获取授权地址,请重试": "인가 주소를 가져오지 못했습니다. 다시 시도하세요", "未能读取 cc-switch 数据": "cc-switch 데이터를 읽지 못했습니다", "未领取成功": "수령하지 못했습니다", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "로컬 Ollama, OpenCode Zen 무료 등급 같은 업스트림에는 체크해야 하며, 그렇지 않으면 계정을 사용할 수 없습니다", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "이 제공자에는 **서로 대체할 수 없는** 자격 증명이 두 개 있습니다. 사용할 기능에 따라 입력하고 최소 하나는 입력하세요: 코딩 플랜 API Key는 추론 포워딩({site} 호출)과 윈도우 할당량 조회(N시간마다 / 주간 잔여 비율)에 사용하고, jwt는 플랜 수령과 잔액 조회에 사용합니다(zcode.z.ai의 billing 게이트웨이 호출, 공식 명칭 Coding Plan JWT, 3단 점 구분 문자열). 잔액은 둘 다 조회할 수 있지만 읽어 오는 내용이 다릅니다: jwt는 잔액 버킷과 플랜 만료를, API Key는 윈도우 할당량을 읽습니다. 수령은 jwt만, 포워딩은 API Key만 인정합니다. {label} 계정의 자격 증명을 입력하세요 — {plan} (가장 쉽게 얻는 방법: 위의 「웹 로그인」을 바로 사용하세요 — 이 API Key를 대신 교환해 두 자격 증명을 함께 받아 줍니다.)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "이 컴퓨터의 Ollama OpenAI 호환 엔드포인트, API Key 불필요 (기본적으로 「이 업스트림은 인증이 필요하지 않음」이 체크되어 있고, 인증 헤더를 전혀 보내지 않습니다)", "本次未确认到账": "이번에는 적립이 확인되지 않았습니다", "条可导入": "건을 가져올 수 있습니다", "条配置,其中": "건의 설정 중", "桌面运行时不可用(Tauri 未初始化)": "데스크톱 런타임을 사용할 수 없습니다 (Tauri 미초기화)", "模型网关基址": "모델 게이트웨이 기본 주소", "正在打开百度登录页…": "Baidu 로그인 페이지를 여는 중…", "正在扫描本机 cc-switch…": "이 컴퓨터의 cc-switch를 스캔하는 중…", "正在换发访客凭证…": "게스트 자격 증명을 발급하는 중…", "正在添加…": "추가하는 중…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "{name} 로그인 완료를 기다리는 중입니다; 완료하거나 취소한 후에 새로운 로그인을 시작할 수 있습니다", "每周": "매주", "每日": "매일", "每月": "매월", "没有则无法自动续期": "없으면 자동 갱신할 수 없습니다", "没有匹配「{keyword}」的提供商": "「{keyword}」와 일치하는 제공자가 없습니다", "添加 {name} 账号": "{name} 계정 추가", "添加中…": "추가 중…", "添加到 ": "추가 대상: ", "添加失败:{reason}": "추가 실패: {reason}", "添加小浣熊账号": "小浣熊 계정 추가", "添加方式": "추가 방식", "添加访客账号": "게스트 계정 추가", "添加账号": "계정 추가", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "Volcano Engine Coding 플랜; 범용 추론 엔드포인트는 https://ark.cn-beijing.volces.com/api/v3입니다", "点击添加账号": "클릭하여 계정 추가", "点开即预填,填 Key 接入": "열면 값이 미리 채워져 있으며, Key를 입력하면 연결됩니다", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "버튼을 누르면 먼저 슬라이더 인증을 한 번 통과하고(공식 리스크 관리), 이어서 로그인 페이지가 열리며 로그인이 완료되면 계정이 자동으로 추가됩니다.
    이것이 국제판의 공식 유일한 로그인 방식입니다; 이미 클라이언트에 로그인한 적이 있다면 「데스크톱 로그인 상태 가져오기」가 더 빠릅니다.", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "AutoClaw 계정에 연결된 휴대폰 번호로 로그인합니다: 「코드 받기」를 클릭하고 SMS를 받은 뒤 아래에 입력하여 로그인하세요. 인증 코드는 이 컴퓨터에서 공식 API로 직접 제출되며, 화면에 token이 표시되지 않습니다.", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "CatPaw 계정으로 로그인합니다 (Meituan passport), 성공하면 자동으로 계정 목록에 추가됩니다.", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "Loomy 계정에 연결된 휴대폰 번호로 로그인합니다: 「코드 받기」를 클릭한 뒤 입력하면 됩니다. 이 제공자에서 가장 간편한 방법입니다.", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "포워딩에 사용합니다; apiKey.secret 형태의 2단 점 구분 (입력하지 않으면 이 계정은 포워딩할 수 없습니다)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "플랜 수령과 잔액 조회에 사용합니다; 입력하지 않으면 이 계정은 수령과 잔액 조회를 할 수 없습니다", "用户 ID": "사용자 ID", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "연결된 휴대폰 번호로 로그인합니다: 「코드 받기」를 클릭한 뒤 입력하면 됩니다. 이것이 중국판의 공식 유일한 로그인 방식입니다.", "留空则用提供商名称": "비워 두면 제공자 이름 사용", "登录 / 添加 {name} 账号": "로그인 / {name} 계정 추가", "登录 session(一长串)": "로그인 session (긴 문자열)", "登录中…": "로그인 중…", "登录失败:{message}": "로그인 실패: {message}", "登录已结束": "로그인이 종료되었습니다", "登录并添加": "로그인 후 추가", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "로그인 상태 파일 경로: ~/.box-agent/config/auth.json (Windows: C:\\Users\\<사용자 이름>\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "커스텀 제공자 「{name}」을(를) 삭제할까요? 이 제공자 아래의 계정 {count}개도 함께 삭제되며, 삭제 후에는 복구할 수 없습니다.", "等待 Accio {label}登录完成…": "Accio {label} 로그인 대기 중…", "等待 CatPaw 登录完成…": "CatPaw 로그인 대기 중…", "等待 Cline 授权确认…": "Cline 인가 확인 대기 중…", "等待 CodeArts 登录完成…": "CodeArts 로그인 대기 중…", "等待 Google 授权完成…": "Google 인가 대기 중…", "等待 KukuAI 登录完成…": "KukuAI 로그인 대기 중…", "等待 OfficeAce 登录完成…": "OfficeAce 로그인 대기 중…", "等待 OrcaTerm 登录完成…": "OrcaTerm 로그인 대기 중…", "等待 Qoder 授权完成…": "Qoder 인가 대기 중…", "等待 Trae 授权完成…": "Trae 인가 대기 중…", "等待 ZCode {label}授权完成…": "ZCode {label} 인가 대기 중…", "等待小浣熊登录完成…": "小浣熊 로그인 대기 중…", "等待登录完成…": "로그인 완료 대기 중…", "等待网页登录…": "웹 로그인 대기 중…", "粘贴 API Key": "API Key 붙여넣기", "粘贴 Accio 的 accessToken": "Accio의 accessToken 붙여넣기", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Antigravity의 Google refresh token을 붙여넣으세요 (1//로 시작; refresh_token=이 포함된 줄 전체를 붙여넣어도 됨).
    웹 로그인 외의 수동 입구입니다(예: 로그인된 공식 IDE에서 내보내기). refresh token은 만료되지 않으며, access token 만료 시 게이트웨이가 자동으로 갱신합니다; 토큰을 잃어버리면 Google 인가를 다시 받아야 하므로 잘 보관하세요.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Command Code의 API Key를 붙여넣으세요 (user_로 시작; 공식 CLI의 ~/.commandcode/auth.json 또는 웹 studio에서 획득). 줄 전체 / 따옴표 포함 / Bearer 접두사 포함 그대로 붙여넣어도 됩니다. 게이트웨이가 알아서 순수한 key만 추출합니다. key는 만료되지 않고 갱신 인터페이스도 없으므로, 무효가 되면 다시 받으면 됩니다; 추가 시 게이트웨이가 가벼운 활성 확인을 한 번 수행하며, 실패해도 추가에는 영향을 주지 않습니다.", "粘贴 Cookie": "Cookie 붙여넣기", "粘贴 Google refresh token": "Google refresh token 붙여넣기", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "OrcaTerm의 OAuth accessToken(점 3개로 구분된 JWT. 데스크톱 클라이언트의 data.bin 또는 웹 버전 Cookie ot_session에서 확인)을 붙여넣으세요. Bearer / ot_session=이 포함된 줄을 그대로 붙여넣어도 되며, 게이트웨이가 토큰만 추출합니다. 추가 후에는 게이트웨이가 자동으로 갱신하므로(업스트림에 갱신 API가 있음) 2시간 만료를 직접 따라갈 필요가 없습니다.", "粘贴 Qoder 个人访问令牌(pt-…)": "Qoder 개인 액세스 토큰(pt-…) 붙여넣기", "粘贴 accessToken": "accessToken 붙여넣기", "粘贴 access_token(一长串 JWT)": "access_token 붙여넣기 (긴 JWT)", "粘贴 session cookie": "session cookie 붙여넣기", "粘贴 token / refreshToken": "token / refreshToken 붙여넣기", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "workos:…로 시작하는 토큰 붙여넣기 (접두사가 없어도 자동으로 붙습니다)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "智谱清言 액세스 토큰(점 3개로 구분된 JWT)을 붙여넣으세요. 발급 방법: 브라우저에서 chatglm.cn을 열고 로그인한 뒤 개발자 도구의 Application → Cookies에서 chatglm_token 값을 복사합니다(chatglm_token=…; 줄을 그대로 붙여도 됩니다). 붙여넣은 뒤 업스트림에 한 번 검증하며, 통과한 경우에만 계정을 저장합니다. 로그인된 계정은 포인트와 签到 기능을 쓸 수 있고, 이후 게이트웨이가 자동으로 갱신합니다(업스트림에 갱신 인터페이스가 있습니다).", "粘贴登录凭据": "로그인 자격 증명 붙여넣기", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "붙여넣는 것은 로그인 session입니다 (동시에 모델 게이트웨이의 token입니다). Loomy에는 갱신 인터페이스가 없으며 session 유효 기간은 약 14일이므로, 만료되면 다시 로그인하면 됩니다.", "粘贴网关凭据": "게이트웨이 자격 증명 붙여넣기", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "웹 로그인 상태 cookie monkeycode_ai_session의 값을 붙여넣으세요 (브라우저에서 전체 Cookie를 복사해 그대로 붙여넣어도 됩니다. 게이트웨이가 값을 알아서 추출합니다).
    {siteNote}
    MonkeyCode에는 갱신 인터페이스가 없습니다: session 유효 기간은 약 30일(하드 제한)이며, 만료되면 웹에 다시 로그인해 한 번 더 붙여넣으면 됩니다.", "粘贴访问令牌": "액세스 토큰 붙여넣기", "系统浏览器": "시스템 브라우저", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "시스템 브라우저는 기존 로그인 상태를 재사용할 수 있습니다 (국제판 권장); 내장 창이 더 깔끔합니다.", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "시스템 브라우저로 엽니다 (로그인된 Cline 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "시스템 브라우저로 엽니다(로그인된 Google 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "시스템 브라우저로 엽니다 (로그인된 Zai / Google 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "시스템 브라우저로 엽니다 (로그인된 Meituan 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "시스템 브라우저로 엽니다 (로그인된 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统默认浏览器": "시스템 기본 브라우저", "编码套餐 API Key": "코딩 플랜 API Key", "网关 Secret": "게이트웨이 시크릿", "网页登录": "웹 로그인", "网页登录的打开方式": "웹 로그인을 여는 방식", "网页登录(Zai / Google)": "웹 로그인 (Zai / Google)", "自定义": "커스텀", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "자체 구축 어그리게이션 패널: 자신의 사이트 주소를 입력하세요. 잔액 조회는 이 계정의 API 키로 {base}/v1/usage 를 호출하며 추가 설정이 필요 없습니다", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "자체 구축 어그리게이션 패널: 자신의 사이트 주소를 입력하세요. 잔액 조회에는 별도로 NewAPI 개인 액세스 토큰이 필요합니다 (아래 \"잔액 조회\" 단락 참조)", "获取风控配置失败,将直接尝试领取:{message}": "리스크 관리 구성을 가져오지 못했습니다. 바로 수령을 시도합니다: {message}", "获取验证码": "코드 받기", "访客模式": "게스트 모드", "访客模式(免登录)": "게스트 모드(로그인 불필요)", "该上游无需鉴权(不发送鉴权头)": "이 업스트림은 인증이 필요하지 않음 (인증 헤더를 보내지 않음)", "该提供商": "이 제공자", "该提供商账号添加功能即将上线": "이 제공자의 계정 추가 기능이 곧 출시됩니다", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "이 커스텀 제공자가 더 이상 존재하지 않습니다(삭제되었을 수 있습니다). 새로 고친 후 다시 시도하세요", "请先选择一个自定义提供商": "먼저 커스텀 제공자를 선택하세요", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "표시된 슬라이더에서 인증을 완료하세요 (공식에서 요구하는 리스크 관리 단계)", "请填写 11 位大陆手机号": "11자리 중국 본토 휴대폰 번호를 입력하세요", "请填写 6 位数字验证码": "6자리 숫자 인증 코드를 입력하세요", "请填写 Base URL": "Base URL을 입력하세요", "请填写 {label}": "{label}을(를) 입력하세요", "请填写名称": "이름을 입력하세요", "请完成验证…": "인증을 완료하세요…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "%APPDATA%/AutoClaw/auth.json을 읽어 복호화합니다. Windows 전용", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "~/.cline/data/settings/providers.json을 읽습니다. Cline 클라이언트에 로그인되어 있어야 합니다", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "~/.meituan-catpaw/auth.json을 읽습니다. CatPaw 클라이언트에 로그인되어 있어야 합니다", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "이 컴퓨터의 KukuAI 클라이언트 로그인 상태를 읽습니다 (%APPDATA%\\baidugenflowpro\\Network\\Cookies). KukuAI 클라이언트에 로그인되어 있어야 합니다", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "로컬 OrcaTerm 클라이언트 로그인 상태(%APPDATA%\\com.orcaterm-desktop.app\\data.bin)를 읽습니다. OrcaTerm 클라이언트에 로그인되어 있어야 합니다", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "이 PC의 智谱清言 클라이언트 로그인 상태를 읽습니다(%APPDATA%\\chatglm\\Network\\Cookies). 클라이언트에 로그인되어 있어야 합니다", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "이 컴퓨터의 공식 클라이언트(Tencent WorkBuddy / WorkBuddy AI)에 현재 로그인된 계정을 읽습니다. 자격 증명 디렉터리에서 최신 로그인 상태 파일을 자동으로 찾습니다(이 컴퓨터의 공식 클라이언트에 로그인되어 있어야 함). 가져온 후에는 게이트웨이가 자동 갱신하므로 2시간 유효 기간에 맞춰 토큰을 수동으로 교체할 필요가 없습니다.", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 읽습니다 (평문 Cookie, 복호화 불필요). 클라이언트 실행 중에는 Cookies 파일이 독점 점유되므로, 가져오기 전에 KukuAI 클라이언트를 먼저 종료하세요.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다).", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다). 클라이언트에서 다시 로그인한 후 「Token 갱신」을 눌러 동기화하세요.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다). 클라이언트에서 다시 로그인한 후 다시 가져오면 됩니다.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다). Zai / Google로 클라이언트에 로그인하는 사용자는 이 항목을 사용하세요.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다). 이 항목은 {label}로 분류됩니다.", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "로컬 클라이언트가 현재 로그인한 OAuth 토큰을 읽습니다(평문 JSON, 복호화 불필요). 가져온 뒤에는 게이트웨이가 자동으로 갱신하므로 클라이언트의 2시간 만료에 맞춰 수동으로 교체할 필요가 없습니다.", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "이 PC 클라이언트의 현재 로그인 상태를 읽습니다. 클라이언트의 Cookies는 DPAPI로 암호화되어 있어(Chromium os_crypt) Windows에서만 사용할 수 있습니다. 클라이언트가 실행 중이면 이 파일을 읽지 못할 수 있으니 클라이언트를 종료한 뒤 다시 시도하세요(\"자격 증명 입력\"으로 토큰을 붙여넣어도 됩니다).", "账号信息": "계정 정보", "账号信息不完整,请刷新后重试": "계정 정보가 불완전합니다. 새로 고친 후 다시 시도하세요", "账号已添加,但请留意:{warning}": "계정은 추가되었지만 확인해 주세요: {warning}", "账号版本": "계정 버전", "账号类型": "계정 유형", "账号:{name}
    ": "계정: {name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "Inference Providers 라우팅을 사용하며, Key는 hf.co/settings/tokens에서 만듭니다", "还没有账号": "아직 계정이 없습니다", "这一家当前不支持网页登录,请改用填写凭证": "이 제공자는 현재 웹 로그인을 지원하지 않습니다. 대신 자격 증명 입력을 사용하세요", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "이 계정에는 현재 자동으로 수령할 수 있는 이벤트가 없습니다 (매일 로그인 보너스 포인트만 자동 수령합니다)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "이 할당량은 「이벤트 플랜」 채널을 사용합니다: 포워딩 시 코딩 플랜이 만료되었다는 안내가 나오면, ", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "여기에는 중국 사이트(monkeycode-ai.com)의 계정을 입력합니다: 중국 사이트의 session을 붙여넣으세요. 국제 사이트(monkeycode-ai.net)는 다른 제공자이며 별도의 계정입니다. 양쪽 자격 증명은 호환되지 않습니다.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "여기에는 국제 사이트(monkeycode-ai.net)의 계정을 입력합니다: 국제 사이트의 session을 붙여넣으세요. 중국 사이트(monkeycode-ai.com)는 다른 제공자이며 별도의 계정입니다. 양쪽 자격 증명은 호환되지 않습니다.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "CatPaw 클라이언트의 로그인 상태 파일 auth.json을 선택하세요 (Windows: C:\\Users\\<사용자 이름>\\.meituan-catpaw\\auth.json, macOS / Linux: ~/.meituan-catpaw/auth.json). 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다 — 더 이상 이 컴퓨터의 클라이언트에 의존하지 않습니다.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Cline 클라이언트의 로그인 상태 파일 providers.json을 선택하세요 (Windows: C:\\Users\\<사용자 이름>\\.cline\\data\\settings\\providers.json, macOS / Linux: ~/.cline/data/settings/providers.json). 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다 — 더 이상 이 컴퓨터의 클라이언트에 의존하지 않습니다. 이 항목은 {label}에 등록됩니다.", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "KukuAI 클라이언트의 Cookies 파일을 선택하세요 (%APPDATA%\\baidugenflowpro\\Network\\Cookies): **바이너리** SQLite 데이터베이스입니다 (확장자 없음, JSON 아님). 가져오기는 선택한 파일의 복사본을 읽어 실행 중인 클라이언트와 점유를 다투지 않으므로 **클라이언트를 먼저 종료할 필요가 없습니다**. 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다.", "选择凭证文件导入": "자격 증명 파일에서 가져오기", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "공식 클라이언트의 로그인 자격 증명 파일(workbuddy-desktop.info / workbuddy-desktop-ai.info) 또는 wb2api에서 내보낸 계정 JSON(중첩/평면 형식 모두 가능)을 선택하세요.", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "小浣熊 클라이언트의 로그인 상태 파일 auth.json을 선택하세요 (Windows: C:\\Users\\<사용자 이름>\\.box-agent\\config\\auth.json, macOS / Linux: ~/.box-agent/config/auth.json). 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다 — 더 이상 이 컴퓨터의 클라이언트에 의존하지 않습니다.", "选择提供商": "제공자 선택", "选择的文件不是合法 JSON": "선택한 파일이 유효한 JSON이 아닙니다", "选择要添加账号的提供商": "계정을 추가할 제공자 선택", "重新扫描": "다시 스캔", "鉴权": "인증", "阿里云 Token Plan 套餐(国际站)": "Alibaba Cloud Token Plan (국제 사이트)", "阿里云百炼 Coding 套餐(国内站)": "Alibaba Cloud Model Studio Coding 플랜 (중국 사이트)", "阿里云百炼 Coding 套餐(国际站)": "Alibaba Cloud Model Studio Coding 플랜 (국제 사이트)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "Alibaba Cloud Model Studio 모델 서비스 (국제 사이트, OpenAI 호환 모드)", "需要图形验证码:登录窗口已弹出,请填写后继续": "그래픽 캡차가 필요합니다: 로그인 창이 열렸으니 입력한 후 계속하세요", "预置 API": "프리셋 API", "领取 CodeArts 每日福利": "CodeArts 일일 혜택 수령", "领取失败:{message}": "수령 실패: {message}", "领取并让官方确认": "수령하고 공식 확인 받기", "风控验证配置不完整,请稍后重试": "리스크 관리 인증 구성이 불완전합니다. 잠시 후 다시 시도하세요", "验证码": "인증 코드", "验证码已发送。收到后填入下方并点「登录并添加」": "인증 코드를 전송했습니다. 받은 후 아래에 입력하고 「로그인 후 추가」를 클릭하세요", "验证码已发送,请查看手机短信": "인증 코드를 전송했습니다. 휴대폰 SMS를 확인하세요", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "인증 코드를 전송했습니다. 휴대폰 SMS를 확인하세요. 아래에 입력하고 「로그인 후 추가」를 클릭하면 로그인이 완료됩니다", "验证码已发送,请查看短信": "인증 코드를 전송했습니다. 문자 메시지를 확인하세요", "验证码校验失败,请重试": "인증 코드 확인에 실패했습니다. 다시 시도하세요", "验证码校验超时,请重试": "인증 코드 확인 시간이 초과되었습니다. 다시 시도하세요", "验证码组件不可用,请重试": "캡차 컴포넌트를 사용할 수 없습니다. 다시 시도하세요", "验证码组件初始化超时,请重试": "캡차 컴포넌트 초기화 시간이 초과되었습니다. 다시 시도하세요", "验证码组件加载失败,请检查网络后重试": "캡차 컴포넌트 로드에 실패했습니다. 네트워크를 확인한 후 다시 시도하세요", "验证码组件加载异常,请重试": "캡차 컴포넌트 로드 중 오류가 발생했습니다. 다시 시도하세요", "验证码组件加载超时,请检查网络后重试": "캡차 컴포넌트 로드 시간이 초과되었습니다. 네트워크를 확인한 후 다시 시도하세요", "验证码组件未加载,请重启应用后重试": "캡차 컴포넌트가 로드되지 않았습니다. 앱을 다시 시작한 후 다시 시도하세요", "(免费额度池,模型名带 cline-free/ 前缀)。": " (무료 할당량 풀, 모델 이름에 cline-free/ 접두사 포함).", "(其中 {n} 把恢复为不限制)": " (이 중 {n}개는 제한 없음으로 복원)", "(必填)": " (필수)", "(有效期 {window})": "(유효 기간 {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": " (구독 풀, 모델 이름에 cline-pass/ 접두사 포함, 계정에 해당 구독이 있어야 합니다).", ",下一次最快 {minutes} 分钟后": ", 다음 시도는 최소 {minutes}분 후", ",并从 {n} 把 Key 的可用提供商里移除": ", Key {n}개의 사용 가능한 제공자 목록에서 이 제공자를 제거했습니다" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · 모델 {head}{rest}", " 等 {n} 个": " 등 {n}개", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "1//로 시작하는 Google refresh token (refresh_token=… 줄 전체를 붙여넣어도 됨)", "11 位大陆手机号": "11자리 중국 본토 휴대폰 번호", "1~64 个字符,账号列表里按它分组显示": "1~64자, 계정 목록에서 이 값을 기준으로 그룹화되어 표시됩니다", "6 位数字": "6자리 숫자", "

  • 没有可自动领的活动
  • ": "
  • 자동으로 수령할 수 있는 이벤트가 없습니다
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    수령하는 것은 플랜 증정 포인트이며, 혜택 모델의 token 풀은 늘지 않습니다;", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "Anthropic 호환 엔드포인트는 https://api.deepseek.com/anthropic입니다 (프로토콜을 anthropic으로 바꿀 때 입력합니다)", "Anthropic 协议填根地址,不要带 /v1": "Anthropic 프로토콜은 루트 주소를 입력하고 /v1은 붙이지 마세요", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw 중국판", "AutoClaw 国际版": "AutoClaw 국제판", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS는 필수입니다; **전체 Cookie**를 붙여넣으세요 (Cookie 편집기에서 원클릭 내보내기 가능) — 이 중 **PTOKEN은 반드시 남겨 두세요**. 게이트웨이가 이것을 사용해 Baidu에서 KukuAI 비즈니스 세션 토큰을 교환 발급받으며, 없으면 모델 갱신 시 「미로그인」 오류가 발생합니다. 전체 Cookie 헤더, Cookie 편집기에서 내보낸 JSON 배열, 또는 {BDUSS, STOKEN} 객체를 지원합니다. KukuAI에는 갱신 메커니즘이 없으므로 로그인 상태가 만료되면 다시 붙여넣으면 됩니다.", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=… (또는 Cookie 편집기에서 내보낸 JSON)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "CatPaw의 X-Passport-Token (로그인 상태 Cookie)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Cline Pass의 API Key는 app.cline.bot에서 발급받습니다(구독제). 엔드포인트는 OpenAI 호환이며, 모델 목록은 Cline 콘솔을 기준으로 하고, 모델 이름은 모델 관리에서 접두사 없는 이름 그대로 추가합니다(예: glm-5.2 / kimi-k2.7-code / deepseek-v4-pro). 업스트림이 클라이언트 형태를 검증하므로 필요한 클라이언트 요청 헤더는 이 카드에 미리 설정되어 있습니다", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT (3단 점 구분)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT(점 3개 구분. Bearer 전체 줄 또는 data.bin 내용을 붙여넣어도 됨)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT(점 3개로 구분된 형식. chatglm_token=… 줄을 그대로 붙여도 됩니다)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode 국제판", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM 관리형 엔드포인트, Key는 integrate.api.nvidia.com에서 신청합니다", "OfficeAce 果办": "OfficeAce", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken은 Accio의 로그인 자격 증명입니다 (길고 불투명한 token 문자열이며 JWT가 아닙니다); refreshToken은 선택이며, 입력하면 만료 시 자동 갱신됩니다. {label} 계정의 자격 증명을 입력하세요 — {siteNote} (가장 쉽게 얻는 방법: 위의 「웹 로그인」을 바로 사용하세요. token을 직접 찾을 필요가 없습니다.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken은 Trae의 Cloud-IDE-JWT이며(3단 점 구분), refreshToken은 만료 시 자동 갱신에 사용됩니다 (이 제공자는 refreshToken이 교환할 때마다 바뀝니다: 한 번 교환하면 이전 것은 무효가 되므로 두 프로그램에서 같은 계정을 동시에 갱신하지 마세요).
    수동으로 붙여넣을 때는 machineId / deviceId도 함께 입력하세요: 업스트림은 이를 로그인 시 업로드한 기기 공개 키와 묶어 기기를 판별하므로, 갑자기 새로운 값을 넣으면 2xxxx 계열 기기 바인딩 거부가 발생합니다.
    이 세 가지가 없을 때의 올바른 방법은 위의 「웹 로그인」이며, 컨테이너 / 원격 배포 환경에서는 안내에 따라 주소 표시줄의 콜백 주소를 붙여넣으면 됩니다.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "monkeycode_ai_session의 값 (전체 Cookie를 붙여넣어도 됨)", "ms- 开头的 API 令牌": "ms- 로 시작하는 API 토큰", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken은 선택이며, 입력하면 만료 시 자동 갱신됩니다; 둘 다 小浣熊 클라이언트 로그인 상태 파일에서 얻을 수 있습니다.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken은 선택이며, 입력하면 자동 갱신됩니다; 둘 다 클라이언트 로그인 상태 파일에서 얻을 수 있습니다. 같은 Cline 계정은 두 풀 모두에서 사용할 수 있으며, 여기서는 {label}로 분류됩니다.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token은 enc: 접두사를 지원합니다 (Windows에서는 자동 복호화). refreshToken을 입력하지 않으면 자동 갱신할 수 없습니다.", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "token은 로그인 상태 Cookie입니다; CatPaw에는 갱신 메커니즘이 없어 만료 후 클라이언트에서 다시 로그인해야 합니다.", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "user_로 시작하는 API Key (Authorization: Bearer … 줄 전체를 붙여넣어도 됨)", "{label} 网页登录的打开方式": "{label} 웹 로그인을 여는 방식", "{label} 账号地区": "{label} 계정 지역", "{label} 账号的添加方式": "{label} 계정 추가 방식", "{name} 不是合法 JSON:{reason}": "{name}은(는) 올바른 JSON이 아닙니다: {reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name}에는 JSON 객체를 붙여넣어야 합니다 (예: {sample})", "{n} 个账号": "계정 {n}개", "{n} 个账号,点击添加": "계정 {n}개, 클릭하여 추가", "{seconds}s 后重发": "{seconds}초 후 재발송", "✅ {label}账号已添加": "✅ {label} 계정을 추가했습니다", "✅ {label}账号已添加{name}": "✅ {label} 계정을 추가했습니다{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ cc-switch에서 제공자 {n}개를 가져왔습니다", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ 커스텀 제공자 「{name}」을(를) 만들고 계정을 추가했습니다", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ 커스텀 제공자 「{name}」을(를) 삭제했습니다{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ 기존 계정{name}을(를) 업데이트했습니다(동일한 API Key는 하나만 유지되며 다시 추가하면 병합됩니다)", "✅ 登录成功,{edition}账号已加入列表": "✅ 로그인 성공, {edition} 계정을 목록에 추가했습니다", "✅ 领取成功:{planId}{period}": "✅ 수령 성공: {planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " 같은 제공자에 key를 여러 개 둘 수 있으며, 우선순위에 따라 로테이션됩니다.", "「{name}」的账号添加功能还在开发中,敬请期待。": "「{name}」의 계정 추가 기능은 아직 개발 중입니다. 기대해 주세요.", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "하나의 Key로 여러 제공자의 모델을 사용할 수 있으며, 모델 이름은 「벤더/모델」 전체 이름을 씁니다 (예: deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "업스트림이 인증을 요구하지 않으면 비워 두고 아래 항목을 체크하세요 (비워 두고 체크하지 않으면 자격 증명 미설정으로 간주됩니다)", "上游信息": "업스트림 정보", "不可领({status})": "수령 불가 ({status})", "不支持导入": "가져오기 미지원", "不是有效的凭证文件:内容要是一个 JSON 对象": "유효한 자격 증명 파일이 아닙니다. 내용은 JSON 객체여야 합니다", "不是有效的凭证文件:需要包含 accessToken 与 uid": "유효한 자격 증명 파일이 아닙니다. accessToken과 uid가 필요합니다", "不是自定义提供商": "커스텀 제공자가 아닙니다", "不需要 Key:转发与拉取模型都不发送鉴权头": "Key 불필요: 포워딩과 모델 조회 모두 인증 헤더를 보내지 않습니다", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "로그인이 필요 없습니다. 아래 버튼을 누르면 게이트웨이가 智谱清言에서 게스트 자격 증명을 직접 발급받아 계정 목록에 추가합니다(먼저 메모 이름을 입력해도 됩니다). 게스트 자격 증명은 바로 대화에 쓸 수 있고, 무료 할당량은 업스트림이 기기 단위로 발급합니다.

    주의: 게스트 계정에는 포인트 체계가 없습니다. 회원 포인트, 매일 로그인 포인트, 활동 수령 관련 인터페이스는 모두 로그인이 필요하므로 이러한 기능은 게스트에서 건너뜁니다(계정 페이지의 포인트와 签到 센터에 수치가 표시되지 않습니다). 포인트가 필요하면 \"자격 증명 입력\"으로 로그인된 계정 토큰을 붙여넣거나 \"데스크톱 로그인 상태 가져오기\"를 사용하세요.", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "두 판의 계정을 동시에 저장할 수 있으며 각각 별도의 모델 목록을 가집니다 (중국판과 국제판은 서로 다른 두 제공자로, 각각 활성화하고 매핑할 수 있습니다).", "中国版": "중국판", "今天没有需要领的活动(都已到账)": "오늘 수령할 이벤트가 없습니다 (모두 적립됨)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "오늘(베이징 시간 {day}) {attempts}회 시도했고, {left}회 더 시도할 수 있습니다{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "다른 컴퓨터(또는 OfficeAce 데스크톱 앱의 models.json)에서 다음 세 항목을 가져와 붙여넣으세요: 모델 게이트웨이 기본 주소(baseUrl, https://modelgw-…/v2 형태)와 modelAppKey / modelAppSecret. 이 세 항목만 있으면 전달할 수 있습니다(게이트웨이 자격 증명은 만료되지 않음). 제어 영역 임시 자격 증명(accessKeyId 등)은 선택이며, 비워 두면 잔액 조회와 자동 갱신을 쓸 수 없지만 전달에는 영향이 없습니다.", "从本机导入桌面端登录态": "이 컴퓨터에서 데스크톱 로그인 상태 가져오기", "任务镜像 id": "작업 이미지 id", "余额查询": "잔액 조회", "使用 Google 账号登录": "Google 계정으로 로그인", "使用 Zai 账号登录": "Zai 계정으로 로그인", "使用个人访问令牌(PAT)": "개인 액세스 토큰(PAT) 사용", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "무료 모델은 Key를 입력하지 않아도 됩니다 (기본적으로 「이 업스트림은 인증이 필요하지 않음」이 체크되어 있고, 게이트웨이가 자동으로 익명 자격 증명을 사용합니다); 유료 모델은 Zen의 API Key를 입력하세요. 무료 등급 업스트림은 공식 클라이언트 형태만 허용하므로 「OpenCode 공식 클라이언트로 위장」이 기본으로 켜져 있습니다", "内嵌窗口": "내장 창", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "내장 창으로 엽니다; 창을 닫으면 대기가 취소됩니다 (Google 계정이 거부되면 시스템 브라우저를 사용하세요)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "내장 창으로 엽니다; 완료하면 자동으로 목록에 추가되고, 창을 닫으면 대기가 취소됩니다", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "내장 창으로 열립니다. 스캔이 끝나면 자동으로 목록에 추가되며, 창을 닫으면 대기가 취소됩니다", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "내장 창은 새 환경을 사용하므로 여러 계정이 서로 영향을 주지 않습니다; 창을 닫으면 대기가 취소됩니다", "内嵌窗口(推荐)": "내장 창(권장)", "准备验证…": "인증 준비 중…", "凭据 JSON": "자격 증명 JSON", "凭证文件在哪?": "자격 증명 파일 위치는?", "创建并添加账号": "생성하고 계정 추가", "创建这个提供商,并同时建立它的第一个账号。": "이 제공자를 만들고 동시에 첫 계정을 생성합니다.", "删除功能不可用(脚本未就绪)": "삭제 기능을 사용할 수 없습니다 (스크립트가 준비되지 않음)", "删除失败:{reason}": "삭제 실패: {reason}", "删除此提供商": "이 제공자 삭제", "及 {n} 个账号": " 및 계정 {n}개", "发送中…": "전송 중…", "发送失败:{message}": "전송 실패: {message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "전송 미확인: 로그인 창이 열렸습니다. 열린 창에서 직접 로그인을 완료하세요", "取消失败:{message}": "취소 실패: {message}", "取消等待": "대기 취소", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "「내장 창」에서만 제3자 로그인 항목을 복원할 수 있습니다: 시스템 브라우저에서는 로그인 페이지를 수정할 수 없습니다", "可选": "선택", "可选(cloudaicompanionProject):留空由网关自动发现": "선택 (cloudaicompanionProject): 비워 두면 게이트웨이가 자동으로 찾습니다", "可选,展示用": "선택, 표시용", "可选,没有则无法自动续期": "선택, 없으면 자동 갱신 불가", "可选,留空使用凭据里的 user_name": "선택, 비워 두면 자격 증명의 user_name 사용", "可选,留空使用账号姓名、邮箱或令牌指纹": "선택, 비워 두면 계정 이름, 이메일 또는 토큰 지문 사용", "可选,留空使用账号昵称或邮箱": "선택, 비워 두면 계정 닉네임 또는 이메일 사용", "可选,留空则用 key 尾号": "선택, 비워 두면 key 끝자리 사용", "可选,留空则用 userId": "선택, 비워 두면 userId 사용", "可选,留空则用上游账号昵称": "선택 사항. 비워 두면 업스트림 계정 닉네임을 사용합니다", "可选,留空则用上游返回的账号名或账号 id": "선택, 비워 두면 업스트림이 반환한 계정 이름 또는 계정 id 사용", "可选,留空则用凭证里的账号名": "선택, 비워 두면 자격 증명의 계정 이름 사용", "可选,留空则用文件里的昵称": "선택 사항, 비워 두면 파일의 닉네임 사용", "可选,留空则用登录名或 uid": "선택, 비워 두면 로그인 이름 또는 uid 사용", "可选,留空则用脱敏手机号": "선택, 비워 두면 마스킹된 휴대폰 번호 사용", "可选,留空则用脱敏手机号或 userId": "선택, 비워 두면 마스킹된 휴대폰 번호 또는 userId 사용", "可选,留空则用账号 uk": "선택, 비워 두면 계정 uk 사용", "可选,留空则用账号昵称": "선택 사항. 비워 두면 계정 닉네임을 사용합니다", "可选,留空则用账号昵称或 userId": "선택 사항. 비워 두면 계정 닉네임 또는 userId 사용", "可选,留空则用邮箱或令牌尾号": "선택, 비워 두면 이메일 또는 토큰 끝자리 사용", "可选,留空用「OfficeAce 果办」": "선택, 비워 두면 「OfficeAce」 사용", "可选,留空自动生成": "선택, 비워 두면 자동 생성", "可选,留空自动用昵称": "선택, 비워 두면 닉네임 자동 사용", "可选,给这个访客账号起个备注名": "선택 사항. 이 게스트 계정의 메모 이름", "可选,续期时带上": "선택, 갱신 시 함께 전송", "可选,讯飞侧 userid": "선택, iFlytek 측 userid", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "선택; 대화 시작에 필요합니다. 비워 두면 게이트웨이가 이 계정의 기존 작업에서 자동으로 찾습니다. 찾지 못하면 나중에 직접 입력하면 됩니다.", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "선택; 계정 이메일로, 표시와 신원 식별에 사용됩니다 (새 토큰으로 바꿔도 같은 계정으로 인식됩니다)", "可选;UUID 形态,与凭据同生共死": "선택; UUID 형식이며 자격 증명과 함께 생성되고 함께 사라집니다", "可选;填了才能到期自动续期": "선택; 입력해야 만료 시 자동 갱신할 수 있습니다", "可选;用于去重与展示名(留空时网关会问一次上游)": "선택; 중복 제거와 표시 이름에 사용됩니다 (비워 두면 게이트웨이가 업스트림에 한 번 물어봅니다)", "可选;用于生成账号 id 与展示名": "선택; 계정 id와 표시 이름 생성에 사용됩니다", "可选;纯数字串(上游只收 8–24 位数字)": "선택; 숫자만 입력 (업스트림은 8–24자리 숫자만 허용)", "可领取": "수령 가능", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "한 제공사에 API Key 있는 계정과 인증 불필요 계정을 섞어 둘 수 있으며 각각의 규칙으로 라우팅됩니다. 인증 불필요 계정도 여러 개 둘 수 있고 각각 다른 아웃바운드 프록시를 설정할 수 있습니다", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "같은 주소에서 anthropic 프로토콜로 바꾸면 해당 Claude 호환 엔드포인트를 사용합니다. 포워딩에는 OpenCode Go의 API Key가 반드시 필요합니다 (구독제; 모델 목록 조회에는 Key가 필요 없지만, 요청을 보내면 업스트림이 401 「Missing API key」를 반환합니다)", "响应为空": "응답이 비어 있습니다", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "SenseNova 의 OpenAI 호환 엔드포인트. 잔액 조회는 콘솔 계정 / 비밀번호를 사용합니다 (아래 \"잔액 조회\" 단락 참조)", "国内版": "중국판", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "중국판과 **국제판은 서로 독립된 두 세트의 계정과 플랜**입니다. 자격 증명과 수령한 플랜은 서로 호환되지 않습니다.", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "중국판 로그인 페이지에는 Google / GitHub 항목이 없습니다 (WeChat / 휴대폰 번호 / 이메일로 로그인합니다)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "중국판의 로그인 사이트는 www.accio-ai.com이며, 국제판과 같은 사이트가 아닙니다.", "国内版(WorkBuddy)": "중국판 (WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "중국 사이트는 https://api.siliconflow.cn/v1입니다", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "중국 사이트 (minimaxi.com); OpenAI 호환 주소는 https://api.minimaxi.com/v1입니다", "国际版": "국제판", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "국제판 z.ai의 Coding 플랜; OpenAI 호환 주소는 https://api.z.ai/api/coding/paas/v4입니다", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "국제판과 중국판은 **서로 독립된 두 세트의 계정**입니다 (같은 계정 체계의 두 사이트). 자격 증명은 호환되지 않습니다.", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "국제판과 중국판은 계정 체계가 독립적입니다. 국제판의 자격 증명을 입력하세요. refreshToken을 입력하지 않으면 자동 갱신할 수 없습니다.", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "국제판 로그인 페이지는 기본적으로 이메일 로그인만 표시하며, 체크하면 Google / GitHub / X 항목이 복원됩니다", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "국제판의 추론 사이트는 api.z.ai이며 중국판과 다른 사이트입니다; 플랜도 각각 독립적입니다.", "国际版(WorkBuddy AI)": "국제판 (WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "국제 사이트 Coding 플랜; OpenAI 호환 주소는 https://api.minimax.io/v1입니다", "在 cc-switch 里找到": "cc-switch에서 찾은", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "내장 창에서 공식 로그인을 완료하면 성공 시 자동으로 계정 목록에 추가됩니다.", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "{label}의 Qoder 계정 설정 → Integrations에서 PAT를 생성하세요 (Google / GitHub 토큰을 입력하지 마세요). 두 지역의 계정과 자격 증명은 호환되지 않습니다.", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "열린 공식 인증 페이지에서 위챗 QR 코드를 스캔하여 로그인하세요(페이지에 QR 코드가 바로 표시됩니다). 스캔에 성공하면 계정이 자동으로 목록에 추가됩니다.", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "열린 창에서 Baidu 계정으로 KukuAI 메인 사이트에 로그인하세요 (SMS 인증 코드 / QR 스캔 모두 가능). 로그인에 성공하면 자동으로 계정 목록에 추가됩니다. 게이트웨이는 Baidu에서 KukuAI 비즈니스 세션 토큰을 교환 발급받습니다 (이 컴퓨터에 KukuAI 클라이언트가 설치되어 있어야 합니다).", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "열린 창에서 Google 계정으로 로그인하세요(Antigravity의 인가 페이지). 인가가 완료되면 자동으로 계정 목록에 추가됩니다.", "在浏览器中打开登录页": "브라우저에서 로그인 페이지 열기", "地区": "지역", "填写凭证": "자격 증명 입력", "填写凭证添加": "자격 증명 입력 후 추가", "备注名": "라벨명", "套餐": "플랜", "如:智谱 GLM": "예: Zhipu GLM", "完成登录后自动加入账号列表,昵称取自上游。": "로그인을 완료하면 자동으로 계정 목록에 추가되며, 닉네임은 업스트림에서 가져옵니다.", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "공식 클라이언트 자격 증명 디렉터리: Windows는 C:\\Users\\<사용자명>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth, macOS는 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "공식 적립 확인 완료", "导入": "가져오기", "导入中…": "가져오는 중…", "导入凭证文件": "자격 증명 파일 가져오기", "导入失败": "가져오기 실패", "导入失败:{reason}": "가져오기 실패: {reason}", "导入所选": "선택 항목 가져오기", "导入所选({n})": "선택 항목 가져오기({n})", "导入桌面端登录态": "데스크톱 로그인 상태 가져오기", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "내장 창이 열립니다; 인가가 완료되면 자동으로 계정 목록에 추가됩니다. 창을 닫으면 대기가 취소됩니다. 인가 페이지 마지막에 zcode:// 링크를 열 수 없다는 안내가 나올 수 있는데, 정상입니다 — 결과는 이미 서버 측에 기록되었습니다", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "내장 창이 열립니다; 인가가 완료되면 자동으로 계정 목록에 추가됩니다. 원격 패널에서는 콜백 주소를 붙여넣을 수 있습니다. 창을 닫으면 대기가 취소됩니다. 링크는 5분간 유효하며, 시간이 초과되거나 클릭하지 않으면 무효가 됩니다 (다시 시작할 수 있습니다)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "내장 창이 열립니다; 로그인이 완료되면 자동으로 계정 목록에 추가됩니다. 창을 닫으면 대기가 취소됩니다", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "시스템 기본 브라우저로 인가 페이지를 엽니다 (브라우저에 로그인된 Trae 계정을 재사용합니다); 같은 컴퓨터에서는 완료 시 자동으로 추가되며, Docker / 원격 패널에서는 안내에 따라 주소 표시줄의 콜백 주소를 붙여넣으세요.", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "시스템 기본 브라우저로 인가 페이지를 엽니다 (브라우저에 로그인된 ZCode 계정을 재사용합니다); 인가가 완료되면 자동으로 계정 목록에 추가됩니다. 페이지 마지막에 zcode:// 링크를 열 수 없다는 안내가 나올 수 있는데 정상입니다", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "시스템 기본 브라우저로 인가 페이지를 엽니다 (브라우저에 로그인된 Huawei Cloud 계정을 재사용합니다); 인가 코드는 게이트웨이가 클라우드를 폴링해 가져오므로 브라우저가 어느 컴퓨터에서 실행되는지는 상관없습니다. 완료하면 자동으로 계정 목록에 추가됩니다", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "시스템 기본 브라우저로 인가 페이지를 엽니다 (브라우저에 로그인된 Huawei Cloud 계정을 재사용합니다); 브라우저와 게이트웨이가 같은 컴퓨터에 있지 않다면 위 설명대로 최종 콜백 주소를 패널에 다시 붙여넣으세요", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "시스템 기본 브라우저로 로그인 페이지를 엽니다 (브라우저에 로그인된 Accio 계정을 재사용합니다); 로그인을 완료하면 자동으로 계정 목록에 추가되며, 팝업을 닫으면 대기가 취소됩니다", "小米 MiMo Token Plan 套餐(新加坡站)": "小米 MiMo Token Plan 플랜 (싱가포르 사이트)", "已到账": "적립 완료", "已取消登录等待": "로그인 대기를 취소했습니다", "已取消领取": "수령을 취소했습니다", "已取消验证码": "인증 코드를 취소했습니다", "已填写手机号,正在发送验证码…": "휴대폰 번호 입력 완료, 인증 코드 전송 중…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "인증 필요 없음으로 선언됨: 계정이 정상적으로 라우팅되며, 외부로 나갈 때 인증 헤더를 전혀 보내지 않습니다", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "가져오기 성공 {ok}개, 실패 {fail}개 (실패 항목은 목록에 표시해 두었습니다)", "已建过 · {n} 个账号,点击继续添加": "이미 생성됨 · 계정 {n}개, 클릭하여 추가", "已建过,点击继续添加账号": "이미 생성됨, 클릭하여 계정 추가", "已打开官方登录页,请在窗口中完成登录…": "공식 로그인 페이지를 열었습니다. 창에서 로그인을 완료하세요…", "已点发送,等待短信…": "전송을 눌렀습니다. SMS 대기 중…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "시스템 기본 브라우저로 로그인 페이지를 열었습니다. 브라우저에서 로그인을 완료하세요…", "已领取,等官方确认": "수령 완료, 공식 확인 대기 중", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "현재 앱 버전에서는 AutoClaw 웹 로그인을 지원하지 않습니다. 앱을 업데이트하세요", "当前没有可领取的套餐(活动尚未开始)": "현재 수령 가능한 플랜이 없습니다 (이벤트가 아직 시작되지 않았습니다)", "当前环境不支持领取(桥接方法缺失)": "현재 환경에서는 수령을 지원하지 않습니다 (브리지 메서드 없음)", "必填,CatPaw 账号标识": "필수, CatPaw 계정 식별자", "恢复 Google / GitHub 入口": "Google / GitHub 항목 복원", "手机号": "휴대폰 번호", "手机验证码登录": "SMS 인증 코드 로그인", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "Trae SOLO의 공식 인가 페이지(trae.cn)를 열고 Trae 계정으로 로그인하세요: 인가가 완료되면 공식 페이지가 이 컴퓨터의 임시 포트로 되돌아옵니다; 같은 컴퓨터 배포에서는 자동으로 수신하며, Docker / 원격 패널에서는 안내에 따라 주소 표시줄의 콜백 주소를 복사하세요.", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "Accio {label}의 공식 로그인 페이지({site})를 열고 Accio 계정으로 로그인하세요: 로그인에 성공하면 공식 페이지가 이 컴퓨터로 되돌아옵니다; 같은 컴퓨터에서는 자동으로 완료되며, Docker / 원격 패널에서는 안내에 따라 콜백 주소를 붙여넣으면 됩니다 (인가 코드는 이 컴퓨터에서만 게이트웨이에 전달되며, 화면에 평문 token이 표시되지 않습니다).", "打开 Accio {label}登录页": "Accio {label} 로그인 페이지 열기", "打开 Antigravity 网页登录": "Antigravity 웹 로그인 열기", "打开 CatPaw 网页登录": "CatPaw 웹 로그인 열기", "打开 Cline 授权页": "Cline 인가 페이지 열기", "打开 CodeArts 授权页": "CodeArts 인가 페이지 열기", "打开 Qoder 网页登录": "Qoder 웹 로그인 열기", "打开 Trae 授权页": "Trae 인가 페이지 열기", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "ZCode {label}의 공식 인가 페이지를 열고 계정으로 로그인하세요. 인가 결과는 ZCode 서버에 기록되며, 게이트웨이가 백그라운드에서 자격 증명을 자동으로 가져와 계정 목록에 추가합니다.", "打开 ZCode {label}授权页": "ZCode {label} 인가 페이지 열기", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "Huawei Cloud CodeArts의 공식 인가 페이지를 열어 로그인하세요: 로그인이 완료되면 공식 페이지가 브라우저를 게이트웨이 자체의 /oauth/callback으로 되돌립니다. 게이트웨이는 일회성 인가 코드를 임시 자격 증명으로 교환하고 계정 목록에 추가합니다.
    게이트웨이가 다른 컴퓨터에서 실행 중이면 웹 UI에서 주소 표시줄의 최종 콜백 주소를 패널에 그대로 붙여넣으라는 안내가 표시됩니다.", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "Huawei Cloud 인가 페이지를 열고 로그인하세요: 완료되면 게이트웨이가 클라우드를 폴링해 인가 코드를 가져와 계정 목록에 추가합니다 (OfficeAce 데스크톱 앱이 필요 없고, 콜백 URL을 수동으로 다시 붙여넣을 필요도 없습니다).", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "공식 인가 페이지를 열어 기기 코드 인가를 완료하세요. 로그인되는 계정은 {label} ({site}) 계정입니다.", "打开授权页": "인가 페이지 열기", "打开授权页完成确认,账号自动加入 {label}{note}": "인가 페이지를 열어 확인을 완료하면 계정이 {label}에 자동으로 추가됩니다{note}", "打开方式": "여는 방식", "打开网页登录": "웹 로그인 열기", "探测失败:{message}": "탐지 실패: {message}", "接入一个兼容上游": "호환 업스트림 연결", "提交中…": "제출 중…", "搜索提供商": "제공자 검색", "搜索提供商…": "제공자 검색…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "공식 플러그인 / CLIProxyAPI가 디스크에 기록한 자격 증명 JSON을 통째로 붙여넣으세요 (형식: {\"codearts_provider_credential\":{…}}, 평탄화된 형태도 가능).
    필수: access_key_id, secret_access_key, security_token.자동 갱신을 원하면 refresh_token과 oauth_context도 함께 붙여넣어야 합니다 — 임시 자격 증명은 약 1시간 후 만료되며, 이 부분이 없으면 갱신할 수 없어 다시 로그인해야 합니다.", "文件是{edition}凭证,已按该版本导入": "파일은 {edition} 자격 증명이며 해당 버전으로 가져왔습니다", "新建自定义提供商": "커스텀 제공자 새로 만들기", "方案:{label}": "방식: {label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "평문 JWT 또는 auth.json의 enc: 암호화 값 (자동 복호화)", "明文 JWT(国际版账号的 access token)": "평문 JWT (국제판 계정의 access token)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "Zhipu bigmodel.cn의 Coding 플랜, Key는 open.bigmodel.cn/usercenter/apikeys에서 발급합니다", "未知错误": "알 수 없는 오류", "未能获取授权地址,请重试": "인가 주소를 가져오지 못했습니다. 다시 시도하세요", "未能读取 cc-switch 数据": "cc-switch 데이터를 읽지 못했습니다", "未领取成功": "수령하지 못했습니다", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "로컬 Ollama, OpenCode Zen 무료 등급 같은 업스트림에는 체크해야 하며, 그렇지 않으면 계정을 사용할 수 없습니다", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "이 제공자에는 **서로 대체할 수 없는** 자격 증명이 두 개 있습니다. 사용할 기능에 따라 입력하고 최소 하나는 입력하세요: 코딩 플랜 API Key는 추론 포워딩({site} 호출)과 윈도우 할당량 조회(N시간마다 / 주간 잔여 비율)에 사용하고, jwt는 플랜 수령과 잔액 조회에 사용합니다(zcode.z.ai의 billing 게이트웨이 호출, 공식 명칭 Coding Plan JWT, 3단 점 구분 문자열). 잔액은 둘 다 조회할 수 있지만 읽어 오는 내용이 다릅니다: jwt는 잔액 버킷과 플랜 만료를, API Key는 윈도우 할당량을 읽습니다. 수령은 jwt만, 포워딩은 API Key만 인정합니다. {label} 계정의 자격 증명을 입력하세요 — {plan} (가장 쉽게 얻는 방법: 위의 「웹 로그인」을 바로 사용하세요 — 이 API Key를 대신 교환해 두 자격 증명을 함께 받아 줍니다.)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "이 컴퓨터의 Ollama OpenAI 호환 엔드포인트, API Key 불필요 (기본적으로 「이 업스트림은 인증이 필요하지 않음」이 체크되어 있고, 인증 헤더를 전혀 보내지 않습니다)", "本次未确认到账": "이번에는 적립이 확인되지 않았습니다", "条可导入": "건을 가져올 수 있습니다", "条配置,其中": "건의 설정 중", "桌面运行时不可用(Tauri 未初始化)": "데스크톱 런타임을 사용할 수 없습니다 (Tauri 미초기화)", "模型网关基址": "모델 게이트웨이 기본 주소", "正在打开百度登录页…": "Baidu 로그인 페이지를 여는 중…", "正在扫描本机 cc-switch…": "이 컴퓨터의 cc-switch를 스캔하는 중…", "正在换发访客凭证…": "게스트 자격 증명을 발급하는 중…", "正在添加…": "추가하는 중…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "{name} 로그인 완료를 기다리는 중입니다; 완료하거나 취소한 후에 새로운 로그인을 시작할 수 있습니다", "每周": "매주", "每日": "매일", "每月": "매월", "没有则无法自动续期": "없으면 자동 갱신할 수 없습니다", "没有匹配「{keyword}」的提供商": "「{keyword}」와 일치하는 제공자가 없습니다", "添加 {name} 账号": "{name} 계정 추가", "添加中…": "추가 중…", "添加到 ": "추가 대상: ", "添加失败:{reason}": "추가 실패: {reason}", "添加小浣熊账号": "小浣熊 계정 추가", "添加方式": "추가 방식", "添加访客账号": "게스트 계정 추가", "添加账号": "계정 추가", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "Volcano Engine Coding 플랜; 범용 추론 엔드포인트는 https://ark.cn-beijing.volces.com/api/v3입니다", "点击添加账号": "클릭하여 계정 추가", "点开即预填,填 Key 接入": "열면 값이 미리 채워져 있으며, Key를 입력하면 연결됩니다", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "버튼을 누르면 먼저 슬라이더 인증을 한 번 통과하고(공식 리스크 관리), 이어서 로그인 페이지가 열리며 로그인이 완료되면 계정이 자동으로 추가됩니다.
    이것이 국제판의 공식 유일한 로그인 방식입니다; 이미 클라이언트에 로그인한 적이 있다면 「데스크톱 로그인 상태 가져오기」가 더 빠릅니다.", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "AutoClaw 계정에 연결된 휴대폰 번호로 로그인합니다: 「코드 받기」를 클릭하고 SMS를 받은 뒤 아래에 입력하여 로그인하세요. 인증 코드는 이 컴퓨터에서 공식 API로 직접 제출되며, 화면에 token이 표시되지 않습니다.", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "CatPaw 계정으로 로그인합니다 (Meituan passport), 성공하면 자동으로 계정 목록에 추가됩니다.", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "Loomy 계정에 연결된 휴대폰 번호로 로그인합니다: 「코드 받기」를 클릭한 뒤 입력하면 됩니다. 이 제공자에서 가장 간편한 방법입니다.", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "포워딩에 사용합니다; apiKey.secret 형태의 2단 점 구분 (입력하지 않으면 이 계정은 포워딩할 수 없습니다)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "플랜 수령과 잔액 조회에 사용합니다; 입력하지 않으면 이 계정은 수령과 잔액 조회를 할 수 없습니다", "用户 ID": "사용자 ID", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "연결된 휴대폰 번호로 로그인합니다: 「코드 받기」를 클릭한 뒤 입력하면 됩니다. 이것이 중국판의 공식 유일한 로그인 방식입니다.", "留空则用提供商名称": "비워 두면 제공자 이름 사용", "登录 / 添加 {name} 账号": "로그인 / {name} 계정 추가", "登录 session(一长串)": "로그인 session (긴 문자열)", "登录中…": "로그인 중…", "登录失败:{message}": "로그인 실패: {message}", "登录已结束": "로그인이 종료되었습니다", "登录并添加": "로그인 후 추가", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "로그인 상태 파일 경로: ~/.box-agent/config/auth.json (Windows: C:\\Users\\<사용자 이름>\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "커스텀 제공자 「{name}」을(를) 삭제할까요? 이 제공자 아래의 계정 {count}개도 함께 삭제되며, 삭제 후에는 복구할 수 없습니다.", "等待 Accio {label}登录完成…": "Accio {label} 로그인 대기 중…", "等待 CatPaw 登录完成…": "CatPaw 로그인 대기 중…", "等待 Cline 授权确认…": "Cline 인가 확인 대기 중…", "等待 CodeArts 登录完成…": "CodeArts 로그인 대기 중…", "等待 Google 授权完成…": "Google 인가 대기 중…", "等待 KukuAI 登录完成…": "KukuAI 로그인 대기 중…", "等待 OfficeAce 登录完成…": "OfficeAce 로그인 대기 중…", "等待 OrcaTerm 登录完成…": "OrcaTerm 로그인 대기 중…", "等待 Qoder 授权完成…": "Qoder 인가 대기 중…", "等待 Trae 授权完成…": "Trae 인가 대기 중…", "等待 ZCode {label}授权完成…": "ZCode {label} 인가 대기 중…", "等待小浣熊登录完成…": "小浣熊 로그인 대기 중…", "等待登录完成…": "로그인 완료 대기 중…", "等待网页登录…": "웹 로그인 대기 중…", "粘贴 API Key": "API Key 붙여넣기", "粘贴 API 令牌": "API 토큰 붙여넣기", "粘贴 Accio 的 accessToken": "Accio의 accessToken 붙여넣기", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Antigravity의 Google refresh token을 붙여넣으세요 (1//로 시작; refresh_token=이 포함된 줄 전체를 붙여넣어도 됨).
    웹 로그인 외의 수동 입구입니다(예: 로그인된 공식 IDE에서 내보내기). refresh token은 만료되지 않으며, access token 만료 시 게이트웨이가 자동으로 갱신합니다; 토큰을 잃어버리면 Google 인가를 다시 받아야 하므로 잘 보관하세요.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Command Code의 API Key를 붙여넣으세요 (user_로 시작; 공식 CLI의 ~/.commandcode/auth.json 또는 웹 studio에서 획득). 줄 전체 / 따옴표 포함 / Bearer 접두사 포함 그대로 붙여넣어도 됩니다. 게이트웨이가 알아서 순수한 key만 추출합니다. key는 만료되지 않고 갱신 인터페이스도 없으므로, 무효가 되면 다시 받으면 됩니다; 추가 시 게이트웨이가 가벼운 활성 확인을 한 번 수행하며, 실패해도 추가에는 영향을 주지 않습니다.", "粘贴 Cookie": "Cookie 붙여넣기", "粘贴 Google refresh token": "Google refresh token 붙여넣기", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "OrcaTerm의 OAuth accessToken(점 3개로 구분된 JWT. 데스크톱 클라이언트의 data.bin 또는 웹 버전 Cookie ot_session에서 확인)을 붙여넣으세요. Bearer / ot_session=이 포함된 줄을 그대로 붙여넣어도 되며, 게이트웨이가 토큰만 추출합니다. 추가 후에는 게이트웨이가 자동으로 갱신하므로(업스트림에 갱신 API가 있음) 2시간 만료를 직접 따라갈 필요가 없습니다.", "粘贴 Qoder 个人访问令牌(pt-…)": "Qoder 개인 액세스 토큰(pt-…) 붙여넣기", "粘贴 accessToken": "accessToken 붙여넣기", "粘贴 access_token(一长串 JWT)": "access_token 붙여넣기 (긴 JWT)", "粘贴 session cookie": "session cookie 붙여넣기", "粘贴 token / refreshToken": "token / refreshToken 붙여넣기", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "workos:…로 시작하는 토큰 붙여넣기 (접두사가 없어도 자동으로 붙습니다)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "智谱清言 액세스 토큰(점 3개로 구분된 JWT)을 붙여넣으세요. 발급 방법: 브라우저에서 chatglm.cn을 열고 로그인한 뒤 개발자 도구의 Application → Cookies에서 chatglm_token 값을 복사합니다(chatglm_token=…; 줄을 그대로 붙여도 됩니다). 붙여넣은 뒤 업스트림에 한 번 검증하며, 통과한 경우에만 계정을 저장합니다. 로그인된 계정은 포인트와 签到 기능을 쓸 수 있고, 이후 게이트웨이가 자동으로 갱신합니다(업스트림에 갱신 인터페이스가 있습니다).", "粘贴登录凭据": "로그인 자격 증명 붙여넣기", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "붙여넣는 것은 로그인 session입니다 (동시에 모델 게이트웨이의 token입니다). Loomy에는 갱신 인터페이스가 없으며 session 유효 기간은 약 14일이므로, 만료되면 다시 로그인하면 됩니다.", "粘贴网关凭据": "게이트웨이 자격 증명 붙여넣기", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "웹 로그인 상태 cookie monkeycode_ai_session의 값을 붙여넣으세요 (브라우저에서 전체 Cookie를 복사해 그대로 붙여넣어도 됩니다. 게이트웨이가 값을 알아서 추출합니다).
    {siteNote}
    MonkeyCode에는 갱신 인터페이스가 없습니다: session 유효 기간은 약 30일(하드 제한)이며, 만료되면 웹에 다시 로그인해 한 번 더 붙여넣으면 됩니다.", "粘贴访问令牌": "액세스 토큰 붙여넣기", "系统浏览器": "시스템 브라우저", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "시스템 브라우저는 기존 로그인 상태를 재사용할 수 있습니다 (국제판 권장); 내장 창이 더 깔끔합니다.", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "시스템 브라우저로 엽니다 (로그인된 Cline 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "시스템 브라우저로 엽니다(로그인된 Google 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "시스템 브라우저로 엽니다 (로그인된 Zai / Google 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "시스템 브라우저로 엽니다 (로그인된 Meituan 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "시스템 브라우저로 엽니다 (로그인된 계정 재사용); 완료하면 자동으로 목록에 추가됩니다", "系统默认浏览器": "시스템 기본 브라우저", "编码套餐 API Key": "코딩 플랜 API Key", "网关 Secret": "게이트웨이 시크릿", "网页登录": "웹 로그인", "网页登录的打开方式": "웹 로그인을 여는 방식", "网页登录(Zai / Google)": "웹 로그인 (Zai / Google)", "自定义": "커스텀", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "자체 구축 어그리게이션 패널: 자신의 사이트 주소를 입력하세요. 잔액 조회는 이 계정의 API 키로 {base}/v1/usage 를 호출하며 추가 설정이 필요 없습니다", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "자체 구축 어그리게이션 패널: 자신의 사이트 주소를 입력하세요. 잔액 조회에는 별도로 NewAPI 개인 액세스 토큰이 필요합니다 (아래 \"잔액 조회\" 단락 참조)", "获取风控配置失败,将直接尝试领取:{message}": "리스크 관리 구성을 가져오지 못했습니다. 바로 수령을 시도합니다: {message}", "获取验证码": "코드 받기", "访客模式": "게스트 모드", "访客模式(免登录)": "게스트 모드(로그인 불필요)", "该上游无需鉴权(不发送鉴权头)": "이 업스트림은 인증이 필요하지 않음 (인증 헤더를 보내지 않음)", "该提供商": "이 제공자", "该提供商账号添加功能即将上线": "이 제공자의 계정 추가 기능이 곧 출시됩니다", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "이 커스텀 제공자가 더 이상 존재하지 않습니다(삭제되었을 수 있습니다). 새로 고친 후 다시 시도하세요", "请先选择一个自定义提供商": "먼저 커스텀 제공자를 선택하세요", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "표시된 슬라이더에서 인증을 완료하세요 (공식에서 요구하는 리스크 관리 단계)", "请填写 11 位大陆手机号": "11자리 중국 본토 휴대폰 번호를 입력하세요", "请填写 6 位数字验证码": "6자리 숫자 인증 코드를 입력하세요", "请填写 Base URL": "Base URL을 입력하세요", "请填写 {label}": "{label}을(를) 입력하세요", "请填写名称": "이름을 입력하세요", "请完成验证…": "인증을 완료하세요…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "%APPDATA%/AutoClaw/auth.json을 읽어 복호화합니다. Windows 전용", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "~/.cline/data/settings/providers.json을 읽습니다. Cline 클라이언트에 로그인되어 있어야 합니다", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "~/.meituan-catpaw/auth.json을 읽습니다. CatPaw 클라이언트에 로그인되어 있어야 합니다", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "이 컴퓨터의 KukuAI 클라이언트 로그인 상태를 읽습니다 (%APPDATA%\\baidugenflowpro\\Network\\Cookies). KukuAI 클라이언트에 로그인되어 있어야 합니다", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "로컬 OrcaTerm 클라이언트 로그인 상태(%APPDATA%\\com.orcaterm-desktop.app\\data.bin)를 읽습니다. OrcaTerm 클라이언트에 로그인되어 있어야 합니다", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "이 PC의 智谱清言 클라이언트 로그인 상태를 읽습니다(%APPDATA%\\chatglm\\Network\\Cookies). 클라이언트에 로그인되어 있어야 합니다", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "이 컴퓨터의 공식 클라이언트(Tencent WorkBuddy / WorkBuddy AI)에 현재 로그인된 계정을 읽습니다. 자격 증명 디렉터리에서 최신 로그인 상태 파일을 자동으로 찾습니다(이 컴퓨터의 공식 클라이언트에 로그인되어 있어야 함). 가져온 후에는 게이트웨이가 자동 갱신하므로 2시간 유효 기간에 맞춰 토큰을 수동으로 교체할 필요가 없습니다.", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 읽습니다 (평문 Cookie, 복호화 불필요). 클라이언트 실행 중에는 Cookies 파일이 독점 점유되므로, 가져오기 전에 KukuAI 클라이언트를 먼저 종료하세요.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다).", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다). 클라이언트에서 다시 로그인한 후 「Token 갱신」을 눌러 동기화하세요.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다). 클라이언트에서 다시 로그인한 후 다시 가져오면 됩니다.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다). Zai / Google로 클라이언트에 로그인하는 사용자는 이 항목을 사용하세요.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "이 컴퓨터 클라이언트의 현재 로그인 상태를 매번 실시간으로 읽습니다 (이 기록을 삭제해도 클라이언트 로그인 상태에는 영향을 주지 않습니다). 이 항목은 {label}로 분류됩니다.", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "로컬 클라이언트가 현재 로그인한 OAuth 토큰을 읽습니다(평문 JSON, 복호화 불필요). 가져온 뒤에는 게이트웨이가 자동으로 갱신하므로 클라이언트의 2시간 만료에 맞춰 수동으로 교체할 필요가 없습니다.", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "이 PC 클라이언트의 현재 로그인 상태를 읽습니다. 클라이언트의 Cookies는 DPAPI로 암호화되어 있어(Chromium os_crypt) Windows에서만 사용할 수 있습니다. 클라이언트가 실행 중이면 이 파일을 읽지 못할 수 있으니 클라이언트를 종료한 뒤 다시 시도하세요(\"자격 증명 입력\"으로 토큰을 붙여넣어도 됩니다).", "账号信息": "계정 정보", "账号信息不完整,请刷新后重试": "계정 정보가 불완전합니다. 새로 고친 후 다시 시도하세요", "账号已添加,但请留意:{warning}": "계정은 추가되었지만 확인해 주세요: {warning}", "账号版本": "계정 버전", "账号类型": "계정 유형", "账号:{name}
    ": "계정: {name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "Inference Providers 라우팅을 사용하며, Key는 hf.co/settings/tokens에서 만듭니다", "还没有账号": "아직 계정이 없습니다", "这一家当前不支持网页登录,请改用填写凭证": "이 제공자는 현재 웹 로그인을 지원하지 않습니다. 대신 자격 증명 입력을 사용하세요", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "이 계정에는 현재 자동으로 수령할 수 있는 이벤트가 없습니다 (매일 로그인 보너스 포인트만 자동 수령합니다)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "이 할당량은 「이벤트 플랜」 채널을 사용합니다: 포워딩 시 코딩 플랜이 만료되었다는 안내가 나오면, ", "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "여기에는 중국 사이트(modelscope.cn) 계정을 입력합니다. 중국 사이트의 토큰을 붙여넣으세요. 인터내셔널 사이트(modelscope.ai)는 다른 provider·다른 계정이며, 양쪽 토큰은 호환되지 않습니다.", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "여기에는 중국 사이트(monkeycode-ai.com)의 계정을 입력합니다: 중국 사이트의 session을 붙여넣으세요. 국제 사이트(monkeycode-ai.net)는 다른 제공자이며 별도의 계정입니다. 양쪽 자격 증명은 호환되지 않습니다.", "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "여기에는 인터내셔널 사이트(modelscope.ai) 계정을 입력합니다. 인터내셔널 사이트의 토큰을 붙여넣으세요. 중국 사이트(modelscope.cn)는 다른 provider·다른 계정이며, 양쪽 토큰은 호환되지 않습니다.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "여기에는 국제 사이트(monkeycode-ai.net)의 계정을 입력합니다: 국제 사이트의 session을 붙여넣으세요. 중국 사이트(monkeycode-ai.com)는 다른 제공자이며 별도의 계정입니다. 양쪽 자격 증명은 호환되지 않습니다.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "CatPaw 클라이언트의 로그인 상태 파일 auth.json을 선택하세요 (Windows: C:\\Users\\<사용자 이름>\\.meituan-catpaw\\auth.json, macOS / Linux: ~/.meituan-catpaw/auth.json). 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다 — 더 이상 이 컴퓨터의 클라이언트에 의존하지 않습니다.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Cline 클라이언트의 로그인 상태 파일 providers.json을 선택하세요 (Windows: C:\\Users\\<사용자 이름>\\.cline\\data\\settings\\providers.json, macOS / Linux: ~/.cline/data/settings/providers.json). 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다 — 더 이상 이 컴퓨터의 클라이언트에 의존하지 않습니다. 이 항목은 {label}에 등록됩니다.", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "KukuAI 클라이언트의 Cookies 파일을 선택하세요 (%APPDATA%\\baidugenflowpro\\Network\\Cookies): **바이너리** SQLite 데이터베이스입니다 (확장자 없음, JSON 아님). 가져오기는 선택한 파일의 복사본을 읽어 실행 중인 클라이언트와 점유를 다투지 않으므로 **클라이언트를 먼저 종료할 필요가 없습니다**. 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다.", "选择凭证文件导入": "자격 증명 파일에서 가져오기", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "공식 클라이언트의 로그인 자격 증명 파일(workbuddy-desktop.info / workbuddy-desktop-ai.info) 또는 wb2api에서 내보낸 계정 JSON(중첩/평면 형식 모두 가능)을 선택하세요.", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "小浣熊 클라이언트의 로그인 상태 파일 auth.json을 선택하세요 (Windows: C:\\Users\\<사용자 이름>\\.box-agent\\config\\auth.json, macOS / Linux: ~/.box-agent/config/auth.json). 가져오기 후에는 자격 증명이 게이트웨이에 저장되어 독립적으로 전달할 수 있습니다 — 더 이상 이 컴퓨터의 클라이언트에 의존하지 않습니다.", "选择提供商": "제공자 선택", "选择的文件不是合法 JSON": "선택한 파일이 유효한 JSON이 아닙니다", "选择要添加账号的提供商": "계정을 추가할 제공자 선택", "重新扫描": "다시 스캔", "鉴权": "인증", "阿里云 Token Plan 套餐(国际站)": "Alibaba Cloud Token Plan (국제 사이트)", "阿里云百炼 Coding 套餐(国内站)": "Alibaba Cloud Model Studio Coding 플랜 (중국 사이트)", "阿里云百炼 Coding 套餐(国际站)": "Alibaba Cloud Model Studio Coding 플랜 (국제 사이트)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "Alibaba Cloud Model Studio 모델 서비스 (국제 사이트, OpenAI 호환 모드)", "需要图形验证码:登录窗口已弹出,请填写后继续": "그래픽 캡차가 필요합니다: 로그인 창이 열렸으니 입력한 후 계속하세요", "预置 API": "프리셋 API", "领取 CodeArts 每日福利": "CodeArts 일일 혜택 수령", "领取失败:{message}": "수령 실패: {message}", "领取并让官方确认": "수령하고 공식 확인 받기", "风控验证配置不完整,请稍后重试": "리스크 관리 인증 구성이 불완전합니다. 잠시 후 다시 시도하세요", "验证码": "인증 코드", "验证码已发送。收到后填入下方并点「登录并添加」": "인증 코드를 전송했습니다. 받은 후 아래에 입력하고 「로그인 후 추가」를 클릭하세요", "验证码已发送,请查看手机短信": "인증 코드를 전송했습니다. 휴대폰 SMS를 확인하세요", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "인증 코드를 전송했습니다. 휴대폰 SMS를 확인하세요. 아래에 입력하고 「로그인 후 추가」를 클릭하면 로그인이 완료됩니다", "验证码已发送,请查看短信": "인증 코드를 전송했습니다. 문자 메시지를 확인하세요", "验证码校验失败,请重试": "인증 코드 확인에 실패했습니다. 다시 시도하세요", "验证码校验超时,请重试": "인증 코드 확인 시간이 초과되었습니다. 다시 시도하세요", "验证码组件不可用,请重试": "캡차 컴포넌트를 사용할 수 없습니다. 다시 시도하세요", "验证码组件初始化超时,请重试": "캡차 컴포넌트 초기화 시간이 초과되었습니다. 다시 시도하세요", "验证码组件加载失败,请检查网络后重试": "캡차 컴포넌트 로드에 실패했습니다. 네트워크를 확인한 후 다시 시도하세요", "验证码组件加载异常,请重试": "캡차 컴포넌트 로드 중 오류가 발생했습니다. 다시 시도하세요", "验证码组件加载超时,请检查网络后重试": "캡차 컴포넌트 로드 시간이 초과되었습니다. 네트워크를 확인한 후 다시 시도하세요", "验证码组件未加载,请重启应用后重试": "캡차 컴포넌트가 로드되지 않았습니다. 앱을 다시 시작한 후 다시 시도하세요", "(免费额度池,模型名带 cline-free/ 前缀)。": " (무료 할당량 풀, 모델 이름에 cline-free/ 접두사 포함).", "(其中 {n} 把恢复为不限制)": " (이 중 {n}개는 제한 없음으로 복원)", "(必填)": " (필수)", "(有效期 {window})": "(유효 기간 {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": " (구독 풀, 모델 이름에 cline-pass/ 접두사 포함, 계정에 해당 구독이 있어야 합니다).", ",下一次最快 {minutes} 分钟后": ", 다음 시도는 최소 {minutes}분 후", ",并从 {n} 把 Key 的可用提供商里移除": ", Key {n}개의 사용 가능한 제공자 목록에서 이 제공자를 제거했습니다" }); diff --git a/desktop-tauri/ui/i18n/ko/checkin.js b/desktop-tauri/ui/i18n/ko/checkin.js index 1a3f2ee1..06b41b83 100644 --- a/desktop-tauri/ui/i18n/ko/checkin.js +++ b/desktop-tauri/ui/i18n/ko/checkin.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:ko/checkin —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "SOLO의 checkin_credits 수령 · 자연일 0시 기준 새로고침", "UMID 组件安装失败:{error}": "UMID 컴포넌트 설치 실패: {error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy 중국판 · 작업 트리를 조회한 뒤 한 번에 점등/수령 · 개학 시즌 이벤트와 고양이 여행 포함 · 행을 클릭하면 상세", "WorkBuddy 国际版保活模型,按顺序回退": "WorkBuddy 국제판 키핑 모델, 순서대로 폴백", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "WorkBuddy 국제판 일일 활동용 무료 모델 · 전역 단일 설정, 항목과 무관", "{date}(每天 {time})": "{date} (매일 {time})", "{label} ×{count}({reason})": "{label} ×{count}({reason})", "{n} 项可完成": "{n}개 완료 가능", "{n} 项待领": "수령 대기 {n}건", "{total} 账号 · {done} 已签": "계정 {total}개 · 출석 완료 {done}개", "{total} 项任务 · {pending} 项可完成": "작업 {total}개 · 완료 가능 {pending}개", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ UMID 컴포넌트를 설치했습니다. 다음 출석부터 국제판 포인트를 수령할 수 있습니다", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ 예약 출석이 켜졌습니다", "✅ 开学季任务执行完成": "✅ 개학 시즌 작업 실행 완료", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ 성장 과제 완료: 크레딧 +{credit} 에너지 +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ 입문 혜택 수령 완료, 누적 {n} 포인트", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ 출석 완료: {succeeded}/{total}개 계정 수령 성공{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "\"키핑 모델 체인\"은 WorkBuddy 국제판 일일 활동에서 계정을 활성 상태로 유지하는 무료 모델입니다. 순서대로 시도하며 첫 성공에서 멈춥니다. 비운 채로 제출하면 기본값({defaults})으로 복원됩니다. 당일 중복 제거 + 멱등한 수령: 반복 실행해도 \"이미 수령됨\"만 반환되며 포인트가 이중으로 적립되지 않습니다.", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "\"키핑 모델 체인\"은 WorkBuddy 국제판 일일 활동에서 계정을 활성 상태로 유지하는 무료 모델입니다. 순서대로 시도하며 첫 성공에서 멈춥니다. 목록을 비우고 저장하면 기본 체인(현재 기본값: {defaults})으로 복원됩니다. 당일 중복 제거 + 멱등한 수령: 반복 실행해도 \"이미 수령됨\"만 반환되며 포인트가 이중으로 적립되지 않습니다.", "「免费领积分」的每日任务 · 逐个领取": "「무료 포인트 받기」 일일 작업 · 하나씩 수령", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "일회성 혜택 · 출석 후 자동으로 조회하고 수령하며, 수령을 마치면 로컬에 기록해 업스트림을 더 조회하지 않음 · 행을 클릭해 작업 목록 펼치기", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "그날의 보상을 한 번에 일괄 수령합니다(매일 출석 + 신규 혜택) · 멱등성은 업스트림이 보장", "一键安装组件": "컴포넌트 한 번에 설치", "一键完成": "한 번에 완료", "一键领取({n})": "전체 수령({n})", "上次执行:{line}": "마지막 실행: {line}", "上次签到时间": "최근 출석 시간", "上次领取 {time} · 领取需通过滑块验证码": "최근 수령 {time} · 수령 시 슬라이더 캡차 필요", "下次 {date}": "다음 {date}", "下次 {date} · 点此管理条目": "다음 {date} · 클릭하여 항목 관리", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "일일 출석 제외: {list}. CodeArts의 일회성 보상은 아래 \"입문 혜택\"에 있으며, CodeArts와 ZCode의 일일/플랜 혜택 수령은 \"활동 혜택\"에서 볼 수 있습니다.", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "일일 출석 제외: {list}. CodeArts의 일회성 보상은 아래 \"입문 혜택\"에, CodeArts의 일일 혜택은 바로 위 \"일일 출석\"에 있습니다. ZCode의 플랜 수령은 \"활동 혜택\"에서 볼 수 있습니다.", "与国内版同一套任务接口 · 站点不同": "중국판과 동일한 작업 인터페이스 · 사이트만 다름", "今天已领 {n} 份": "오늘 {n}건 받음", "今天未领": "오늘 미수령", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "오늘(베이징 시간 {day}) 수령 완료 · 공식 확인 반영 {n}건 · 내일 다시 수령 가능", "今日已执行": "오늘 실행됨", "今日已派出": "오늘 이미 출발", "今日已领取": "오늘 수령 완료", "今日签到": "오늘 출석", "今日签到进度": "오늘 출석 진행률", "从清单里移除": "목록에서 제거", "保活": "키핑", "保活 {n}": "키핑 {n}", "保活+领取": "키핑+수령", "保活中…": "키핑 중…", "保活模型链": "키핑 모델 체인", "全选": "전체 선택", "全部 {n} 家": "전체 {n}곳", "全部完成": "모두 완료", "全部查询": "전체 조회", "全部结果": "모든 결과", "全部账号均可签到": "모든 계정이 출석할 수 있습니다", "全部领取": "전체 수령 완료", "关着:所有条目都不执行": "꺼짐: 어떤 항목도 실행되지 않습니다", "删除失败:{error}": "삭제 실패: {error}", "删除定时条目": "예약 항목 삭제", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "예정 시각에 체크한 제공자의 사용 가능한 계정을 자동으로 출석 체크합니다 (WorkBuddy 국내판은 매일 출석 API, 국제판은 데일리 액티비티 퀘스트: 이벤트 탐색 → 데일리 액티브 보상 수령 → 무료 모델로 킵얼라이브하고 웹 채널로 세션을 열어 일일 활성 점등. 소浣熊(샤오환슝)은 데스크톱 일일 포인트 경로, AutoClaw 는 공식 클라이언트의 매일 출석 작업. Qoder 중국판은 이벤트 수령 방식이며 이벤트를 배정받지 못한 계정은 중립적 안내를 받습니다. Qoder 국제판은 기기 리스크 관리 신원(로컬 Qoder 클라이언트 / qodercli 의 UMID 컴포넌트가 생성)을 먼저 갖춰야 \"매일 100 Credits\" 이벤트가 보이며, 컴포넌트가 없으면 오류 대신 명확한 설명을 받습니다. Trae 는 SOLO 의 매일 출석 포인트를 수령하고(자정 리셋), 업스트림이 이벤트를 열지 않았거나 자격 증명에 기기 번호가 없으면 오류 대신 \"미수령 + 사유\"를 받습니다. Loomy 는 매일 계정별 첫 로그인 포인트를 한 번 채우고, KukuAI 는 \"무료 포인트\" 일일 작업을 수령하며, CodeArts 는 당일 운영 혜택을 수령합니다(수령 → 확인 → 재조회 검증. 자동 실행은 하루 6 회 / 10 분 간격 쓰기 요청 제한 내). OfficeAce 는 당일 모든 보상을 한 번에 수령합니다 (매일 출석 + 신규 혜택)). 예정 시각을 놓쳐도 부팅 후 자동으로 보충하므로 전원이 꺼져 있어도 누락되지 않습니다. 각사 출석 API 는 멱등하여 반복 실행해도 중복 수령되지 않습니다.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "정해진 시각이 되면 선택한 제공자의 사용 가능한 계정으로 자동 출석합니다 (WorkBuddy 중국판은 매일 출석 체크 인터페이스, 국제판은 일일 활성 작업으로 진행합니다: 이벤트 탐지, 일일 활성 보상 수령, 무료 모델로 키핑; 小浣熊은 데스크톱 앱 일일 포인트 경로를 사용하고; AutoClaw는 공식 클라이언트의 매일 출석 작업을 사용합니다; Qoder 중국판은 이벤트 수령으로 진행하며, 이벤트가 배정되지 않은 계정은 중립적인 안내를 받습니다; Qoder 국제판은 기기 리스크 관리 신원(로컬 Qoder 클라이언트 / qodercli의 UMID 컴포넌트로 생성)을 먼저 갖춰야 「매일 100 Credits」 이벤트가 보이며, 컴포넌트가 없으면 오류 대신 명확한 설명이 표시됩니다; Trae는 SOLO의 매일 출석 포인트를 수령하며(자연일 0시 기준 초기화), 업스트림이 해당 계정에 이벤트를 열지 않았거나 자격 증명에 기기 번호가 없으면 오류 대신 「미수령 + 구체적 사유」가 표시됩니다; Loomy는 매일 계정당 최초 로그인 포인트를 한 번 적립합니다; KukuAI는 「무료 포인트 받기」 일일 작업을 수령합니다; CodeArts는 당일 운영 혜택을 수령합니다(수령 → 확인 → 재조회 검증, 자동 실행은 하루 6회 / 간격 10분의 쓰기 요청 제한이 적용됩니다); OfficeAce 는 그날의 보상을 한 번의 동작으로 일괄 수령합니다(매일 출석 + 신규 혜택)). 시각을 놓치면 부팅 후 자동으로 보충 출석하며, 당시 컴퓨터가 꺼져 있었다고 해서 빠지지 않습니다. 각 사의 출석 인터페이스는 멱등이므로 반복 실행해도 중복 수령되지 않습니다.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "정해진 시각이 되면 선택한 제공자의 사용 가능한 계정으로 자동 출석합니다 (WorkBuddy 중국판은 매일 출석 체크 인터페이스, 국제판은 일일 활성 작업으로 진행합니다: 이벤트 탐지, 일일 활성 보상 수령, 무료 모델로 키핑; 小浣熊은 데스크톱 앱 일일 포인트 경로를 사용하고; AutoClaw는 공식 클라이언트의 매일 출석 작업을 사용합니다; Qoder 중국판은 이벤트 수령으로 진행하며, 이벤트가 배정되지 않은 계정은 중립적인 안내를 받습니다; Qoder 국제판은 기기 리스크 관리 신원(로컬 Qoder 클라이언트 / qodercli의 UMID 컴포넌트로 생성)을 먼저 갖춰야 「매일 100 Credits」 이벤트가 보이며, 컴포넌트가 없으면 오류 대신 명확한 설명이 표시됩니다; Trae는 SOLO의 매일 출석 포인트를 수령하며(자연일 0시 기준 초기화), 업스트림이 해당 계정에 이벤트를 열지 않았거나 자격 증명에 기기 번호가 없으면 오류 대신 「미수령 + 구체적 사유」가 표시됩니다; Loomy는 매일 계정당 최초 로그인 포인트를 한 번 적립합니다; KukuAI는 「무료 포인트 받기」 일일 작업을 수령합니다; OfficeAce 는 그날의 보상을 한 번의 동작으로 일괄 수령합니다(매일 출석 + 신규 혜택)). 시각을 놓치면 부팅 후 자동으로 보충 출석하며, 당시 컴퓨터가 꺼져 있었다고 해서 빠지지 않습니다. 각 사의 출석 인터페이스는 멱등이므로 반복 실행해도 중복 수령되지 않습니다.", "到点时逐个签到,已勾 {n} / {total} 家": "정해진 시각에 하나씩 출석합니다. 선택 {n} / {total}개", "北京时间 · 错过时点开机后会自动补签": "베이징 시간 · 시간을 놓쳐도 시작 후 자동으로 보완됩니다", "去领取": "수령하러 가기", "另有 {n} 个账号不参与每日签到": "그 외 {n}개 계정은 매일 출석 체크에 참여하지 않습니다", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "완료된 작업의 보상만 수령(멱등, 반복 클릭해도 중복 적립되지 않음)", "可完成": "완료 가능", "可派出": "출발 가능", "可选 · 缺省显示时刻": "선택 · 기본값은 시간 표시", "可领奖": "수령 가능", "后端未返回定时签到数据": "백엔드가 예약 데이터를 반환하지 않았습니다", "后端未返回签到中心数据": "백엔드가 출석 체크 센터 데이터를 반환하지 않았습니다", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "국제판 출석에는 기기 리스크 관리 신원을 생성할 UMID 컴포넌트가 필요합니다 (이 기기에서 감지되지 않음).", "在途": "여행 중", "填入缺省链": "기본 체인 채우기", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "시각과 출석 범위를 정한 뒤 「저장」을 누르세요. 이름은 비워도 됩니다(비우면 시각이 표시됩니다)", "失败 {n}": "실패 {n}", "套餐明细": "플랜 상세", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "Qoder 클라이언트 또는 qodercli를 설치하면 됩니다 (게이트웨이 재시작 불필요).", "安装中…": "설치 중…", "官方客户端的每日签到任务": "공식 클라이언트의 매일 출석 작업", "定时签到": "예약 출석", "定时签到已关闭": "예약 출석이 꺼졌습니다", "尚未查询": "아직 조회하지 않음", "尚未查询任务状态": "작업 상태를 아직 조회하지 않았습니다", "巡检一次": "한 번 점검", "已保存:{label}": "저장됨: {label}", "已保存:保活模型链": "저장됨: 키핑 모델 체인", "已保存:定时条目": "저장됨: 예약 항목", "已删除定时条目": "예약 항목이 삭제되었습니다", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "활동 보고 완료(연속 출석 점등), but 캠페인이 진행 중이 아닙니다(이번에 받을 보상 없음)", "已抽 {n} 次": "{n}회 추첨함", "已有结果 {checked} / 共 {total} 个账号": "결과 있음 {checked} / 전체 {total}개 계정", "已签": "출석 완료", "已领 {claimed}/{total} · 累计 {earned} 积分": "수령 {claimed}/{total} · 누적 {earned} 포인트", "已领养": "입양 완료", "已领取": "수령 완료", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "기기 리스크 관리 신원을 갖춰 「매일 100 Credits」 수령 · UMID 컴포넌트 필요", "开学季执行失败:{error}": "개학 시즌 실행 실패: {error}", "开学季执行完成:{message}": "개학 시즌 실행 완료: {message}", "开学季活动": "개학 시즌 이벤트", "开着:启用的条目按各自时刻执行": "켜짐: 활성화된 항목이 각자의 시간에 실행됩니다", "待签": "출석 대기", "待领新手福利": "수령 대기 입문 혜택", "总开关": "메인 스위치", "总开关已关闭 · 在「定时签到」页打开": "메인 스위치가 꺼져 있습니다 · \"예약 출석\" 탭에서 켜세요", "成功 {n}": "성공 {n}", "成长任务": "성장 과제", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "성장 과제 완료(성공 {done}개, 실패 {failed}개): 크레딧 +{credit} 에너지 +{energy}", "成长任务执行失败:{error}": "성장 과제 실행 실패: {error}", "执行失败:{error}": "실행 실패: {error}", "执行并抽奖": "실행 및 추첨", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "개학 시즌 작업을 실행하고 추첨 기회를 모두 사용(공유/대화/전문가 이벤트)", "把缺省链填进清单,再点「保存」生效": "기본 체인을 목록에 채웁니다. 「저장」을 눌러야 반영됩니다", "抽奖机会 {n} 次": "추첨 기회 {n}회", "按住拖动调整顺序": "길게 눌러 드래그해 순서 변경", "按住拖动,调整这个模型在链里的顺序": "길게 눌러 드래그해 체인에서 이 모델의 순서를 조정합니다", "按序逐个尝试,共 {n} 个": "순서대로 시도, 총 {n}개", "按结果筛选": "결과로 필터", "探测 + 领取 + 保活 · 与定时签到同一套组合": "탐지 + 수령 + 키핑 · 예약 출석과 동일한 조합", "探测活动并领取日活奖励 · 不做保活": "이벤트를 탐지해 일일 활성 보상을 수령 · 키핑은 하지 않음", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "수락 + 점등 + 수령(실측으로 검증된 작업만 처리)", "搜账号 / 收益 / 错误 / 触发原因": "계정 / 수익 / 오류 / 트리거 사유 검색", "收起新建": "새 항목 닫기", "新建定时条目": "새 예약 항목", "新手福利": "입문 혜택", "新手福利有 {n} 项领取失败,可重试": "입문 혜택 {n}건의 수령에 실패했습니다. 재시도할 수 있습니다", "无": "없음", "无独立签到接口 · 每天替账号打一次首次登录积分": "독립 출석 인터페이스 없음 · 매일 계정당 최초 로그인 포인트를 한 번 적립", "无账号": "계정 없음", "暂不可领": "지금은 수령 불가", "暂不支持": "아직 미지원", "暂无启用的条目 · 点此添加": "활성화된 항목이 없습니다 · 클릭하여 추가", "有未保存的改动": "저장되지 않은 변경 사항이 있습니다", "未勾选提供商": "공급자 미선택", "未开启": "꺼짐", "未解锁": "잠김", "未领养(领养需先完成当日对话量)": "미입양(입양하려면 먼저 당일 대화량을 채워야 함)", "未领取": "미수령", "本地台账里今天还没领过;活动期内每天发一份新套餐": "로컬 기록상 오늘은 아직 받지 않았습니다. 이벤트 기간에는 매일 새 플랜이 한 건씩 지급됩니다", "本地台账里今天(北京时间)领过的套餐:{plans}": "로컬 기록상 오늘(베이징 시간) 받은 플랜: {plans}", "条启用": "개 활성화", "查询于 {time}": "조회 시각 {time}", "查询任务": "작업 조회", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "작업 트리를 조회하고 한 번에 점등/수령(개학 시즌과 고양이 여행 포함)", "查询失败:{error}": "조회 실패: {error}", "桌面端每日积分链路": "데스크톱 앱 일일 포인트 경로", "正在读取定时签到数据…": "예약 출석 데이터를 읽는 중…", "正在读取签到数据…": "출석 데이터를 읽는 중…", "每天 {time}": "매일 {time}", "每天 {time} · {scope}": "매일 {time} · {scope}", "每天时刻": "매일 시각", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "출석 실행마다 · 계정별 한 행 · 결과와 수익은 백엔드 기록 기준", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "매일 활성 작업 · 웹 채널 세션으로 일일 활성 달성, 포인트는 수령 시 적립 · 두 가지는 따로 실행 가능", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "매일 로그인 포인트 · 회원 활동 함께 수령 · 게스트 계정은 포인트 체계 없음(건너뜀)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "일일 혜택 · 수령 → 확인 → 재조회 검증 · 베이징 시간 자연일 기준 초기화", "每日签到": "매일 출석 체크", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "항목별 시간과 범위 · 항목별 당일 중복 제거 · 시작 시 자동 보완", "每账号一条明细 · 点此查看「签到记录」": "계정별 한 행 · \"출석 기록\" 열기", "没有可领套餐的账号(ZCode 未添加)。": "수령할 플랜이 있는 계정이 없습니다 (ZCode 미추가).", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "혜택을 수령할 수 있는 계정이 없습니다 (CodeArts / ZCode 미추가).", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "성장 과제를 지원하는 계정이 없습니다(WorkBuddy 중국판 필요).", "没有支持新手福利的账号": "입문 혜택을 지원하는 계정이 없습니다", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "입문 혜택을 지원하는 계정이 없습니다 — 현재 Loomy, 小浣熊, CodeArts 세 곳입니다.", "没有符合筛选条件的签到记录": "필터 조건에 맞는 출석 기록이 없습니다", "没有需要执行的任务": "실행할 작업이 없습니다", "活动福利": "이벤트 혜택", "活动(campaign)领取 · 每天 10:00 刷新": "캠페인(campaign) 수령 · 매일 10:00 새로고침", "活跃上报与保活均未成功,且活动未开启": "활동 보고와 keep-alive 모두 실패했고 캠페인도 진행 중이 아닙니다", "活跃上报完成,但保活未成功且活动未开启": "활동 보고는 완료되었지만 keep-alive에 실패했고 캠페인도 진행 중이 아닙니다", "活跃上报完成,但活动未开启": "활동 보고 완료, but 캠페인이 진행 중이 아닙니다", "活跃上报成功": "활동 보고 성공", "活跃保活失败": "활성 키핑 실패", "活跃保活完成": "활성 키핑 완료", "活跃保活完成,但活动未开启": "활성 키핑 완료, 다만 이벤트는 열리지 않았습니다", "活跃保活完成,但活跃上报失败且活动未开启": "keep-alive는 완료되었지만 활동 보고에 실패했고 캠페인도 진행 중이 아닙니다", "添加条目": "항목 추가", "添加模型": "모델 추가", "清单为空 —— 保存后恢复缺省链": "목록이 비어 있습니다 — 저장하면 기본 체인으로 복원됩니다", "清单里已经有「{name}」": "목록에 \"{name}\"이(가) 이미 있습니다", "清空失败:{error}": "비우기 실패: {error}", "清空签到记录": "출석 기록 비우기", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "\"플랜 상세\"에서 어떤 플랜을 받았고 언제 적용되는지 확인하세요. 이벤트 기간에는 매일 다시 받을 수 있습니다", "点击行展开账号明细 · 单账号签到不受范围限制": "행을 클릭해 계정 상세 펼치기 · 개별 계정 출석은 범위 제한을 받지 않습니다", "独立链路 · 只提供手动入口 · 不进自动签到": "독립 경로 · 수동 진입점만 제공 · 자동 출석에는 포함되지 않음", "猫猫旅行": "고양이 여행", "猫猫旅行失败:{error}": "고양이 여행 실패: {error}", "猫猫旅行失败:{message}": "고양이 여행 실패: {message}", "猫猫旅行:{message}": "고양이 여행: {message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "무료 모델과 웹 채널 세션으로 계정 활성 유지 · 보상은 수령하지 않음", "确定删除「{name}」?删除后到点不再执行。": "\"{name}\"을(를) 삭제할까요? 삭제 후 예약 시간에 실행되지 않습니다.", "确定清空全部签到记录?清空后无法恢复。": "모든 출석 기록을 비울까요? 비운 후에는 복구할 수 없습니다.", "确定清空当前筛选出的签到记录?清空后无法恢复。": "현재 필터된 출석 기록을 비울까요? 비운 후에는 복구할 수 없습니다.", "移除 {name}": "{name} 제거", "立即全部签到": "지금 전체 출석", "签到": "출석", "签到中…": "출석 중…", "签到中心分区": "출석 센터 구역", "签到失败:{error}": "출석 실패: {error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "출석 완료: {succeeded}/{total} 성공{active}, {failed}개 실패", "签到成功": "출석 성공", "签到提供商": "출석 제공자", "签到范围": "출석 범위", "签到触发时刻": "출석 실행 시각", "签到记录": "출석 기록", "签到记录时间范围": "출석 기록 시간 범위", "签到记录表": "출석 기록 표", "累计签到记录": "누적 출석 기록", "结算于 {time}": "결산 시각 {time}", "能量 {n}": "에너지 {n}", "腾讯每日签到接口 · 仅国内版": "텐센트 매일 출석 인터페이스 · 중국판 전용", "至少勾一家才能保存(不勾等于这条条目不签到)": "저장하려면 최소 한 곳을 선택하세요(선택하지 않으면 이 항목은 아무것도 출석하지 않습니다)", "读取定时签到数据失败:{error}": "예약 출석 데이터 로드 실패: {error}", "读取签到数据失败:{error}": "출석 데이터 읽기 실패: {error}", "读取签到记录失败:{error}": "출석 기록 로드 실패: {error}", "跳过 {n}": "건너뜀 {n}", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "운영 이벤트 전달 (수령 → 확인 → 재조회 검증) · 플랜 증정 포인트를 수령합니다", "还没执行过": "아직 실행된 적 없음", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "예약 항목이 아직 없습니다 — \"항목 추가\"로 만들거나 \"출석 센터\"에서 수동으로 출석하세요.", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "출석 기록이 아직 없습니다 — 수동 출석 또는 예약 실행 후 여기에 상세 내역이 표시됩니다.", "连登 {n} 天": "연속 로그인 {n}일", "部分": "일부", "重签": "재출석", "重试": "다시 시도", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "기간 한정 체험 플랜 · 수령 시 슬라이더 인증 필요 · 항목별로 확인하고 수령", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "기간 한정 체험 플랜(start-plan), 이벤트 기간 내 매일 1회 · 수령 시 슬라이더 캡차 필요", "需真实操作": "실제 조작 필요", "非活动期": "이벤트 기간 아님", "项": "건", "领取": "수령", "领取中": "수령 중", "领取中…": "수령 중…", "领取失败": "수령 실패", "领取失败:{error}": "수령 실패: {error}", "(共 {n} 个账号)": "(전체 {n}개 계정)", "(能量 / 连登读数本次未取到)": "(에너지/연속 로그인 수치는 이번에 가져오지 못했습니다)", ",日活保活 {n} 个": ", 일일 활성 키핑 {n}개" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "SOLO의 checkin_credits 수령 · 자연일 0시 기준 새로고침", "UMID 组件安装失败:{error}": "UMID 컴포넌트 설치 실패: {error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy 중국판 · 작업 트리를 조회한 뒤 한 번에 점등/수령 · 개학 시즌 이벤트와 고양이 여행 포함 · 행을 클릭하면 상세", "WorkBuddy 国际版保活模型,按顺序回退": "WorkBuddy 국제판 키핑 모델, 순서대로 폴백", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "WorkBuddy 국제판 일일 활동용 무료 모델 · 전역 단일 설정, 항목과 무관", "{date}(每天 {time})": "{date} (매일 {time})", "{label} ×{count}({reason})": "{label} ×{count}({reason})", "{n} 项可完成": "{n}개 완료 가능", "{n} 项待领": "수령 대기 {n}건", "{total} 账号 · {done} 已签": "계정 {total}개 · 출석 완료 {done}개", "{total} 项任务 · {pending} 项可完成": "작업 {total}개 · 완료 가능 {pending}개", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ UMID 컴포넌트를 설치했습니다. 다음 출석부터 국제판 포인트를 수령할 수 있습니다", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ 예약 출석이 켜졌습니다", "✅ 开学季任务执行完成": "✅ 개학 시즌 작업 실행 완료", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ 성장 과제 완료: 크레딧 +{credit} 에너지 +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ 입문 혜택 수령 완료, 누적 {n} 포인트", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ 출석 완료: {succeeded}/{total}개 계정 수령 성공{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "\"키핑 모델 체인\"은 WorkBuddy 국제판 일일 활동에서 계정을 활성 상태로 유지하는 무료 모델입니다. 순서대로 시도하며 첫 성공에서 멈춥니다. 비운 채로 제출하면 기본값({defaults})으로 복원됩니다. 당일 중복 제거 + 멱등한 수령: 반복 실행해도 \"이미 수령됨\"만 반환되며 포인트가 이중으로 적립되지 않습니다.", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "\"키핑 모델 체인\"은 WorkBuddy 국제판 일일 활동에서 계정을 활성 상태로 유지하는 무료 모델입니다. 순서대로 시도하며 첫 성공에서 멈춥니다. 목록을 비우고 저장하면 기본 체인(현재 기본값: {defaults})으로 복원됩니다. 당일 중복 제거 + 멱등한 수령: 반복 실행해도 \"이미 수령됨\"만 반환되며 포인트가 이중으로 적립되지 않습니다.", "「免费领积分」的每日任务 · 逐个领取": "「무료 포인트 받기」 일일 작업 · 하나씩 수령", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "일회성 혜택 · 출석 후 자동으로 조회하고 수령하며, 수령을 마치면 로컬에 기록해 업스트림을 더 조회하지 않음 · 행을 클릭해 작업 목록 펼치기", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "그날의 보상을 한 번에 일괄 수령합니다(매일 출석 + 신규 혜택) · 멱등성은 업스트림이 보장", "一键安装组件": "컴포넌트 한 번에 설치", "一键完成": "한 번에 완료", "一键领取({n})": "전체 수령({n})", "上次执行:{line}": "마지막 실행: {line}", "上次签到时间": "최근 출석 시간", "上次领取 {time} · 领取需通过滑块验证码": "최근 수령 {time} · 수령 시 슬라이더 캡차 필요", "下次 {date}": "다음 {date}", "下次 {date} · 点此管理条目": "다음 {date} · 클릭하여 항목 관리", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "일일 출석 제외: {list}. CodeArts의 일회성 보상은 아래 \"입문 혜택\"에 있으며, CodeArts와 ZCode의 일일/플랜 혜택 수령은 \"활동 혜택\"에서 볼 수 있습니다.", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "일일 출석 제외: {list}. CodeArts의 일회성 보상은 아래 \"입문 혜택\"에, CodeArts의 일일 혜택은 바로 위 \"일일 출석\"에 있습니다. ZCode의 플랜 수령은 \"활동 혜택\"에서 볼 수 있습니다.", "与国内版同一套任务接口 · 站点不同": "중국판과 동일한 작업 인터페이스 · 사이트만 다름", "与国内版同一套链路 · 站点不同、令牌不通用": "중국판과 동일한 흐름 · 사이트가 다르고 토큰은 호환되지 않음", "今天已领 {n} 份": "오늘 {n}건 받음", "今天未领": "오늘 미수령", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "오늘(베이징 시간 {day}) 수령 완료 · 공식 확인 반영 {n}건 · 내일 다시 수령 가능", "今日已执行": "오늘 실행됨", "今日已派出": "오늘 이미 출발", "今日已领取": "오늘 수령 완료", "今日签到": "오늘 출석", "今日签到进度": "오늘 출석 진행률", "从清单里移除": "목록에서 제거", "保活": "키핑", "保活 {n}": "키핑 {n}", "保活+领取": "키핑+수령", "保活中…": "키핑 중…", "保活模型链": "키핑 모델 체인", "全选": "전체 선택", "全部 {n} 家": "전체 {n}곳", "全部完成": "모두 완료", "全部查询": "전체 조회", "全部结果": "모든 결과", "全部账号均可签到": "모든 계정이 출석할 수 있습니다", "全部领取": "전체 수령 완료", "关着:开机后等到窗口起点再签,随机窗口当天生效": "꺼짐: 시작 후 윈도 시작까지 기다리며, 당일부터 랜덤 윈도가 적용", "关着:所有条目都不执行": "꺼짐: 어떤 항목도 실행되지 않습니다", "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "분 · 윈도 내에서 계정별로 무작위 시각에 실행, 0 = 정시에 즉시 실행", "删除失败:{error}": "삭제 실패: {error}", "删除定时条目": "예약 항목 삭제", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "시간이 되면 선택한 제공자의 사용 가능한 계정으로 출석합니다(WorkBuddy 중국판은 일일 출석 API, 국제판은 데일리 액티브 작업: 액티비티 탐지·일일 보상 수령·무료 모델로 키프얼라이브와 웹 세션으로 연속일 점등. 라쿤은 데스크톱 일일 포인트 경로, AutoClaw는 공식 클라이언트의 일일 출석 작업, Qoder 중국판은 캠페인 수령이며 캠페인이 없는 계정에는 중립 안내를 표시, Qoder 국제판은 기기 리스크 신원(로컬 Qoder 클라이언트 / qodercli의 UMID 컴포넌트 생성)이 필요하며 컴포넌트가 없으면 오류 대신 명확한 설명을 표시합니다. Trae는 SOLO의 일일 출석 크레딧(현지 0시 리셋)을 받고, 업스트림이 계정에 캠페인을 내려주지 않았거나 자격 증명에 기기 ID가 없으면 오류 대신 \"미수령 + 사유\"를 반환합니다. Loomy는 매일 최초 로그인 포인트를 한 번 호출하고, KukuAI는 \"무료 포인트\" 일일 작업을 받고, CodeArts는 당일 운영 혜택(수령 → 확인 → 재조회, 자동 실행은 하루 6회·10분 간격 쓰기 제한)을 받고, OfficeAce는 그날의 모든 보상(일일 출석 + 신규 혜택)을 한 번에 받습니다). \"랜덤 폭 N분\"을 설정하면 해당 회차의 계정은 각자의 윈도 내(당일 0:00-23:59로 클램프)에 분산 실행되어 같은 1분에 몰리지 않습니다. 윈도가 이미 지났다면 전부 즉시 실행합니다. 놓친 회차는 시작 후 보충되므로 전원이 꺼져 있었다고 해서 사라지지 않습니다(\"시작 시 보충\"을 끄면 윈도 시작까지 기다립니다). 각 제공자의 출석 API는 멱등이며 반복 실행해도 이중 수령되지 않습니다.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "정해진 시각이 되면 선택한 제공자의 사용 가능한 계정으로 자동 출석합니다 (WorkBuddy 중국판은 매일 출석 체크 인터페이스, 국제판은 일일 활성 작업으로 진행합니다: 이벤트 탐지, 일일 활성 보상 수령, 무료 모델로 키핑; 小浣熊은 데스크톱 앱 일일 포인트 경로를 사용하고; AutoClaw는 공식 클라이언트의 매일 출석 작업을 사용합니다; Qoder 중국판은 이벤트 수령으로 진행하며, 이벤트가 배정되지 않은 계정은 중립적인 안내를 받습니다; Qoder 국제판은 기기 리스크 관리 신원(로컬 Qoder 클라이언트 / qodercli의 UMID 컴포넌트로 생성)을 먼저 갖춰야 「매일 100 Credits」 이벤트가 보이며, 컴포넌트가 없으면 오류 대신 명확한 설명이 표시됩니다; Trae는 SOLO의 매일 출석 포인트를 수령하며(자연일 0시 기준 초기화), 업스트림이 해당 계정에 이벤트를 열지 않았거나 자격 증명에 기기 번호가 없으면 오류 대신 「미수령 + 구체적 사유」가 표시됩니다; Loomy는 매일 계정당 최초 로그인 포인트를 한 번 적립합니다; KukuAI는 「무료 포인트 받기」 일일 작업을 수령합니다; CodeArts는 당일 운영 혜택을 수령합니다(수령 → 확인 → 재조회 검증, 자동 실행은 하루 6회 / 간격 10분의 쓰기 요청 제한이 적용됩니다); OfficeAce 는 그날의 보상을 한 번의 동작으로 일괄 수령합니다(매일 출석 + 신규 혜택)). 시각을 놓치면 부팅 후 자동으로 보충 출석하며, 당시 컴퓨터가 꺼져 있었다고 해서 빠지지 않습니다. 각 사의 출석 인터페이스는 멱등이므로 반복 실행해도 중복 수령되지 않습니다.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "정해진 시각이 되면 선택한 제공자의 사용 가능한 계정으로 자동 출석합니다 (WorkBuddy 중국판은 매일 출석 체크 인터페이스, 국제판은 일일 활성 작업으로 진행합니다: 이벤트 탐지, 일일 활성 보상 수령, 무료 모델로 키핑; 小浣熊은 데스크톱 앱 일일 포인트 경로를 사용하고; AutoClaw는 공식 클라이언트의 매일 출석 작업을 사용합니다; Qoder 중국판은 이벤트 수령으로 진행하며, 이벤트가 배정되지 않은 계정은 중립적인 안내를 받습니다; Qoder 국제판은 기기 리스크 관리 신원(로컬 Qoder 클라이언트 / qodercli의 UMID 컴포넌트로 생성)을 먼저 갖춰야 「매일 100 Credits」 이벤트가 보이며, 컴포넌트가 없으면 오류 대신 명확한 설명이 표시됩니다; Trae는 SOLO의 매일 출석 포인트를 수령하며(자연일 0시 기준 초기화), 업스트림이 해당 계정에 이벤트를 열지 않았거나 자격 증명에 기기 번호가 없으면 오류 대신 「미수령 + 구체적 사유」가 표시됩니다; Loomy는 매일 계정당 최초 로그인 포인트를 한 번 적립합니다; KukuAI는 「무료 포인트 받기」 일일 작업을 수령합니다; OfficeAce 는 그날의 보상을 한 번의 동작으로 일괄 수령합니다(매일 출석 + 신규 혜택)). 시각을 놓치면 부팅 후 자동으로 보충 출석하며, 당시 컴퓨터가 꺼져 있었다고 해서 빠지지 않습니다. 각 사의 출석 인터페이스는 멱등이므로 반복 실행해도 중복 수령되지 않습니다.", "到点时逐个签到,已勾 {n} / {total} 家": "정해진 시각에 하나씩 출석합니다. 선택 {n} / {total}개", "北京时间 · 错过时点开机后会自动补签": "베이징 시간 · 시간을 놓쳐도 시작 후 자동으로 보완됩니다", "去领取": "수령하러 가기", "另有 {n} 个账号不参与每日签到": "그 외 {n}개 계정은 매일 출석 체크에 참여하지 않습니다", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "완료된 작업의 보상만 수령(멱등, 반복 클릭해도 중복 적립되지 않음)", "可完成": "완료 가능", "可派出": "출발 가능", "可选 · 缺省显示时刻": "선택 · 기본값은 시간 표시", "可领奖": "수령 가능", "后端未返回定时签到数据": "백엔드가 예약 데이터를 반환하지 않았습니다", "后端未返回签到中心数据": "백엔드가 출석 체크 센터 데이터를 반환하지 않았습니다", "启动补签": "시작 시 보충", "启动补签已关闭": "시작 시 보충을 껐습니다", "启动补签已开启": "시작 시 보충을 켰습니다", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "국제판 출석에는 기기 리스크 관리 신원을 생성할 UMID 컴포넌트가 필요합니다 (이 기기에서 감지되지 않음).", "在途": "여행 중", "填入缺省链": "기본 체인 채우기", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "시각과 출석 범위를 정한 뒤 「저장」을 누르세요. 이름은 비워도 됩니다(비우면 시각이 표시됩니다)", "失败 {n}": "실패 {n}", "套餐明细": "플랜 상세", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "Qoder 클라이언트 또는 qodercli를 설치하면 됩니다 (게이트웨이 재시작 불필요).", "安装中…": "설치 중…", "官方客户端的每日签到任务": "공식 클라이언트의 매일 출석 작업", "定时签到": "예약 출석", "定时签到已关闭": "예약 출석이 꺼졌습니다", "尚未查询": "아직 조회하지 않음", "尚未查询任务状态": "작업 상태를 아직 조회하지 않았습니다", "巡检一次": "한 번 점검", "已保存:{label}": "저장됨: {label}", "已保存:保活模型链": "저장됨: 키핑 모델 체인", "已保存:定时条目": "저장됨: 예약 항목", "已删除定时条目": "예약 항목이 삭제되었습니다", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "활동 보고 완료(연속 출석 점등), but 캠페인이 진행 중이 아닙니다(이번에 받을 보상 없음)", "已抽 {n} 次": "{n}회 추첨함", "已有结果 {checked} / 共 {total} 个账号": "결과 있음 {checked} / 전체 {total}개 계정", "已签": "출석 완료", "已领 {claimed}/{total} · 累计 {earned} 积分": "수령 {claimed}/{total} · 누적 {earned} 포인트", "已领养": "입양 완료", "已领取": "수령 완료", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "기기 리스크 관리 신원을 갖춰 「매일 100 Credits」 수령 · UMID 컴포넌트 필요", "开学季执行失败:{error}": "개학 시즌 실행 실패: {error}", "开学季执行完成:{message}": "개학 시즌 실행 완료: {message}", "开学季活动": "개학 시즌 이벤트", "开着:启用的条目按各自时刻执行": "켜짐: 활성화된 항목이 각자의 시간에 실행됩니다", "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "켜짐: 시작 직후 오늘 아직 실행하지 않은 스케줄을 랜덤 윈도를 무시하고 즉시 보충", "待签": "출석 대기", "待领新手福利": "수령 대기 입문 혜택", "总开关": "메인 스위치", "总开关已关闭 · 在「定时签到」页打开": "메인 스위치가 꺼져 있습니다 · \"예약 출석\" 탭에서 켜세요", "成功 {n}": "성공 {n}", "成长任务": "성장 과제", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "성장 과제 완료(성공 {done}개, 실패 {failed}개): 크레딧 +{credit} 에너지 +{energy}", "成长任务执行失败:{error}": "성장 과제 실행 실패: {error}", "执行失败:{error}": "실행 실패: {error}", "执行并抽奖": "실행 및 추첨", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "개학 시즌 작업을 실행하고 추첨 기회를 모두 사용(공유/대화/전문가 이벤트)", "把缺省链填进清单,再点「保存」生效": "기본 체인을 목록에 채웁니다. 「저장」을 눌러야 반영됩니다", "抽奖机会 {n} 次": "추첨 기회 {n}회", "按住拖动调整顺序": "길게 눌러 드래그해 순서 변경", "按住拖动,调整这个模型在链里的顺序": "길게 눌러 드래그해 체인에서 이 모델의 순서를 조정합니다", "按序逐个尝试,共 {n} 个": "순서대로 시도, 총 {n}개", "按结果筛选": "결과로 필터", "探测 + 领取 + 保活 · 与定时签到同一套组合": "탐지 + 수령 + 키핑 · 예약 출석과 동일한 조합", "探测活动并领取日活奖励 · 不做保活": "이벤트를 탐지해 일일 활성 보상을 수령 · 키핑은 하지 않음", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "수락 + 점등 + 수령(실측으로 검증된 작업만 처리)", "搜账号 / 收益 / 错误 / 触发原因": "계정 / 수익 / 오류 / 트리거 사유 검색", "收起新建": "새 항목 닫기", "新建定时条目": "새 예약 항목", "新手福利": "입문 혜택", "新手福利有 {n} 项领取失败,可重试": "입문 혜택 {n}건의 수령에 실패했습니다. 재시도할 수 있습니다", "无": "없음", "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "전용 체크인 API 없음 · 하루에 한 번 계정 대신 로그인 정보 엔드포인트를 호출(그것이 당일 마립)", "无独立签到接口 · 每天替账号打一次首次登录积分": "독립 출석 인터페이스 없음 · 매일 계정당 최초 로그인 포인트를 한 번 적립", "无账号": "계정 없음", "暂不可领": "지금은 수령 불가", "暂不支持": "아직 미지원", "暂无启用的条目 · 点此添加": "활성화된 항목이 없습니다 · 클릭하여 추가", "有未保存的改动": "저장되지 않은 변경 사항이 있습니다", "未勾选提供商": "공급자 미선택", "未开启": "꺼짐", "未解锁": "잠김", "未领养(领养需先完成当日对话量)": "미입양(입양하려면 먼저 당일 대화량을 채워야 함)", "未领取": "미수령", "本地台账里今天还没领过;活动期内每天发一份新套餐": "로컬 기록상 오늘은 아직 받지 않았습니다. 이벤트 기간에는 매일 새 플랜이 한 건씩 지급됩니다", "本地台账里今天(北京时间)领过的套餐:{plans}": "로컬 기록상 오늘(베이징 시간) 받은 플랜: {plans}", "条启用": "개 활성화", "查询于 {time}": "조회 시각 {time}", "查询任务": "작업 조회", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "작업 트리를 조회하고 한 번에 점등/수령(개학 시즌과 고양이 여행 포함)", "查询失败:{error}": "조회 실패: {error}", "桌面端每日积分链路": "데스크톱 앱 일일 포인트 경로", "正在读取定时签到数据…": "예약 출석 데이터를 읽는 중…", "正在读取签到数据…": "출석 데이터를 읽는 중…", "每天 {time}": "매일 {time}", "每天 {time} · {scope}": "매일 {time} · {scope}", "每天 {time} · 随机前后 {n} 分钟 · {scope}": "매일 {time} ± {n}분 · {scope}", "每天时刻": "매일 시각", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "출석 실행마다 · 계정별 한 행 · 결과와 수익은 백엔드 기록 기준", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "매일 활성 작업 · 웹 채널 세션으로 일일 활성 달성, 포인트는 수령 시 적립 · 두 가지는 따로 실행 가능", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "매일 로그인 포인트 · 회원 활동 함께 수령 · 게스트 계정은 포인트 체계 없음(건너뜀)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "일일 혜택 · 수령 → 확인 → 재조회 검증 · 베이징 시간 자연일 기준 초기화", "每日签到": "매일 출석 체크", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "항목별 시간과 범위 · 항목별 당일 중복 제거 · 시작 시 자동 보완", "每账号一条明细 · 点此查看「签到记录」": "계정별 한 행 · \"출석 기록\" 열기", "没有可领套餐的账号(ZCode 未添加)。": "수령할 플랜이 있는 계정이 없습니다 (ZCode 미추가).", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "혜택을 수령할 수 있는 계정이 없습니다 (CodeArts / ZCode 미추가).", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "성장 과제를 지원하는 계정이 없습니다(WorkBuddy 중국판 필요).", "没有支持新手福利的账号": "입문 혜택을 지원하는 계정이 없습니다", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "입문 혜택을 지원하는 계정이 없습니다 — 현재 Loomy, 小浣熊, CodeArts 세 곳입니다.", "没有符合筛选条件的签到记录": "필터 조건에 맞는 출석 기록이 없습니다", "没有需要执行的任务": "실행할 작업이 없습니다", "活动福利": "이벤트 혜택", "活动(campaign)领取 · 每天 10:00 刷新": "캠페인(campaign) 수령 · 매일 10:00 새로고침", "活跃上报与保活均未成功,且活动未开启": "활동 보고와 keep-alive 모두 실패했고 캠페인도 진행 중이 아닙니다", "活跃上报完成,但保活未成功且活动未开启": "활동 보고는 완료되었지만 keep-alive에 실패했고 캠페인도 진행 중이 아닙니다", "活跃上报完成,但活动未开启": "활동 보고 완료, but 캠페인이 진행 중이 아닙니다", "活跃上报成功": "활동 보고 성공", "活跃保活失败": "활성 키핑 실패", "活跃保活完成": "활성 키핑 완료", "活跃保活完成,但活动未开启": "활성 키핑 완료, 다만 이벤트는 열리지 않았습니다", "活跃保活完成,但活跃上报失败且活动未开启": "keep-alive는 완료되었지만 활동 보고에 실패했고 캠페인도 진행 중이 아닙니다", "添加条目": "항목 추가", "添加模型": "모델 추가", "清单为空 —— 保存后恢复缺省链": "목록이 비어 있습니다 — 저장하면 기본 체인으로 복원됩니다", "清单里已经有「{name}」": "목록에 \"{name}\"이(가) 이미 있습니다", "清空失败:{error}": "비우기 실패: {error}", "清空签到记录": "출석 기록 비우기", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "\"플랜 상세\"에서 어떤 플랜을 받았고 언제 적용되는지 확인하세요. 이벤트 기간에는 매일 다시 받을 수 있습니다", "点击行展开账号明细 · 单账号签到不受范围限制": "행을 클릭해 계정 상세 펼치기 · 개별 계정 출석은 범위 제한을 받지 않습니다", "独立链路 · 只提供手动入口 · 不进自动签到": "독립 경로 · 수동 진입점만 제공 · 자동 출석에는 포함되지 않음", "猫猫旅行": "고양이 여행", "猫猫旅行失败:{error}": "고양이 여행 실패: {error}", "猫猫旅行失败:{message}": "고양이 여행 실패: {message}", "猫猫旅行:{message}": "고양이 여행: {message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "무료 모델과 웹 채널 세션으로 계정 활성 유지 · 보상은 수령하지 않음", "确定删除「{name}」?删除后到点不再执行。": "\"{name}\"을(를) 삭제할까요? 삭제 후 예약 시간에 실행되지 않습니다.", "确定清空全部签到记录?清空后无法恢复。": "모든 출석 기록을 비울까요? 비운 후에는 복구할 수 없습니다.", "确定清空当前筛选出的签到记录?清空后无法恢复。": "현재 필터된 출석 기록을 비울까요? 비운 후에는 복구할 수 없습니다.", "移除 {name}": "{name} 제거", "立即全部签到": "지금 전체 출석", "签到": "출석", "签到中…": "출석 중…", "签到中心分区": "출석 센터 구역", "签到失败:{error}": "출석 실패: {error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "출석 완료: {succeeded}/{total} 성공{active}, {failed}개 실패", "签到成功": "출석 성공", "签到提供商": "출석 제공자", "签到范围": "출석 범위", "签到触发时刻": "출석 실행 시각", "签到记录": "출석 기록", "签到记录时间范围": "출석 기록 시간 범위", "签到记录表": "출석 기록 표", "累计签到记录": "누적 출석 기록", "结算于 {time}": "결산 시각 {time}", "能量 {n}": "에너지 {n}", "腾讯每日签到接口 · 仅国内版": "텐센트 매일 출석 인터페이스 · 중국판 전용", "至少勾一家才能保存(不勾等于这条条目不签到)": "저장하려면 최소 한 곳을 선택하세요(선택하지 않으면 이 항목은 아무것도 출석하지 않습니다)", "读取定时签到数据失败:{error}": "예약 출석 데이터 로드 실패: {error}", "读取签到数据失败:{error}": "출석 데이터 읽기 실패: {error}", "读取签到记录失败:{error}": "출석 기록 로드 실패: {error}", "跳过 {n}": "건너뜀 {n}", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "운영 이벤트 전달 (수령 → 확인 → 재조회 검증) · 플랜 증정 포인트를 수령합니다", "还没执行过": "아직 실행된 적 없음", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "예약 항목이 아직 없습니다 — \"항목 추가\"로 만들거나 \"출석 센터\"에서 수동으로 출석하세요.", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "출석 기록이 아직 없습니다 — 수동 출석 또는 예약 실행 후 여기에 상세 내역이 표시됩니다.", "连登 {n} 天": "연속 로그인 {n}일", "部分": "일부", "重签": "재출석", "重试": "다시 시도", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "기간 한정 체험 플랜 · 수령 시 슬라이더 인증 필요 · 항목별로 확인하고 수령", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "기간 한정 체험 플랜(start-plan), 이벤트 기간 내 매일 1회 · 수령 시 슬라이더 캡차 필요", "随机前后": "랜덤 폭", "需真实操作": "실제 조작 필요", "非活动期": "이벤트 기간 아님", "项": "건", "领取": "수령", "领取中": "수령 중", "领取中…": "수령 중…", "领取失败": "수령 실패", "领取失败:{error}": "수령 실패: {error}", "(共 {n} 个账号)": "(전체 {n}개 계정)", "(能量 / 连登读数本次未取到)": "(에너지/연속 로그인 수치는 이번에 가져오지 못했습니다)", ",日活保活 {n} 个": ", 일일 활성 키핑 {n}개" }); diff --git a/desktop-tauri/ui/i18n/pt-BR/add-account.js b/desktop-tauri/ui/i18n/pt-BR/add-account.js index e1a4972c..da9d29e4 100644 --- a/desktop-tauri/ui/i18n/pt-BR/add-account.js +++ b/desktop-tauri/ui/i18n/pt-BR/add-account.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:pt-BR/add-account —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · Modelos: {head}{rest}", " 等 {n} 个": " ({n} no total)", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "Google refresh token começando com 1// (também pode colar a linha refresh_token=… inteira)", "11 位大陆手机号": "Celular da China continental (11 dígitos)", "1~64 个字符,账号列表里按它分组显示": "1 a 64 caracteres; na lista de contas, as contas são agrupadas por ele", "6 位数字": "6 dígitos", "

  • 没有可自动领的活动
  • ": "
  • Nenhuma campanha pode ser resgatada automaticamente
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    O que você recebe são pontos de brinde do plano, que não aumentam o pool de tokens dos modelos de benefício; ", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "O endpoint compatível com Anthropic é https://api.deepseek.com/anthropic (preencha-o ao trocar o protocolo para anthropic)", "Anthropic 协议填根地址,不要带 /v1": "No protocolo Anthropic, preencha o endereço raiz, sem /v1", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw edição da China", "AutoClaw 国际版": "AutoClaw edição internacional", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS é obrigatório; cole o **Cookie completo** (um editor de Cookie exporta com um clique) — o **PTOKEN deve ser mantido**, pois o gateway o usa para trocar com o Baidu por um token de sessão de negócio do KukuAI; sem ele, a atualização de modelos reporta \"não conectado\". São aceitos o cabeçalho Cookie inteiro, um array JSON exportado por um editor de Cookie, ou um objeto {BDUSS, STOKEN}. O KukuAI não tem mecanismo de atualização; quando a sessão de login expirar, basta colar de novo.", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=… (ou o JSON exportado por um editor de Cookie)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "X-Passport-Token do CatPaw (Cookie da sessão de login)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Obtenha a API Key do Cline Pass em app.cline.bot (por assinatura); o endpoint é compatível com OpenAI, o catálogo de modelos segue o console da Cline e os nomes dos modelos são adicionados no gerenciamento de modelos como nomes simples, sem prefixo (ex.: glm-5.2 / kimi-k2.7-code / deepseek-v4-pro); o upstream valida o formato do cliente, e os cabeçalhos de requisição do cliente necessários já vêm predefinidos neste cartão", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT (três segmentos separados por ponto)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT (três partes separadas por pontos; também pode colar a linha Bearer inteira ou o conteúdo do data.bin)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT (três partes separadas por ponto; colar a linha chatglm_token=… inteira também funciona)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode edição internacional", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "Endpoint gerenciado do NVIDIA NIM; solicite a Key em integrate.api.nvidia.com", "OfficeAce 果办": "OfficeAce", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken é a credencial de login do Accio (um token opaco bem longo, não é JWT); refreshToken é opcional e, se preenchido, permite renovação automática ao expirar. Preencha a credencial da conta {label} — {siteNote} (a forma mais fácil de obter: use o \"Login web\" acima; não é preciso procurar o token manualmente.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken é o Cloud-IDE-JWT do Trae (três segmentos separados por ponto) e o refreshToken serve para renovação automática ao expirar (este provedor troca o refreshToken a cada uso: assim que é trocado, o antigo é invalidado, então não atualize a mesma conta em dois programas ao mesmo tempo).
    Ao colar manualmente, preencha também machineId / deviceId: o upstream os vincula à chave pública do dispositivo enviada no login para identificar o dispositivo, e inventar um novo par dispara a família de rejeições de vínculo de dispositivo 2xxxx.
    Sem esses três itens, o caminho correto é o \"Login web\" acima; em contêiner / implantação remota, basta colar o endereço de callback da barra de endereços conforme as instruções.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "O valor de monkeycode_ai_session (também pode colar o Cookie inteiro)", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken é opcional e, se preenchido, permite renovação automática ao expirar; ambos podem ser obtidos do arquivo de sessão de login do cliente Raccoon.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken é opcional e, se preenchido, permite renovação automática; ambos podem ser obtidos do arquivo de sessão de login do cliente. A mesma conta Cline funciona nos dois pools; aqui ela entra em {label}.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "O token aceita o prefixo enc: (descriptografado automaticamente no Windows). Sem preencher o refreshToken, não é possível renovar automaticamente.", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "O token é o Cookie da sessão de login; o CatPaw não tem mecanismo de atualização, então faça login novamente no cliente após expirar.", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "API Key começando com user_ (também pode colar a linha Authorization: Bearer … inteira)", "{label} 网页登录的打开方式": "Como abrir o login web de {label}", "{label} 账号地区": "Região da conta {label}", "{label} 账号的添加方式": "Como adicionar uma conta {label}", "{name} 不是合法 JSON:{reason}": "{name} não é um JSON válido: {reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name}: cole um objeto JSON (no formato {sample})", "{n} 个账号": "{n} contas", "{n} 个账号,点击添加": "{n} contas, clique para adicionar", "{seconds}s 后重发": "Reenviar em {seconds}s", "✅ {label}账号已添加": "✅ Conta {label} adicionada", "✅ {label}账号已添加{name}": "✅ Conta {label} adicionada{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ {n} provedores importados do cc-switch", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ Provedor personalizado \"{name}\" criado e conta adicionada", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ Provedor personalizado \"{name}\" excluído{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ Conta existente{name} atualizada (apenas uma conta por chave de API; adições repetidas são mescladas)", "✅ 登录成功,{edition}账号已加入列表": "✅ Login concluído; conta {edition} adicionada à lista", "✅ 领取成功:{planId}{period}": "✅ Resgate concluído: {planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " Um mesmo provedor pode ter várias keys, rotacionadas por prioridade.", "「{name}」的账号添加功能还在开发中,敬请期待。": "A adição de contas para \"{name}\" ainda está em desenvolvimento; aguarde novidades.", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "Uma única Key serve para vários fornecedores; use o nome completo \"fornecedor/modelo\" (ex.: deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "Deixe em branco quando o upstream não exigir autenticação e marque a opção abaixo (em branco e sem marcar é tratado como credencial não configurada)", "上游信息": "Informações do upstream", "不可领({status})": "Não resgatável ({status})", "不支持导入": "Importação não suportada", "不是有效的凭证文件:内容要是一个 JSON 对象": "Não é um arquivo de credenciais válido: o conteúdo deve ser um objeto JSON", "不是有效的凭证文件:需要包含 accessToken 与 uid": "Não é um arquivo de credenciais válido: accessToken e uid são obrigatórios", "不是自定义提供商": "Não é um provedor personalizado", "不需要 Key:转发与拉取模型都不发送鉴权头": "Não precisa de Key: nem o encaminhamento nem a busca de modelos enviam cabeçalhos de autenticação", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "Não é preciso fazer login: clique no botão abaixo e o gateway vai obter uma credencial de visitante diretamente do Zhipu Qingyan e adicioná-la à lista de contas (você pode preencher um nome de observação antes). A credencial de visitante pode ser usada para conversar imediatamente; a cota gratuita é emitida pela origem por dispositivo.

    Atenção: uma conta de visitante não tem sistema de pontos — as interfaces de pontos de membro, pontos de login diário e resgate de atividades exigem login, então esses recursos são ignorados para visitantes (nenhuma leitura aparece na página de contas nem na central de check-in). Para obter pontos, use \"Preencher credenciais\" para colar o token de uma conta conectada, ou \"Importar estado de login do desktop\".", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "As contas das duas edições podem ser salvas ao mesmo tempo, cada uma com sua própria lista de modelos (as edições da China e internacional são dois provedores, que podem ser ativados e mapeados separadamente).", "中国版": "Edição da China", "今天没有需要领的活动(都已到账)": "Hoje não há campanhas para resgatar (todas já creditadas)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "Hoje (horário de Pequim, {day}) você já tentou {attempts} vezes; restam {left} tentativas{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "Pegue três itens de outra máquina (ou do models.json do aplicativo de desktop do OfficeAce) e cole aqui: o endereço base do gateway de modelos (baseUrl, no formato https://modelgw-…/v2) e modelAppKey / modelAppSecret. Esses três já bastam para encaminhar requisições (a credencial do gateway não expira); as credenciais temporárias do plano de controle (accessKeyId etc.) são opcionais — se ficarem em branco, a consulta de saldo e a renovação automática ficam indisponíveis, mas o encaminhamento não é afetado.", "从本机导入桌面端登录态": "Importar sessão de login do desktop desta máquina", "任务镜像 id": "id da imagem da tarefa", "余额查询": "Consulta de saldo", "使用 Google 账号登录": "Entrar com conta Google", "使用 Zai 账号登录": "Entrar com conta Zai", "使用个人访问令牌(PAT)": "Usar token de acesso pessoal (PAT)", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "Modelos gratuitos não precisam de Key (a opção \"Este upstream não exige autenticação\" já vem marcada e o gateway usa credenciais anônimas automaticamente); para modelos pagos, preencha a API Key do Zen. O nível gratuito do upstream só aceita o formato do cliente oficial, e a opção \"Simular o cliente oficial do OpenCode\" já vem ativada", "内嵌窗口": "Janela embutida", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "Abre na janela embutida; fechar a janela cancela a espera (se a conta Google for recusada, use o navegador do sistema)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "Abre na janela embutida; ao concluir, entra automaticamente na lista; fechar a janela cancela a espera", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "Abre em uma janela incorporada; a conta é adicionada automaticamente após o escaneamento — fechar a janela cancela a espera", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "A janela embutida usa um ambiente totalmente novo, então várias contas não interferem entre si; fechar a janela cancela a espera", "内嵌窗口(推荐)": "Janela embutida (recomendado)", "准备验证…": "Preparando a verificação…", "凭据 JSON": "JSON da credencial", "凭证文件在哪?": "Onde fica o arquivo de credenciais?", "创建并添加账号": "Criar e adicionar conta", "创建这个提供商,并同时建立它的第一个账号。": "Crie este provedor e, ao mesmo tempo, sua primeira conta.", "删除功能不可用(脚本未就绪)": "Exclusão indisponível (script não está pronto)", "删除失败:{reason}": "Falha ao excluir: {reason}", "删除此提供商": "Excluir este provedor", "及 {n} 个账号": " e {n} contas", "发送中…": "Enviando…", "发送失败:{message}": "Falha ao enviar: {message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "Envio não confirmado: a janela de login foi aberta; conclua o login manualmente nessa janela", "取消失败:{message}": "Falha ao cancelar: {message}", "取消等待": "Cancelar espera", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "Somente a \"Janela embutida\" pode restaurar os acessos de terceiros: no navegador do sistema não podemos alterar a página de login", "可选": "Opcional", "可选(cloudaicompanionProject):留空由网关自动发现": "Opcional (cloudaicompanionProject); se vazio, o gateway descobre automaticamente", "可选,展示用": "Opcional, para exibição", "可选,没有则无法自动续期": "Opcional; sem ele, não é possível renovar automaticamente", "可选,留空使用凭据里的 user_name": "Opcional; se vazio, usa o user_name da credencial", "可选,留空使用账号姓名、邮箱或令牌指纹": "Opcional; se vazio, usa o nome, o e-mail ou a impressão digital do token", "可选,留空使用账号昵称或邮箱": "Opcional; se vazio, usa o apelido ou o e-mail da conta", "可选,留空则用 key 尾号": "Opcional; se vazio, usa o final da key", "可选,留空则用 userId": "Opcional; se vazio, usa o userId", "可选,留空则用上游返回的账号名或账号 id": "Opcional; se vazio, usa o nome ou o id da conta retornados pelo upstream", "可选,留空则用凭证里的账号名": "Opcional; se vazio, usa o nome da conta na credencial", "可选,留空则用文件里的昵称": "Opcional; deixe vazio para usar o apelido do arquivo", "可选,留空则用登录名或 uid": "Opcional; se vazio, usa o nome de login ou o uid", "可选,留空则用脱敏手机号": "Opcional; se vazio, usa o celular mascarado", "可选,留空则用脱敏手机号或 userId": "Opcional; se vazio, usa o celular mascarado ou o userId", "可选,留空则用账号 uk": "Opcional; se vazio, usa o uk da conta", "可选,留空则用账号昵称": "Opcional; em branco usa o apelido da conta", "可选,留空则用账号昵称或 userId": "Opcional; deixe em branco para usar o apelido da conta ou o userId", "可选,留空则用邮箱或令牌尾号": "Opcional; se vazio, usa o e-mail ou o final do token", "可选,留空用「OfficeAce 果办」": "Opcional; se vazio, usa “OfficeAce”", "可选,留空自动生成": "Opcional; se vazio, gerado automaticamente", "可选,留空自动用昵称": "Opcional; se vazio, usa o apelido", "可选,给这个访客账号起个备注名": "Opcional; um nome de observação para esta conta de visitante", "可选,续期时带上": "Opcional; enviado na renovação", "可选,讯飞侧 userid": "Opcional; userid do lado iFlytek", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "Opcional; necessário para iniciar uma conversa. Se vazio, o gateway descobre automaticamente nas tarefas existentes da conta; se não encontrar, preencha manualmente depois.", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "Opcional; e-mail da conta, usado para exibição e identificação (a mesma conta é reconhecida mesmo ao trocar por um token novo)", "可选;UUID 形态,与凭据同生共死": "Opcional; formato UUID, vive e morre com a credencial", "可选;填了才能到期自动续期": "Opcional; preencha para renovar automaticamente ao expirar", "可选;用于去重与展示名(留空时网关会问一次上游)": "Opcional; usado para deduplicação e nome de exibição (se vazio, o gateway consulta o upstream uma vez)", "可选;用于生成账号 id 与展示名": "Opcional; usado para gerar o id e o nome de exibição da conta", "可选;纯数字串(上游只收 8–24 位数字)": "Opcional; apenas dígitos (o upstream aceita somente 8–24 dígitos)", "可领取": "Resgatável", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "Contas com chave e sem autenticação podem coexistir no mesmo provedor, cada uma roteada pelas próprias regras; várias contas sem autenticação também são permitidas (cada uma com seu próprio proxy de saída)", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "No mesmo endereço, troque o protocolo para anthropic e ele usará o endpoint compatível com Claude. Para encaminhar, é obrigatório preencher a API Key do OpenCode Go (por assinatura; obter a lista de modelos não exige Key, mas as requisições recebem 401 \"Missing API key\" do upstream)", "响应为空": "Resposta vazia", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "Endpoint compatível com OpenAI do SenseNova; a consulta de saldo usa a conta e a senha do console (veja \"Consulta de saldo\" abaixo)", "国内版": "Edição da China", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "A edição da China e **a edição internacional são dois conjuntos independentes de contas e planos**; as credenciais e os planos resgatados não são compartilhados.", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "A página de login da edição da China não tem acessos Google / GitHub (o login é por WeChat / celular / e-mail)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "O site de login da edição da China é www.accio-ai.com, diferente do site da edição internacional.", "国内版(WorkBuddy)": "Edição da China (WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "O site da China é https://api.siliconflow.cn/v1", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "Site da China (minimaxi.com); o endereço compatível com OpenAI é https://api.minimaxi.com/v1", "国际版": "Edição internacional", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "Plano Coding do z.ai da edição internacional; o endereço compatível com OpenAI é https://api.z.ai/api/coding/paas/v4", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "As edições internacional e da China são **dois conjuntos independentes de contas** (dois sites do mesmo sistema de contas); as credenciais não são compartilhadas.", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "As edições internacional e da China têm sistemas de contas independentes; preencha a credencial da edição internacional. Sem preencher o refreshToken, não é possível renovar automaticamente.", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "A página de login da edição internacional mostra por padrão apenas o login por e-mail; marcar a opção restaura os acessos Google / GitHub / X", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "O site de inferência da edição internacional é api.z.ai, diferente do site da edição da China; os planos também são independentes.", "国际版(WorkBuddy AI)": "Edição internacional (WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "Plano Coding do site internacional; o endereço compatível com OpenAI é https://api.minimax.io/v1", "在 cc-switch 里找到": "Encontradas", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "Conclua o login oficial na janela embutida; em caso de sucesso, a conta entra automaticamente na lista de contas.", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "Gere um PAT nas configurações da conta Qoder do {label} → Integrations (não use um token do Google / GitHub). Contas e credenciais não são compartilhadas entre as duas regiões.", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "Escaneie o QR code do WeChat na página de autorização oficial que abrir (o QR code aparece imediatamente). A conta é adicionada à lista automaticamente após a leitura bem-sucedida.", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "Na janela aberta, entre no site principal do KukuAI com sua conta Baidu (código SMS ou QR code, tanto faz); após o login, a conta entra automaticamente na lista. O gateway troca com o Baidu um token de sessão de negócio do KukuAI (requer o cliente KukuAI instalado nesta máquina).", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "Faça login com sua conta Google na janela que abrir (página de autorização do Antigravity); a conta é adicionada à lista automaticamente quando a autorização for concluída.", "在浏览器中打开登录页": "Abrir a página de login no navegador", "地区": "Região", "填写凭证": "Preencher credenciais", "填写凭证添加": "Preencher credenciais para adicionar", "备注名": "Rótulo", "套餐": "Plano", "如:智谱 GLM": "ex.: Zhipu GLM", "完成登录后自动加入账号列表,昵称取自上游。": "Após concluir o login, a conta entra automaticamente na lista; o apelido vem do upstream.", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "Diretório de credenciais do cliente oficial: Windows — C:\\Users\\\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth; macOS — ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "Crédito confirmado oficialmente", "导入": "Importar", "导入中…": "Importando…", "导入凭证文件": "Importar arquivo de credenciais", "导入失败": "Falha na importação", "导入失败:{reason}": "Falha na importação: {reason}", "导入所选": "Importar selecionados", "导入所选({n})": "Importar selecionados ({n})", "导入桌面端登录态": "Importar sessão de login do desktop", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "A janela embutida será aberta; após a autorização, a conta entra automaticamente na lista de contas. Fechar a janela cancela a espera. No final, a página de autorização pode avisar que não conseguiu abrir o link zcode:// — isso é normal; o resultado já foi registrado no servidor", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "A janela embutida será aberta; após a autorização, a conta entra automaticamente na lista de contas. No painel remoto, é possível colar o endereço de callback. Fechar a janela cancela a espera. O link é válido por 5 minutos; se expirar ou não for clicado, ele é invalidado (você pode iniciar de novo)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "A janela embutida será aberta; após o login, a conta entra automaticamente na lista. Fechar a janela cancela a espera", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "A página de autorização será aberta no navegador padrão do sistema (reaproveitando a conta Trae já conectada nele); na mesma máquina, a conta entra automaticamente ao concluir. Para Docker / painel remoto, cole o endereço de callback da barra de endereços conforme as instruções.", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "A página de autorização será aberta no navegador padrão do sistema (reaproveitando a conta ZCode já conectada nele); após a autorização, a conta entra automaticamente na lista. No final, a página pode avisar que não conseguiu abrir o link zcode://; isso é normal", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "A página de autorização será aberta no navegador padrão do sistema (reaproveitando a conta Huawei Cloud já conectada nele); o gateway consulta a nuvem em polling para obter o código de autorização, então não importa em qual máquina o navegador roda. Ao concluir, a conta entra automaticamente na lista", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "A página de autorização será aberta no navegador padrão do sistema (reaproveitando a conta Huawei Cloud já conectada nele); se o navegador e o gateway não estiverem na mesma máquina, cole o endereço de callback final de volta no painel conforme as instruções acima", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "A página de login será aberta no navegador padrão do sistema (reaproveitando a conta Accio já conectada nele); após o login, a conta entra automaticamente na lista; fechar a janela cancela a espera", "小米 MiMo Token Plan 套餐(新加坡站)": "Plano Token Plan do Xiaomi MiMo (site de Singapura)", "已到账": "Creditado", "已取消登录等待": "Espera de login cancelada", "已取消领取": "Resgate cancelado", "已取消验证码": "Captcha cancelado", "已填写手机号,正在发送验证码…": "Celular preenchido; enviando o código…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "Marcada como sem necessidade de autenticação: a conta é roteada normalmente e nenhum cabeçalho de autenticação é enviado nas requisições de saída", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "{ok} importados, {fail} com falha (os itens com falha estão marcados na lista)", "已建过 · {n} 个账号,点击继续添加": "Já criado · {n} contas, clique para adicionar mais", "已建过,点击继续添加账号": "Já criado, clique para adicionar outra conta", "已打开官方登录页,请在窗口中完成登录…": "Página de login oficial aberta; conclua o login na janela…", "已点发送,等待短信…": "Enviado; aguardando o SMS…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "Página de login aberta no navegador padrão do sistema; conclua o login no navegador…", "已领取,等官方确认": "Resgatado; aguardando confirmação oficial", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "Esta versão do aplicativo não suporta o login web do AutoClaw; atualize o aplicativo", "当前没有可领取的套餐(活动尚未开始)": "Nenhum plano disponível para resgate no momento (a campanha ainda não começou)", "当前环境不支持领取(桥接方法缺失)": "O resgate não é suportado neste ambiente (método de ponte ausente)", "必填,CatPaw 账号标识": "Obrigatório; identificador da conta CatPaw", "恢复 Google / GitHub 入口": "Restaurar acessos Google / GitHub", "手机号": "Celular", "手机验证码登录": "Login com código SMS", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "Abra a página de autorização oficial do Trae SOLO (trae.cn) e entre com sua conta Trae: ao concluir a autorização, a página oficial redireciona de volta para uma porta temporária desta máquina; implantações na mesma máquina recebem automaticamente, e no Docker / painel remoto copie o endereço de callback da barra de endereços conforme as instruções.", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "Abra a página de login oficial do Accio {label} ({site}) e entre com sua conta Accio: após o login, a página oficial redireciona de volta para esta máquina; na mesma máquina tudo se completa automaticamente, e no Docker / painel remoto basta colar o endereço de callback conforme as instruções (o código de autorização é passado ao gateway apenas nesta máquina, e nenhum token em texto claro é exibido na interface).", "打开 Accio {label}登录页": "Abrir a página de login do Accio {label}", "打开 Antigravity 网页登录": "Abrir login web do Antigravity", "打开 CatPaw 网页登录": "Abrir o login web do CatPaw", "打开 Cline 授权页": "Abrir a página de autorização do Cline", "打开 CodeArts 授权页": "Abrir a página de autorização do CodeArts", "打开 Qoder 网页登录": "Abrir o login web do Qoder", "打开 Trae 授权页": "Abrir a página de autorização do Trae", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "Abra a página de autorização oficial do ZCode {label} e entre com sua conta. O resultado da autorização é registrado pelo servidor do ZCode; o gateway busca a credencial em segundo plano e a adiciona à lista de contas.", "打开 ZCode {label}授权页": "Abrir a página de autorização do ZCode {label}", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "Abra a página de autorização oficial do Huawei Cloud CodeArts para entrar: após o login, a página oficial leva o navegador de volta ao /oauth/callback do próprio gateway, e o gateway troca o código de autorização de uso único por credenciais temporárias e adiciona a conta à lista.
    Quando o gateway roda em outra máquina, a interface web pede para colar o endereço de callback final da barra de endereços de volta no painel.", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "Abra a página de autorização do Huawei Cloud e faça login: ao concluir, o gateway consulta a nuvem automaticamente para obter o código de autorização e adiciona a conta à lista (não é preciso instalar o aplicativo de desktop do OfficeAce nem colar manualmente uma URL de retorno).", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "Abra a página de autorização oficial e conclua a autorização por código de dispositivo; a conta usada é do {label} ({site}).", "打开授权页": "Abrir a página de autorização", "打开授权页完成确认,账号自动加入 {label}{note}": "Abra a página de autorização e confirme; a conta entra automaticamente em {label}{note}", "打开方式": "Como abrir", "打开网页登录": "Abrir login web", "探测失败:{message}": "Falha na detecção: {message}", "接入一个兼容上游": "Conectar um upstream compatível", "提交中…": "Enviando…", "搜索提供商": "Buscar provedores", "搜索提供商…": "Buscar provedores…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "Cole o JSON de credencial inteiro gravado pelo plugin oficial / CLIProxyAPI (no formato {\"codearts_provider_credential\":{…}}; a versão achatada também serve).
    Obrigatórios: access_key_id, secret_access_key, security_token.Para renovar automaticamente, é preciso colar também refresh_token e oauth_context — as credenciais temporárias expiram em cerca de uma hora, e sem essa parte não há como renovar; será preciso fazer login de novo.", "文件是{edition}凭证,已按该版本导入": "O arquivo contém credenciais da {edition} e foi importado como tal", "新建自定义提供商": "Novo provedor personalizado", "方案:{label}": "Esquema: {label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "JWT em texto claro ou o valor criptografado enc: do auth.json (descriptografado automaticamente)", "明文 JWT(国际版账号的 access token)": "JWT em texto claro (o access token da conta da edição internacional)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "Plano Coding do bigmodel.cn da Zhipu; obtenha a Key em open.bigmodel.cn/usercenter/apikeys", "未知错误": "Erro desconhecido", "未能获取授权地址,请重试": "Não foi possível obter o endereço de autorização; tente novamente", "未能读取 cc-switch 数据": "Não foi possível ler os dados do cc-switch", "未领取成功": "Resgate não concluído", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "Marque esta opção para upstreams como o Ollama local ou o nível gratuito do OpenCode Zen; caso contrário, a conta não funcionará", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "Este provedor tem duas credenciais que **não se substituem**; preencha as que correspondem aos recursos que você vai usar, pelo menos uma: a API Key do Coding Plan serve para encaminhar inferência (acessa {site}) e para consultar os limites de janela (a porcentagem restante de cada janela de N horas / semanal); o jwt serve para resgatar planos e consultar saldo (acessa o gateway de billing em zcode.z.ai; oficialmente chamado Coding Plan JWT, uma string de três segmentos separados por ponto). As duas consultam saldo, mas leem coisas diferentes: o jwt lê os baldes de saldo e a expiração do plano, enquanto a API Key lê os limites de janela; e o resgate só aceita o jwt, o encaminhamento só aceita a API Key. Preencha a credencial da conta {label} — {plan} (a forma mais fácil: use o \"Login web\" acima — ele troca essa API Key por você e obtém as duas credenciais de uma vez.)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "Endpoint compatível com OpenAI do Ollama local; não precisa de API Key (a opção \"Este upstream não exige autenticação\" já vem marcada e nenhum cabeçalho de autenticação é enviado)", "本次未确认到账": "Crédito não confirmado desta vez", "条可导入": "importáveis", "条配置,其中": "configurações no cc-switch, das quais", "桌面运行时不可用(Tauri 未初始化)": "Runtime do desktop indisponível (Tauri não inicializado)", "模型网关基址": "Endereço base do gateway de modelos", "正在打开百度登录页…": "Abrindo a página de login do Baidu…", "正在扫描本机 cc-switch…": "Escaneando o cc-switch desta máquina…", "正在换发访客凭证…": "Solicitando uma credencial de visitante…", "正在添加…": "Adicionando…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "Aguardando a conclusão do login de {name}; só após concluir ou cancelar você pode iniciar um novo login", "每周": "Semanal", "每日": "Diário", "每月": "Mensal", "没有则无法自动续期": "Sem ele, não é possível renovar automaticamente", "没有匹配「{keyword}」的提供商": "Nenhum provedor corresponde a \"{keyword}\"", "添加 {name} 账号": "Adicionar conta {name}", "添加中…": "Adicionando…", "添加到 ": "Adicionar a ", "添加失败:{reason}": "Falha ao adicionar: {reason}", "添加小浣熊账号": "Adicionar conta Raccoon", "添加方式": "Forma de adicionar", "添加访客账号": "Adicionar uma conta de visitante", "添加账号": "Adicionar conta", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "Plano Coding do Volcano Engine; o endpoint de inferência geral é https://ark.cn-beijing.volces.com/api/v3", "点击添加账号": "Clique para adicionar uma conta", "点开即预填,填 Key 接入": "Abre já preenchido; informe a Key para conectar", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "Após clicar no botão, primeiro passe por uma verificação de slider (controle de risco do provedor); em seguida a página de login abre e a conta é adicionada automaticamente ao concluir o login.
    Esta é a única forma oficial de login da edição internacional; se você já entrou no cliente, \"Importar sessão de login do desktop\" é mais rápido.", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "Entre com o celular vinculado à conta AutoClaw: clique em \"Obter código\", informe o código recebido por SMS abaixo e entre. O código é enviado desta máquina diretamente à API oficial, e nenhum token é exibido na interface.", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "Conclua o login com sua conta CatPaw (Meituan Passport); em caso de sucesso, a conta entra automaticamente na lista.", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "Entre com o celular vinculado à conta Loomy: clique em \"Obter código\" e informe o código. Esta é a forma mais simples neste provedor.", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "Usado para encaminhamento; no formato apiKey.secret, dois segmentos separados por ponto (se vazio, esta conta não pode encaminhar)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "Usado para resgatar planos e consultar saldo; se vazio, esta conta não pode resgatar nem consultar saldo", "用户 ID": "ID do usuário", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "Entre com o celular vinculado: clique em \"Obter código\" e informe o código. Esta é a única forma oficial de login da edição da China.", "留空则用提供商名称": "Se vazio, usa o nome do provedor", "登录 / 添加 {name} 账号": "Entrar / adicionar conta {name}", "登录 session(一长串)": "Sessão de login (uma string longa)", "登录中…": "Entrando…", "登录失败:{message}": "Falha no login: {message}", "登录已结束": "Login encerrado", "登录并添加": "Entrar e adicionar", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "Caminho do arquivo de sessão de login: ~/.box-agent/config/auth.json (Windows: C:\\Users\\\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "Excluir o provedor personalizado \"{name}\"? Isso também excluirá {count} contas desse provedor; a exclusão não pode ser desfeita.", "等待 Accio {label}登录完成…": "Aguardando a conclusão do login do Accio {label}…", "等待 CatPaw 登录完成…": "Aguardando a conclusão do login do CatPaw…", "等待 Cline 授权确认…": "Aguardando a confirmação de autorização do Cline…", "等待 CodeArts 登录完成…": "Aguardando a conclusão do login do CodeArts…", "等待 Google 授权完成…": "Aguardando a conclusão da autorização do Google…", "等待 KukuAI 登录完成…": "Aguardando a conclusão do login do KukuAI…", "等待 OfficeAce 登录完成…": "Aguardando a conclusão do login do OfficeAce…", "等待 OrcaTerm 登录完成…": "Aguardando o login no OrcaTerm…", "等待 Qoder 授权完成…": "Aguardando a conclusão da autorização do Qoder…", "等待 Trae 授权完成…": "Aguardando a conclusão da autorização do Trae…", "等待 ZCode {label}授权完成…": "Aguardando a conclusão da autorização do ZCode {label}…", "等待小浣熊登录完成…": "Aguardando a conclusão do login do Raccoon…", "等待登录完成…": "Aguardando a conclusão do login…", "等待网页登录…": "Aguardando o login web…", "粘贴 API Key": "Colar API Key", "粘贴 Accio 的 accessToken": "Colar o accessToken do Accio", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Cole o Google refresh token do Antigravity (começa com 1//; também pode colar a linha inteira que contém refresh_token=).
    Esta é uma entrada manual além do login web (por exemplo, exportada do IDE oficial em que você já está conectado). O refresh token não expira, e o gateway renova o access token automaticamente ao expirar; se o token for perdido, só resta refazer a autorização do Google, então guarde-o bem.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Cole a API Key do Command Code (começa com user_; obtenha no ~/.commandcode/auth.json do CLI oficial ou no studio web). Colar a linha inteira / com aspas / com o prefixo Bearer funciona; o gateway extrai a key pura sozinho. A key não expira e não há API de renovação, então basta obter uma nova se ela deixar de funcionar. Ao adicionar, o gateway faz uma verificação leve de atividade; uma falha não impede a adição.", "粘贴 Cookie": "Colar Cookie", "粘贴 Google refresh token": "Colar Google refresh token", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "Cole o accessToken OAuth do OrcaTerm (um JWT com três partes separadas por pontos; obtido do data.bin do cliente desktop ou do cookie ot_session da versão web). Também pode colar a linha inteira contendo Bearer / ot_session= — o gateway extrai apenas o token. Após adicionar, o gateway renova automaticamente (o upstream tem API de renovação), sem precisar acompanhar a expiração de 2 horas manualmente.", "粘贴 Qoder 个人访问令牌(pt-…)": "Colar o token de acesso pessoal do Qoder (pt-…)", "粘贴 accessToken": "Colar accessToken", "粘贴 access_token(一长串 JWT)": "Colar o access_token (um JWT longo)", "粘贴 session cookie": "Colar session cookie", "粘贴 token / refreshToken": "Colar token / refreshToken", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "Cole um token começando com workos:… (o prefixo é adicionado automaticamente se faltar)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "Cole um token de acesso do Zhipu Qingyan (um JWT com três partes separadas por ponto). Como obter: abra chatglm.cn no navegador, faça login e copie o valor do cookie chatglm_token em Application → Cookies nas ferramentas de desenvolvedor (colar a linha chatglm_token=…; inteira também funciona). O token é verificado uma vez na origem após a colagem, e a conta só é salva se passar; contas conectadas têm pontos e check-in, e o gateway renova automaticamente depois (a origem tem API de renovação).", "粘贴登录凭据": "Colar credenciais de login", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "O que você cola é a sessão de login (que também é o token do gateway de modelos). O Loomy não tem API de renovação; a sessão vale cerca de 14 dias, então basta entrar de novo após expirar.", "粘贴网关凭据": "Colar credenciais do gateway", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "Cole o valor do cookie de sessão de login web monkeycode_ai_session (copiar o Cookie inteiro no navegador e colar diretamente também funciona; o gateway extrai o valor sozinho).
    {siteNote}
    O MonkeyCode não tem API de renovação: a sessão vale cerca de 30 dias (limite rígido); quando expirar, entre novamente no site e cole mais uma vez.", "粘贴访问令牌": "Cole o token de acesso", "系统浏览器": "Navegador do sistema", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "O navegador do sistema pode reaproveitar a sessão de login existente (recomendado para a edição internacional); a janela embutida é mais limpa.", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "Abre no navegador do sistema (reaproveita a conta Cline já conectada); ao concluir, entra automaticamente na lista", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "Abre no navegador do sistema (reutiliza a conta Google já conectada); ao concluir, entra automaticamente na lista", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "Abre no navegador do sistema (reaproveita a conta Zai / Google já conectada); ao concluir, entra automaticamente na lista", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "Abre no navegador do sistema (reaproveita a conta Meituan já conectada); ao concluir, entra automaticamente na lista", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "Abre no navegador do sistema (reaproveita a conta já conectada); ao concluir, entra automaticamente na lista", "系统默认浏览器": "Navegador padrão do sistema", "编码套餐 API Key": "API Key do Coding Plan", "网关 Secret": "Segredo do gateway", "网页登录": "Login web", "网页登录的打开方式": "Como abrir o login web", "网页登录(Zai / Google)": "Login web (Zai / Google)", "自定义": "Personalizado", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "Painel de agregação próprio: preencha o endereço do seu site. A consulta de saldo chama {base}/v1/usage com a chave de API desta conta; sem configuração extra", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "Painel de agregação próprio: preencha o endereço do seu site; a consulta de saldo precisa também de um token de acesso pessoal do NewAPI (veja \"Consulta de saldo\" abaixo)", "获取风控配置失败,将直接尝试领取:{message}": "Falha ao obter a configuração de controle de risco; tentando resgatar diretamente: {message}", "获取验证码": "Obter código", "访客模式": "Modo visitante", "访客模式(免登录)": "Modo visitante (sem login)", "该上游无需鉴权(不发送鉴权头)": "Este upstream não exige autenticação (nenhum cabeçalho de autenticação é enviado)", "该提供商": "Este provedor", "该提供商账号添加功能即将上线": "A adição de contas deste provedor chega em breve", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "Este provedor personalizado não existe mais (pode ter sido excluído); atualize e tente novamente", "请先选择一个自定义提供商": "Selecione primeiro um provedor personalizado", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "Conclua a verificação no slider exibido (etapa de controle de risco exigida pelo provedor)", "请填写 11 位大陆手机号": "Informe um número de celular da China continental com 11 dígitos", "请填写 6 位数字验证码": "Informe o código de 6 dígitos", "请填写 Base URL": "Preencha a Base URL", "请填写 {label}": "Preencha {label}", "请填写名称": "Preencha o nome", "请完成验证…": "Conclua a verificação…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "Lê e descriptografa %APPDATA%/AutoClaw/auth.json; somente no Windows", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "Lê ~/.cline/data/settings/providers.json; requer login no cliente Cline", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "Lê ~/.meituan-catpaw/auth.json; requer login no cliente CatPaw", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "Lê a sessão de login do cliente KukuAI desta máquina (%APPDATA%\\baidugenflowpro\\Network\\Cookies); requer login no cliente KukuAI", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "Lê o estado de login do cliente OrcaTerm local (%APPDATA%\\com.orcaterm-desktop.app\\data.bin); é preciso estar logado no cliente OrcaTerm", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "Lê o estado de login do cliente 智谱清言 local (%APPDATA%\\chatglm\\Network\\Cookies); o cliente precisa estar conectado", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "Lê a conta atualmente conectada no cliente oficial (Tencent WorkBuddy / WorkBuddy AI) nesta máquina: o arquivo de sessão mais recente no diretório de credenciais é localizado automaticamente (é preciso estar conectado ao cliente oficial nesta máquina). Após a importação, o gateway renova o token automaticamente — não é preciso trocar tokens manualmente conforme a validade de 2 horas.", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "Lê a sessão de login atual do cliente desta máquina (Cookie em texto claro, sem descriptografia). Com o cliente em execução, o arquivo Cookies fica em uso exclusivo; feche o cliente KukuAI antes de importar.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente).", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente). Após entrar novamente no cliente, clique em \"Atualizar Token\" para sincronizar.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente). Após entrar novamente no cliente, basta importar de novo.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente). Usuários que entram no cliente com Zai / Google devem usar esta opção.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente). Esta opção fica em {label}.", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "Lê o token OAuth com que o cliente local está logado (JSON em texto claro, sem descriptografia). Após importar, o gateway renova automaticamente — não é preciso acompanhar a expiração de 2 horas do cliente.", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "Lê o estado de login atual do cliente local. Os cookies do cliente são criptografados com DPAPI (Chromium os_crypt), portanto isto funciona somente no Windows; o arquivo pode ficar ilegível enquanto o cliente está aberto — feche o cliente e tente de novo (ou use \"Preencher credenciais\" para colar um token).", "账号信息": "Informações da conta", "账号信息不完整,请刷新后重试": "Informações da conta incompletas; atualize e tente novamente", "账号已添加,但请留意:{warning}": "Conta adicionada, mas atenção: {warning}", "账号版本": "Edição da conta", "账号类型": "Tipo de conta", "账号:{name}
    ": "Conta: {name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "Usa a rota Inference Providers; crie a Key em hf.co/settings/tokens", "还没有账号": "Ainda não há contas", "这一家当前不支持网页登录,请改用填写凭证": "Este provedor não suporta login web no momento; use \"Preencher credenciais\"", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "Esta conta não tem campanhas com resgate automático no momento (apenas os pontos de brinde do login diário são resgatados automaticamente)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "Esta cota passa pelo canal \"Start Plan\": se o encaminhamento avisar que o Coding Plan expirou, ", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "Aqui é a conta do site da China (monkeycode-ai.com): cole a sessão do site da China. O site internacional (monkeycode-ai.net) é outro provedor, com conta própria; as credenciais não são compartilhadas entre os dois.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "Aqui é a conta do site internacional (monkeycode-ai.net): cole a sessão do site internacional. O site da China (monkeycode-ai.com) é outro provedor, com conta própria; as credenciais não são compartilhadas entre os dois.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Selecione o arquivo de sessão de login auth.json do cliente CatPaw (Windows: C:\\Users\\\\.meituan-catpaw\\auth.json; macOS / Linux: ~/.meituan-catpaw/auth.json). Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente — sem depender mais do cliente desta máquina.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Selecione o arquivo de sessão de login providers.json do cliente Cline (Windows: C:\\Users\\\\.cline\\data\\settings\\providers.json; macOS / Linux: ~/.cline/data/settings/providers.json). Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente — sem depender mais do cliente desta máquina; este registro entra em {label}.", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "Selecione o arquivo Cookies do cliente KukuAI (%APPDATA%\\baidugenflowpro\\Network\\Cookies): é um banco SQLite **binário** (sem extensão, não é JSON). A importação lê uma cópia do arquivo selecionado e não disputa o bloqueio com o cliente em execução, então **não é preciso fechar o cliente antes**. Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente.", "选择凭证文件导入": "Importar de arquivo de credenciais", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "Selecione o arquivo de credenciais de sessão do cliente oficial (workbuddy-desktop.info / workbuddy-desktop-ai.info) ou um JSON de conta exportado pelo wb2api (formato aninhado ou plano).", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Selecione o arquivo de sessão de login auth.json do cliente Raccoon (Windows: C:\\Users\\\\.box-agent\\config\\auth.json; macOS / Linux: ~/.box-agent/config/auth.json). Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente — sem depender mais do cliente desta máquina.", "选择提供商": "Selecionar provedor", "选择的文件不是合法 JSON": "O arquivo selecionado não é um JSON válido", "选择要添加账号的提供商": "Selecione o provedor para adicionar uma conta", "重新扫描": "Escanear novamente", "鉴权": "Autenticação", "阿里云 Token Plan 套餐(国际站)": "Plano Token Plan do Alibaba Cloud (site internacional)", "阿里云百炼 Coding 套餐(国内站)": "Plano Coding do Alibaba Cloud Model Studio (site da China)", "阿里云百炼 Coding 套餐(国际站)": "Plano Coding do Alibaba Cloud Model Studio (site internacional)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "Serviço de modelos Alibaba Cloud Model Studio (site internacional, modo compatível com OpenAI)", "需要图形验证码:登录窗口已弹出,请填写后继续": "Captcha necessário: a janela de login foi aberta; preencha para continuar", "预置 API": "API predefinida", "领取 CodeArts 每日福利": "Resgatar benefício diário do CodeArts", "领取失败:{message}": "Falha ao resgatar: {message}", "领取并让官方确认": "Resgatar e aguardar confirmação oficial", "风控验证配置不完整,请稍后重试": "Configuração de verificação de controle de risco incompleta; tente novamente mais tarde", "验证码": "Código de verificação", "验证码已发送。收到后填入下方并点「登录并添加」": "Código enviado. Informe-o abaixo e clique em \"Entrar e adicionar\"", "验证码已发送,请查看手机短信": "Código enviado; verifique o SMS", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "Código enviado; verifique o SMS. Informe-o abaixo e clique em \"Entrar e adicionar\" para concluir o login", "验证码已发送,请查看短信": "Código enviado; verifique as mensagens", "验证码校验失败,请重试": "Falha na verificação do captcha; tente novamente", "验证码校验超时,请重试": "Tempo esgotado na verificação do captcha; tente novamente", "验证码组件不可用,请重试": "Componente de captcha indisponível; tente novamente", "验证码组件初始化超时,请重试": "Tempo esgotado ao inicializar o componente de captcha; tente novamente", "验证码组件加载失败,请检查网络后重试": "Falha ao carregar o componente de captcha; verifique a rede e tente novamente", "验证码组件加载异常,请重试": "Erro ao carregar o componente de captcha; tente novamente", "验证码组件加载超时,请检查网络后重试": "Tempo esgotado ao carregar o componente de captcha; verifique a rede e tente novamente", "验证码组件未加载,请重启应用后重试": "O componente de captcha não foi carregado; reinicie o aplicativo e tente novamente", "(免费额度池,模型名带 cline-free/ 前缀)。": " (pool de cota gratuita; nomes de modelo com o prefixo cline-free/).", "(其中 {n} 把恢复为不限制)": " ({n} das quais voltaram a ser ilimitadas)", "(必填)": " (obrigatório)", "(有效期 {window})": "(validade {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": " (pool de assinatura; nomes de modelo com o prefixo cline-pass/, e a conta precisa da assinatura correspondente).", ",下一次最快 {minutes} 分钟后": ", próxima tentativa em pelo menos {minutes} min", ",并从 {n} 把 Key 的可用提供商里移除": ", e removido dos provedores permitidos de {n} keys" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · Modelos: {head}{rest}", " 等 {n} 个": " ({n} no total)", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "Google refresh token começando com 1// (também pode colar a linha refresh_token=… inteira)", "11 位大陆手机号": "Celular da China continental (11 dígitos)", "1~64 个字符,账号列表里按它分组显示": "1 a 64 caracteres; na lista de contas, as contas são agrupadas por ele", "6 位数字": "6 dígitos", "

  • 没有可自动领的活动
  • ": "
  • Nenhuma campanha pode ser resgatada automaticamente
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    O que você recebe são pontos de brinde do plano, que não aumentam o pool de tokens dos modelos de benefício; ", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "O endpoint compatível com Anthropic é https://api.deepseek.com/anthropic (preencha-o ao trocar o protocolo para anthropic)", "Anthropic 协议填根地址,不要带 /v1": "No protocolo Anthropic, preencha o endereço raiz, sem /v1", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw edição da China", "AutoClaw 国际版": "AutoClaw edição internacional", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS é obrigatório; cole o **Cookie completo** (um editor de Cookie exporta com um clique) — o **PTOKEN deve ser mantido**, pois o gateway o usa para trocar com o Baidu por um token de sessão de negócio do KukuAI; sem ele, a atualização de modelos reporta \"não conectado\". São aceitos o cabeçalho Cookie inteiro, um array JSON exportado por um editor de Cookie, ou um objeto {BDUSS, STOKEN}. O KukuAI não tem mecanismo de atualização; quando a sessão de login expirar, basta colar de novo.", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=… (ou o JSON exportado por um editor de Cookie)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "X-Passport-Token do CatPaw (Cookie da sessão de login)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Obtenha a API Key do Cline Pass em app.cline.bot (por assinatura); o endpoint é compatível com OpenAI, o catálogo de modelos segue o console da Cline e os nomes dos modelos são adicionados no gerenciamento de modelos como nomes simples, sem prefixo (ex.: glm-5.2 / kimi-k2.7-code / deepseek-v4-pro); o upstream valida o formato do cliente, e os cabeçalhos de requisição do cliente necessários já vêm predefinidos neste cartão", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT (três segmentos separados por ponto)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT (três partes separadas por pontos; também pode colar a linha Bearer inteira ou o conteúdo do data.bin)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT (três partes separadas por ponto; colar a linha chatglm_token=… inteira também funciona)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode edição internacional", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "Endpoint gerenciado do NVIDIA NIM; solicite a Key em integrate.api.nvidia.com", "OfficeAce 果办": "OfficeAce", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken é a credencial de login do Accio (um token opaco bem longo, não é JWT); refreshToken é opcional e, se preenchido, permite renovação automática ao expirar. Preencha a credencial da conta {label} — {siteNote} (a forma mais fácil de obter: use o \"Login web\" acima; não é preciso procurar o token manualmente.)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken é o Cloud-IDE-JWT do Trae (três segmentos separados por ponto) e o refreshToken serve para renovação automática ao expirar (este provedor troca o refreshToken a cada uso: assim que é trocado, o antigo é invalidado, então não atualize a mesma conta em dois programas ao mesmo tempo).
    Ao colar manualmente, preencha também machineId / deviceId: o upstream os vincula à chave pública do dispositivo enviada no login para identificar o dispositivo, e inventar um novo par dispara a família de rejeições de vínculo de dispositivo 2xxxx.
    Sem esses três itens, o caminho correto é o \"Login web\" acima; em contêiner / implantação remota, basta colar o endereço de callback da barra de endereços conforme as instruções.", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "O valor de monkeycode_ai_session (também pode colar o Cookie inteiro)", "ms- 开头的 API 令牌": "Token de API começando com ms-", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken é opcional e, se preenchido, permite renovação automática ao expirar; ambos podem ser obtidos do arquivo de sessão de login do cliente Raccoon.", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken é opcional e, se preenchido, permite renovação automática; ambos podem ser obtidos do arquivo de sessão de login do cliente. A mesma conta Cline funciona nos dois pools; aqui ela entra em {label}.", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "O token aceita o prefixo enc: (descriptografado automaticamente no Windows). Sem preencher o refreshToken, não é possível renovar automaticamente.", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "O token é o Cookie da sessão de login; o CatPaw não tem mecanismo de atualização, então faça login novamente no cliente após expirar.", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "API Key começando com user_ (também pode colar a linha Authorization: Bearer … inteira)", "{label} 网页登录的打开方式": "Como abrir o login web de {label}", "{label} 账号地区": "Região da conta {label}", "{label} 账号的添加方式": "Como adicionar uma conta {label}", "{name} 不是合法 JSON:{reason}": "{name} não é um JSON válido: {reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name}: cole um objeto JSON (no formato {sample})", "{n} 个账号": "{n} contas", "{n} 个账号,点击添加": "{n} contas, clique para adicionar", "{seconds}s 后重发": "Reenviar em {seconds}s", "✅ {label}账号已添加": "✅ Conta {label} adicionada", "✅ {label}账号已添加{name}": "✅ Conta {label} adicionada{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ {n} provedores importados do cc-switch", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ Provedor personalizado \"{name}\" criado e conta adicionada", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ Provedor personalizado \"{name}\" excluído{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ Conta existente{name} atualizada (apenas uma conta por chave de API; adições repetidas são mescladas)", "✅ 登录成功,{edition}账号已加入列表": "✅ Login concluído; conta {edition} adicionada à lista", "✅ 领取成功:{planId}{period}": "✅ Resgate concluído: {planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " Um mesmo provedor pode ter várias keys, rotacionadas por prioridade.", "「{name}」的账号添加功能还在开发中,敬请期待。": "A adição de contas para \"{name}\" ainda está em desenvolvimento; aguarde novidades.", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "Uma única Key serve para vários fornecedores; use o nome completo \"fornecedor/modelo\" (ex.: deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "Deixe em branco quando o upstream não exigir autenticação e marque a opção abaixo (em branco e sem marcar é tratado como credencial não configurada)", "上游信息": "Informações do upstream", "不可领({status})": "Não resgatável ({status})", "不支持导入": "Importação não suportada", "不是有效的凭证文件:内容要是一个 JSON 对象": "Não é um arquivo de credenciais válido: o conteúdo deve ser um objeto JSON", "不是有效的凭证文件:需要包含 accessToken 与 uid": "Não é um arquivo de credenciais válido: accessToken e uid são obrigatórios", "不是自定义提供商": "Não é um provedor personalizado", "不需要 Key:转发与拉取模型都不发送鉴权头": "Não precisa de Key: nem o encaminhamento nem a busca de modelos enviam cabeçalhos de autenticação", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "Não é preciso fazer login: clique no botão abaixo e o gateway vai obter uma credencial de visitante diretamente do Zhipu Qingyan e adicioná-la à lista de contas (você pode preencher um nome de observação antes). A credencial de visitante pode ser usada para conversar imediatamente; a cota gratuita é emitida pela origem por dispositivo.

    Atenção: uma conta de visitante não tem sistema de pontos — as interfaces de pontos de membro, pontos de login diário e resgate de atividades exigem login, então esses recursos são ignorados para visitantes (nenhuma leitura aparece na página de contas nem na central de check-in). Para obter pontos, use \"Preencher credenciais\" para colar o token de uma conta conectada, ou \"Importar estado de login do desktop\".", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "As contas das duas edições podem ser salvas ao mesmo tempo, cada uma com sua própria lista de modelos (as edições da China e internacional são dois provedores, que podem ser ativados e mapeados separadamente).", "中国版": "Edição da China", "今天没有需要领的活动(都已到账)": "Hoje não há campanhas para resgatar (todas já creditadas)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "Hoje (horário de Pequim, {day}) você já tentou {attempts} vezes; restam {left} tentativas{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "Pegue três itens de outra máquina (ou do models.json do aplicativo de desktop do OfficeAce) e cole aqui: o endereço base do gateway de modelos (baseUrl, no formato https://modelgw-…/v2) e modelAppKey / modelAppSecret. Esses três já bastam para encaminhar requisições (a credencial do gateway não expira); as credenciais temporárias do plano de controle (accessKeyId etc.) são opcionais — se ficarem em branco, a consulta de saldo e a renovação automática ficam indisponíveis, mas o encaminhamento não é afetado.", "从本机导入桌面端登录态": "Importar sessão de login do desktop desta máquina", "任务镜像 id": "id da imagem da tarefa", "余额查询": "Consulta de saldo", "使用 Google 账号登录": "Entrar com conta Google", "使用 Zai 账号登录": "Entrar com conta Zai", "使用个人访问令牌(PAT)": "Usar token de acesso pessoal (PAT)", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "Modelos gratuitos não precisam de Key (a opção \"Este upstream não exige autenticação\" já vem marcada e o gateway usa credenciais anônimas automaticamente); para modelos pagos, preencha a API Key do Zen. O nível gratuito do upstream só aceita o formato do cliente oficial, e a opção \"Simular o cliente oficial do OpenCode\" já vem ativada", "内嵌窗口": "Janela embutida", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "Abre na janela embutida; fechar a janela cancela a espera (se a conta Google for recusada, use o navegador do sistema)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "Abre na janela embutida; ao concluir, entra automaticamente na lista; fechar a janela cancela a espera", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "Abre em uma janela incorporada; a conta é adicionada automaticamente após o escaneamento — fechar a janela cancela a espera", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "A janela embutida usa um ambiente totalmente novo, então várias contas não interferem entre si; fechar a janela cancela a espera", "内嵌窗口(推荐)": "Janela embutida (recomendado)", "准备验证…": "Preparando a verificação…", "凭据 JSON": "JSON da credencial", "凭证文件在哪?": "Onde fica o arquivo de credenciais?", "创建并添加账号": "Criar e adicionar conta", "创建这个提供商,并同时建立它的第一个账号。": "Crie este provedor e, ao mesmo tempo, sua primeira conta.", "删除功能不可用(脚本未就绪)": "Exclusão indisponível (script não está pronto)", "删除失败:{reason}": "Falha ao excluir: {reason}", "删除此提供商": "Excluir este provedor", "及 {n} 个账号": " e {n} contas", "发送中…": "Enviando…", "发送失败:{message}": "Falha ao enviar: {message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "Envio não confirmado: a janela de login foi aberta; conclua o login manualmente nessa janela", "取消失败:{message}": "Falha ao cancelar: {message}", "取消等待": "Cancelar espera", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "Somente a \"Janela embutida\" pode restaurar os acessos de terceiros: no navegador do sistema não podemos alterar a página de login", "可选": "Opcional", "可选(cloudaicompanionProject):留空由网关自动发现": "Opcional (cloudaicompanionProject); se vazio, o gateway descobre automaticamente", "可选,展示用": "Opcional, para exibição", "可选,没有则无法自动续期": "Opcional; sem ele, não é possível renovar automaticamente", "可选,留空使用凭据里的 user_name": "Opcional; se vazio, usa o user_name da credencial", "可选,留空使用账号姓名、邮箱或令牌指纹": "Opcional; se vazio, usa o nome, o e-mail ou a impressão digital do token", "可选,留空使用账号昵称或邮箱": "Opcional; se vazio, usa o apelido ou o e-mail da conta", "可选,留空则用 key 尾号": "Opcional; se vazio, usa o final da key", "可选,留空则用 userId": "Opcional; se vazio, usa o userId", "可选,留空则用上游账号昵称": "Opcional; se deixado em branco, o apelido da conta upstream é usado", "可选,留空则用上游返回的账号名或账号 id": "Opcional; se vazio, usa o nome ou o id da conta retornados pelo upstream", "可选,留空则用凭证里的账号名": "Opcional; se vazio, usa o nome da conta na credencial", "可选,留空则用文件里的昵称": "Opcional; deixe vazio para usar o apelido do arquivo", "可选,留空则用登录名或 uid": "Opcional; se vazio, usa o nome de login ou o uid", "可选,留空则用脱敏手机号": "Opcional; se vazio, usa o celular mascarado", "可选,留空则用脱敏手机号或 userId": "Opcional; se vazio, usa o celular mascarado ou o userId", "可选,留空则用账号 uk": "Opcional; se vazio, usa o uk da conta", "可选,留空则用账号昵称": "Opcional; em branco usa o apelido da conta", "可选,留空则用账号昵称或 userId": "Opcional; deixe em branco para usar o apelido da conta ou o userId", "可选,留空则用邮箱或令牌尾号": "Opcional; se vazio, usa o e-mail ou o final do token", "可选,留空用「OfficeAce 果办」": "Opcional; se vazio, usa “OfficeAce”", "可选,留空自动生成": "Opcional; se vazio, gerado automaticamente", "可选,留空自动用昵称": "Opcional; se vazio, usa o apelido", "可选,给这个访客账号起个备注名": "Opcional; um nome de observação para esta conta de visitante", "可选,续期时带上": "Opcional; enviado na renovação", "可选,讯飞侧 userid": "Opcional; userid do lado iFlytek", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "Opcional; necessário para iniciar uma conversa. Se vazio, o gateway descobre automaticamente nas tarefas existentes da conta; se não encontrar, preencha manualmente depois.", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "Opcional; e-mail da conta, usado para exibição e identificação (a mesma conta é reconhecida mesmo ao trocar por um token novo)", "可选;UUID 形态,与凭据同生共死": "Opcional; formato UUID, vive e morre com a credencial", "可选;填了才能到期自动续期": "Opcional; preencha para renovar automaticamente ao expirar", "可选;用于去重与展示名(留空时网关会问一次上游)": "Opcional; usado para deduplicação e nome de exibição (se vazio, o gateway consulta o upstream uma vez)", "可选;用于生成账号 id 与展示名": "Opcional; usado para gerar o id e o nome de exibição da conta", "可选;纯数字串(上游只收 8–24 位数字)": "Opcional; apenas dígitos (o upstream aceita somente 8–24 dígitos)", "可领取": "Resgatável", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "Contas com chave e sem autenticação podem coexistir no mesmo provedor, cada uma roteada pelas próprias regras; várias contas sem autenticação também são permitidas (cada uma com seu próprio proxy de saída)", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "No mesmo endereço, troque o protocolo para anthropic e ele usará o endpoint compatível com Claude. Para encaminhar, é obrigatório preencher a API Key do OpenCode Go (por assinatura; obter a lista de modelos não exige Key, mas as requisições recebem 401 \"Missing API key\" do upstream)", "响应为空": "Resposta vazia", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "Endpoint compatível com OpenAI do SenseNova; a consulta de saldo usa a conta e a senha do console (veja \"Consulta de saldo\" abaixo)", "国内版": "Edição da China", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "A edição da China e **a edição internacional são dois conjuntos independentes de contas e planos**; as credenciais e os planos resgatados não são compartilhados.", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "A página de login da edição da China não tem acessos Google / GitHub (o login é por WeChat / celular / e-mail)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "O site de login da edição da China é www.accio-ai.com, diferente do site da edição internacional.", "国内版(WorkBuddy)": "Edição da China (WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "O site da China é https://api.siliconflow.cn/v1", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "Site da China (minimaxi.com); o endereço compatível com OpenAI é https://api.minimaxi.com/v1", "国际版": "Edição internacional", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "Plano Coding do z.ai da edição internacional; o endereço compatível com OpenAI é https://api.z.ai/api/coding/paas/v4", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "As edições internacional e da China são **dois conjuntos independentes de contas** (dois sites do mesmo sistema de contas); as credenciais não são compartilhadas.", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "As edições internacional e da China têm sistemas de contas independentes; preencha a credencial da edição internacional. Sem preencher o refreshToken, não é possível renovar automaticamente.", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "A página de login da edição internacional mostra por padrão apenas o login por e-mail; marcar a opção restaura os acessos Google / GitHub / X", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "O site de inferência da edição internacional é api.z.ai, diferente do site da edição da China; os planos também são independentes.", "国际版(WorkBuddy AI)": "Edição internacional (WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "Plano Coding do site internacional; o endereço compatível com OpenAI é https://api.minimax.io/v1", "在 cc-switch 里找到": "Encontradas", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "Conclua o login oficial na janela embutida; em caso de sucesso, a conta entra automaticamente na lista de contas.", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "Gere um PAT nas configurações da conta Qoder do {label} → Integrations (não use um token do Google / GitHub). Contas e credenciais não são compartilhadas entre as duas regiões.", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "Escaneie o QR code do WeChat na página de autorização oficial que abrir (o QR code aparece imediatamente). A conta é adicionada à lista automaticamente após a leitura bem-sucedida.", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "Na janela aberta, entre no site principal do KukuAI com sua conta Baidu (código SMS ou QR code, tanto faz); após o login, a conta entra automaticamente na lista. O gateway troca com o Baidu um token de sessão de negócio do KukuAI (requer o cliente KukuAI instalado nesta máquina).", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "Faça login com sua conta Google na janela que abrir (página de autorização do Antigravity); a conta é adicionada à lista automaticamente quando a autorização for concluída.", "在浏览器中打开登录页": "Abrir a página de login no navegador", "地区": "Região", "填写凭证": "Preencher credenciais", "填写凭证添加": "Preencher credenciais para adicionar", "备注名": "Rótulo", "套餐": "Plano", "如:智谱 GLM": "ex.: Zhipu GLM", "完成登录后自动加入账号列表,昵称取自上游。": "Após concluir o login, a conta entra automaticamente na lista; o apelido vem do upstream.", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "Diretório de credenciais do cliente oficial: Windows — C:\\Users\\\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth; macOS — ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "Crédito confirmado oficialmente", "导入": "Importar", "导入中…": "Importando…", "导入凭证文件": "Importar arquivo de credenciais", "导入失败": "Falha na importação", "导入失败:{reason}": "Falha na importação: {reason}", "导入所选": "Importar selecionados", "导入所选({n})": "Importar selecionados ({n})", "导入桌面端登录态": "Importar sessão de login do desktop", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "A janela embutida será aberta; após a autorização, a conta entra automaticamente na lista de contas. Fechar a janela cancela a espera. No final, a página de autorização pode avisar que não conseguiu abrir o link zcode:// — isso é normal; o resultado já foi registrado no servidor", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "A janela embutida será aberta; após a autorização, a conta entra automaticamente na lista de contas. No painel remoto, é possível colar o endereço de callback. Fechar a janela cancela a espera. O link é válido por 5 minutos; se expirar ou não for clicado, ele é invalidado (você pode iniciar de novo)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "A janela embutida será aberta; após o login, a conta entra automaticamente na lista. Fechar a janela cancela a espera", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "A página de autorização será aberta no navegador padrão do sistema (reaproveitando a conta Trae já conectada nele); na mesma máquina, a conta entra automaticamente ao concluir. Para Docker / painel remoto, cole o endereço de callback da barra de endereços conforme as instruções.", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "A página de autorização será aberta no navegador padrão do sistema (reaproveitando a conta ZCode já conectada nele); após a autorização, a conta entra automaticamente na lista. No final, a página pode avisar que não conseguiu abrir o link zcode://; isso é normal", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "A página de autorização será aberta no navegador padrão do sistema (reaproveitando a conta Huawei Cloud já conectada nele); o gateway consulta a nuvem em polling para obter o código de autorização, então não importa em qual máquina o navegador roda. Ao concluir, a conta entra automaticamente na lista", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "A página de autorização será aberta no navegador padrão do sistema (reaproveitando a conta Huawei Cloud já conectada nele); se o navegador e o gateway não estiverem na mesma máquina, cole o endereço de callback final de volta no painel conforme as instruções acima", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "A página de login será aberta no navegador padrão do sistema (reaproveitando a conta Accio já conectada nele); após o login, a conta entra automaticamente na lista; fechar a janela cancela a espera", "小米 MiMo Token Plan 套餐(新加坡站)": "Plano Token Plan do Xiaomi MiMo (site de Singapura)", "已到账": "Creditado", "已取消登录等待": "Espera de login cancelada", "已取消领取": "Resgate cancelado", "已取消验证码": "Captcha cancelado", "已填写手机号,正在发送验证码…": "Celular preenchido; enviando o código…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "Marcada como sem necessidade de autenticação: a conta é roteada normalmente e nenhum cabeçalho de autenticação é enviado nas requisições de saída", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "{ok} importados, {fail} com falha (os itens com falha estão marcados na lista)", "已建过 · {n} 个账号,点击继续添加": "Já criado · {n} contas, clique para adicionar mais", "已建过,点击继续添加账号": "Já criado, clique para adicionar outra conta", "已打开官方登录页,请在窗口中完成登录…": "Página de login oficial aberta; conclua o login na janela…", "已点发送,等待短信…": "Enviado; aguardando o SMS…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "Página de login aberta no navegador padrão do sistema; conclua o login no navegador…", "已领取,等官方确认": "Resgatado; aguardando confirmação oficial", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "Esta versão do aplicativo não suporta o login web do AutoClaw; atualize o aplicativo", "当前没有可领取的套餐(活动尚未开始)": "Nenhum plano disponível para resgate no momento (a campanha ainda não começou)", "当前环境不支持领取(桥接方法缺失)": "O resgate não é suportado neste ambiente (método de ponte ausente)", "必填,CatPaw 账号标识": "Obrigatório; identificador da conta CatPaw", "恢复 Google / GitHub 入口": "Restaurar acessos Google / GitHub", "手机号": "Celular", "手机验证码登录": "Login com código SMS", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "Abra a página de autorização oficial do Trae SOLO (trae.cn) e entre com sua conta Trae: ao concluir a autorização, a página oficial redireciona de volta para uma porta temporária desta máquina; implantações na mesma máquina recebem automaticamente, e no Docker / painel remoto copie o endereço de callback da barra de endereços conforme as instruções.", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "Abra a página de login oficial do Accio {label} ({site}) e entre com sua conta Accio: após o login, a página oficial redireciona de volta para esta máquina; na mesma máquina tudo se completa automaticamente, e no Docker / painel remoto basta colar o endereço de callback conforme as instruções (o código de autorização é passado ao gateway apenas nesta máquina, e nenhum token em texto claro é exibido na interface).", "打开 Accio {label}登录页": "Abrir a página de login do Accio {label}", "打开 Antigravity 网页登录": "Abrir login web do Antigravity", "打开 CatPaw 网页登录": "Abrir o login web do CatPaw", "打开 Cline 授权页": "Abrir a página de autorização do Cline", "打开 CodeArts 授权页": "Abrir a página de autorização do CodeArts", "打开 Qoder 网页登录": "Abrir o login web do Qoder", "打开 Trae 授权页": "Abrir a página de autorização do Trae", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "Abra a página de autorização oficial do ZCode {label} e entre com sua conta. O resultado da autorização é registrado pelo servidor do ZCode; o gateway busca a credencial em segundo plano e a adiciona à lista de contas.", "打开 ZCode {label}授权页": "Abrir a página de autorização do ZCode {label}", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "Abra a página de autorização oficial do Huawei Cloud CodeArts para entrar: após o login, a página oficial leva o navegador de volta ao /oauth/callback do próprio gateway, e o gateway troca o código de autorização de uso único por credenciais temporárias e adiciona a conta à lista.
    Quando o gateway roda em outra máquina, a interface web pede para colar o endereço de callback final da barra de endereços de volta no painel.", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "Abra a página de autorização do Huawei Cloud e faça login: ao concluir, o gateway consulta a nuvem automaticamente para obter o código de autorização e adiciona a conta à lista (não é preciso instalar o aplicativo de desktop do OfficeAce nem colar manualmente uma URL de retorno).", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "Abra a página de autorização oficial e conclua a autorização por código de dispositivo; a conta usada é do {label} ({site}).", "打开授权页": "Abrir a página de autorização", "打开授权页完成确认,账号自动加入 {label}{note}": "Abra a página de autorização e confirme; a conta entra automaticamente em {label}{note}", "打开方式": "Como abrir", "打开网页登录": "Abrir login web", "探测失败:{message}": "Falha na detecção: {message}", "接入一个兼容上游": "Conectar um upstream compatível", "提交中…": "Enviando…", "搜索提供商": "Buscar provedores", "搜索提供商…": "Buscar provedores…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "Cole o JSON de credencial inteiro gravado pelo plugin oficial / CLIProxyAPI (no formato {\"codearts_provider_credential\":{…}}; a versão achatada também serve).
    Obrigatórios: access_key_id, secret_access_key, security_token.Para renovar automaticamente, é preciso colar também refresh_token e oauth_context — as credenciais temporárias expiram em cerca de uma hora, e sem essa parte não há como renovar; será preciso fazer login de novo.", "文件是{edition}凭证,已按该版本导入": "O arquivo contém credenciais da {edition} e foi importado como tal", "新建自定义提供商": "Novo provedor personalizado", "方案:{label}": "Esquema: {label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "JWT em texto claro ou o valor criptografado enc: do auth.json (descriptografado automaticamente)", "明文 JWT(国际版账号的 access token)": "JWT em texto claro (o access token da conta da edição internacional)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "Plano Coding do bigmodel.cn da Zhipu; obtenha a Key em open.bigmodel.cn/usercenter/apikeys", "未知错误": "Erro desconhecido", "未能获取授权地址,请重试": "Não foi possível obter o endereço de autorização; tente novamente", "未能读取 cc-switch 数据": "Não foi possível ler os dados do cc-switch", "未领取成功": "Resgate não concluído", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "Marque esta opção para upstreams como o Ollama local ou o nível gratuito do OpenCode Zen; caso contrário, a conta não funcionará", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "Este provedor tem duas credenciais que **não se substituem**; preencha as que correspondem aos recursos que você vai usar, pelo menos uma: a API Key do Coding Plan serve para encaminhar inferência (acessa {site}) e para consultar os limites de janela (a porcentagem restante de cada janela de N horas / semanal); o jwt serve para resgatar planos e consultar saldo (acessa o gateway de billing em zcode.z.ai; oficialmente chamado Coding Plan JWT, uma string de três segmentos separados por ponto). As duas consultam saldo, mas leem coisas diferentes: o jwt lê os baldes de saldo e a expiração do plano, enquanto a API Key lê os limites de janela; e o resgate só aceita o jwt, o encaminhamento só aceita a API Key. Preencha a credencial da conta {label} — {plan} (a forma mais fácil: use o \"Login web\" acima — ele troca essa API Key por você e obtém as duas credenciais de uma vez.)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "Endpoint compatível com OpenAI do Ollama local; não precisa de API Key (a opção \"Este upstream não exige autenticação\" já vem marcada e nenhum cabeçalho de autenticação é enviado)", "本次未确认到账": "Crédito não confirmado desta vez", "条可导入": "importáveis", "条配置,其中": "configurações no cc-switch, das quais", "桌面运行时不可用(Tauri 未初始化)": "Runtime do desktop indisponível (Tauri não inicializado)", "模型网关基址": "Endereço base do gateway de modelos", "正在打开百度登录页…": "Abrindo a página de login do Baidu…", "正在扫描本机 cc-switch…": "Escaneando o cc-switch desta máquina…", "正在换发访客凭证…": "Solicitando uma credencial de visitante…", "正在添加…": "Adicionando…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "Aguardando a conclusão do login de {name}; só após concluir ou cancelar você pode iniciar um novo login", "每周": "Semanal", "每日": "Diário", "每月": "Mensal", "没有则无法自动续期": "Sem ele, não é possível renovar automaticamente", "没有匹配「{keyword}」的提供商": "Nenhum provedor corresponde a \"{keyword}\"", "添加 {name} 账号": "Adicionar conta {name}", "添加中…": "Adicionando…", "添加到 ": "Adicionar a ", "添加失败:{reason}": "Falha ao adicionar: {reason}", "添加小浣熊账号": "Adicionar conta Raccoon", "添加方式": "Forma de adicionar", "添加访客账号": "Adicionar uma conta de visitante", "添加账号": "Adicionar conta", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "Plano Coding do Volcano Engine; o endpoint de inferência geral é https://ark.cn-beijing.volces.com/api/v3", "点击添加账号": "Clique para adicionar uma conta", "点开即预填,填 Key 接入": "Abre já preenchido; informe a Key para conectar", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "Após clicar no botão, primeiro passe por uma verificação de slider (controle de risco do provedor); em seguida a página de login abre e a conta é adicionada automaticamente ao concluir o login.
    Esta é a única forma oficial de login da edição internacional; se você já entrou no cliente, \"Importar sessão de login do desktop\" é mais rápido.", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "Entre com o celular vinculado à conta AutoClaw: clique em \"Obter código\", informe o código recebido por SMS abaixo e entre. O código é enviado desta máquina diretamente à API oficial, e nenhum token é exibido na interface.", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "Conclua o login com sua conta CatPaw (Meituan Passport); em caso de sucesso, a conta entra automaticamente na lista.", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "Entre com o celular vinculado à conta Loomy: clique em \"Obter código\" e informe o código. Esta é a forma mais simples neste provedor.", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "Usado para encaminhamento; no formato apiKey.secret, dois segmentos separados por ponto (se vazio, esta conta não pode encaminhar)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "Usado para resgatar planos e consultar saldo; se vazio, esta conta não pode resgatar nem consultar saldo", "用户 ID": "ID do usuário", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "Entre com o celular vinculado: clique em \"Obter código\" e informe o código. Esta é a única forma oficial de login da edição da China.", "留空则用提供商名称": "Se vazio, usa o nome do provedor", "登录 / 添加 {name} 账号": "Entrar / adicionar conta {name}", "登录 session(一长串)": "Sessão de login (uma string longa)", "登录中…": "Entrando…", "登录失败:{message}": "Falha no login: {message}", "登录已结束": "Login encerrado", "登录并添加": "Entrar e adicionar", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "Caminho do arquivo de sessão de login: ~/.box-agent/config/auth.json (Windows: C:\\Users\\\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "Excluir o provedor personalizado \"{name}\"? Isso também excluirá {count} contas desse provedor; a exclusão não pode ser desfeita.", "等待 Accio {label}登录完成…": "Aguardando a conclusão do login do Accio {label}…", "等待 CatPaw 登录完成…": "Aguardando a conclusão do login do CatPaw…", "等待 Cline 授权确认…": "Aguardando a confirmação de autorização do Cline…", "等待 CodeArts 登录完成…": "Aguardando a conclusão do login do CodeArts…", "等待 Google 授权完成…": "Aguardando a conclusão da autorização do Google…", "等待 KukuAI 登录完成…": "Aguardando a conclusão do login do KukuAI…", "等待 OfficeAce 登录完成…": "Aguardando a conclusão do login do OfficeAce…", "等待 OrcaTerm 登录完成…": "Aguardando o login no OrcaTerm…", "等待 Qoder 授权完成…": "Aguardando a conclusão da autorização do Qoder…", "等待 Trae 授权完成…": "Aguardando a conclusão da autorização do Trae…", "等待 ZCode {label}授权完成…": "Aguardando a conclusão da autorização do ZCode {label}…", "等待小浣熊登录完成…": "Aguardando a conclusão do login do Raccoon…", "等待登录完成…": "Aguardando a conclusão do login…", "等待网页登录…": "Aguardando o login web…", "粘贴 API Key": "Colar API Key", "粘贴 API 令牌": "Colar token de API", "粘贴 Accio 的 accessToken": "Colar o accessToken do Accio", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "Cole o Google refresh token do Antigravity (começa com 1//; também pode colar a linha inteira que contém refresh_token=).
    Esta é uma entrada manual além do login web (por exemplo, exportada do IDE oficial em que você já está conectado). O refresh token não expira, e o gateway renova o access token automaticamente ao expirar; se o token for perdido, só resta refazer a autorização do Google, então guarde-o bem.", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "Cole a API Key do Command Code (começa com user_; obtenha no ~/.commandcode/auth.json do CLI oficial ou no studio web). Colar a linha inteira / com aspas / com o prefixo Bearer funciona; o gateway extrai a key pura sozinho. A key não expira e não há API de renovação, então basta obter uma nova se ela deixar de funcionar. Ao adicionar, o gateway faz uma verificação leve de atividade; uma falha não impede a adição.", "粘贴 Cookie": "Colar Cookie", "粘贴 Google refresh token": "Colar Google refresh token", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "Cole o accessToken OAuth do OrcaTerm (um JWT com três partes separadas por pontos; obtido do data.bin do cliente desktop ou do cookie ot_session da versão web). Também pode colar a linha inteira contendo Bearer / ot_session= — o gateway extrai apenas o token. Após adicionar, o gateway renova automaticamente (o upstream tem API de renovação), sem precisar acompanhar a expiração de 2 horas manualmente.", "粘贴 Qoder 个人访问令牌(pt-…)": "Colar o token de acesso pessoal do Qoder (pt-…)", "粘贴 accessToken": "Colar accessToken", "粘贴 access_token(一长串 JWT)": "Colar o access_token (um JWT longo)", "粘贴 session cookie": "Colar session cookie", "粘贴 token / refreshToken": "Colar token / refreshToken", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "Cole um token começando com workos:… (o prefixo é adicionado automaticamente se faltar)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "Cole um token de acesso do Zhipu Qingyan (um JWT com três partes separadas por ponto). Como obter: abra chatglm.cn no navegador, faça login e copie o valor do cookie chatglm_token em Application → Cookies nas ferramentas de desenvolvedor (colar a linha chatglm_token=…; inteira também funciona). O token é verificado uma vez na origem após a colagem, e a conta só é salva se passar; contas conectadas têm pontos e check-in, e o gateway renova automaticamente depois (a origem tem API de renovação).", "粘贴登录凭据": "Colar credenciais de login", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "O que você cola é a sessão de login (que também é o token do gateway de modelos). O Loomy não tem API de renovação; a sessão vale cerca de 14 dias, então basta entrar de novo após expirar.", "粘贴网关凭据": "Colar credenciais do gateway", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "Cole o valor do cookie de sessão de login web monkeycode_ai_session (copiar o Cookie inteiro no navegador e colar diretamente também funciona; o gateway extrai o valor sozinho).
    {siteNote}
    O MonkeyCode não tem API de renovação: a sessão vale cerca de 30 dias (limite rígido); quando expirar, entre novamente no site e cole mais uma vez.", "粘贴访问令牌": "Cole o token de acesso", "系统浏览器": "Navegador do sistema", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "O navegador do sistema pode reaproveitar a sessão de login existente (recomendado para a edição internacional); a janela embutida é mais limpa.", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "Abre no navegador do sistema (reaproveita a conta Cline já conectada); ao concluir, entra automaticamente na lista", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "Abre no navegador do sistema (reutiliza a conta Google já conectada); ao concluir, entra automaticamente na lista", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "Abre no navegador do sistema (reaproveita a conta Zai / Google já conectada); ao concluir, entra automaticamente na lista", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "Abre no navegador do sistema (reaproveita a conta Meituan já conectada); ao concluir, entra automaticamente na lista", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "Abre no navegador do sistema (reaproveita a conta já conectada); ao concluir, entra automaticamente na lista", "系统默认浏览器": "Navegador padrão do sistema", "编码套餐 API Key": "API Key do Coding Plan", "网关 Secret": "Segredo do gateway", "网页登录": "Login web", "网页登录的打开方式": "Como abrir o login web", "网页登录(Zai / Google)": "Login web (Zai / Google)", "自定义": "Personalizado", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "Painel de agregação próprio: preencha o endereço do seu site. A consulta de saldo chama {base}/v1/usage com a chave de API desta conta; sem configuração extra", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "Painel de agregação próprio: preencha o endereço do seu site; a consulta de saldo precisa também de um token de acesso pessoal do NewAPI (veja \"Consulta de saldo\" abaixo)", "获取风控配置失败,将直接尝试领取:{message}": "Falha ao obter a configuração de controle de risco; tentando resgatar diretamente: {message}", "获取验证码": "Obter código", "访客模式": "Modo visitante", "访客模式(免登录)": "Modo visitante (sem login)", "该上游无需鉴权(不发送鉴权头)": "Este upstream não exige autenticação (nenhum cabeçalho de autenticação é enviado)", "该提供商": "Este provedor", "该提供商账号添加功能即将上线": "A adição de contas deste provedor chega em breve", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "Este provedor personalizado não existe mais (pode ter sido excluído); atualize e tente novamente", "请先选择一个自定义提供商": "Selecione primeiro um provedor personalizado", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "Conclua a verificação no slider exibido (etapa de controle de risco exigida pelo provedor)", "请填写 11 位大陆手机号": "Informe um número de celular da China continental com 11 dígitos", "请填写 6 位数字验证码": "Informe o código de 6 dígitos", "请填写 Base URL": "Preencha a Base URL", "请填写 {label}": "Preencha {label}", "请填写名称": "Preencha o nome", "请完成验证…": "Conclua a verificação…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "Lê e descriptografa %APPDATA%/AutoClaw/auth.json; somente no Windows", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "Lê ~/.cline/data/settings/providers.json; requer login no cliente Cline", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "Lê ~/.meituan-catpaw/auth.json; requer login no cliente CatPaw", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "Lê a sessão de login do cliente KukuAI desta máquina (%APPDATA%\\baidugenflowpro\\Network\\Cookies); requer login no cliente KukuAI", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "Lê o estado de login do cliente OrcaTerm local (%APPDATA%\\com.orcaterm-desktop.app\\data.bin); é preciso estar logado no cliente OrcaTerm", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "Lê o estado de login do cliente 智谱清言 local (%APPDATA%\\chatglm\\Network\\Cookies); o cliente precisa estar conectado", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "Lê a conta atualmente conectada no cliente oficial (Tencent WorkBuddy / WorkBuddy AI) nesta máquina: o arquivo de sessão mais recente no diretório de credenciais é localizado automaticamente (é preciso estar conectado ao cliente oficial nesta máquina). Após a importação, o gateway renova o token automaticamente — não é preciso trocar tokens manualmente conforme a validade de 2 horas.", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "Lê a sessão de login atual do cliente desta máquina (Cookie em texto claro, sem descriptografia). Com o cliente em execução, o arquivo Cookies fica em uso exclusivo; feche o cliente KukuAI antes de importar.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente).", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente). Após entrar novamente no cliente, clique em \"Atualizar Token\" para sincronizar.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente). Após entrar novamente no cliente, basta importar de novo.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente). Usuários que entram no cliente com Zai / Google devem usar esta opção.", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "Lê a sessão de login atual do cliente desta máquina, em tempo real a cada vez (excluir este registro não afeta a sessão de login do cliente). Esta opção fica em {label}.", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "Lê o token OAuth com que o cliente local está logado (JSON em texto claro, sem descriptografia). Após importar, o gateway renova automaticamente — não é preciso acompanhar a expiração de 2 horas do cliente.", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "Lê o estado de login atual do cliente local. Os cookies do cliente são criptografados com DPAPI (Chromium os_crypt), portanto isto funciona somente no Windows; o arquivo pode ficar ilegível enquanto o cliente está aberto — feche o cliente e tente de novo (ou use \"Preencher credenciais\" para colar um token).", "账号信息": "Informações da conta", "账号信息不完整,请刷新后重试": "Informações da conta incompletas; atualize e tente novamente", "账号已添加,但请留意:{warning}": "Conta adicionada, mas atenção: {warning}", "账号版本": "Edição da conta", "账号类型": "Tipo de conta", "账号:{name}
    ": "Conta: {name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "Usa a rota Inference Providers; crie a Key em hf.co/settings/tokens", "还没有账号": "Ainda não há contas", "这一家当前不支持网页登录,请改用填写凭证": "Este provedor não suporta login web no momento; use \"Preencher credenciais\"", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "Esta conta não tem campanhas com resgate automático no momento (apenas os pontos de brinde do login diário são resgatados automaticamente)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "Esta cota passa pelo canal \"Start Plan\": se o encaminhamento avisar que o Coding Plan expirou, ", "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "Aqui é a conta do site da China (modelscope.cn): cole o token do site da China. O site internacional (modelscope.ai) é outro provider com outra conta; os tokens não são intercambiáveis entre os dois.", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "Aqui é a conta do site da China (monkeycode-ai.com): cole a sessão do site da China. O site internacional (monkeycode-ai.net) é outro provedor, com conta própria; as credenciais não são compartilhadas entre os dois.", "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "Aqui é a conta do site internacional (modelscope.ai): cole o token do site internacional. O site da China (modelscope.cn) é outro provider com outra conta; os tokens não são intercambiáveis entre os dois.", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "Aqui é a conta do site internacional (monkeycode-ai.net): cole a sessão do site internacional. O site da China (monkeycode-ai.com) é outro provedor, com conta própria; as credenciais não são compartilhadas entre os dois.", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Selecione o arquivo de sessão de login auth.json do cliente CatPaw (Windows: C:\\Users\\\\.meituan-catpaw\\auth.json; macOS / Linux: ~/.meituan-catpaw/auth.json). Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente — sem depender mais do cliente desta máquina.", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "Selecione o arquivo de sessão de login providers.json do cliente Cline (Windows: C:\\Users\\\\.cline\\data\\settings\\providers.json; macOS / Linux: ~/.cline/data/settings/providers.json). Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente — sem depender mais do cliente desta máquina; este registro entra em {label}.", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "Selecione o arquivo Cookies do cliente KukuAI (%APPDATA%\\baidugenflowpro\\Network\\Cookies): é um banco SQLite **binário** (sem extensão, não é JSON). A importação lê uma cópia do arquivo selecionado e não disputa o bloqueio com o cliente em execução, então **não é preciso fechar o cliente antes**. Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente.", "选择凭证文件导入": "Importar de arquivo de credenciais", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "Selecione o arquivo de credenciais de sessão do cliente oficial (workbuddy-desktop.info / workbuddy-desktop-ai.info) ou um JSON de conta exportado pelo wb2api (formato aninhado ou plano).", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "Selecione o arquivo de sessão de login auth.json do cliente Raccoon (Windows: C:\\Users\\\\.box-agent\\config\\auth.json; macOS / Linux: ~/.box-agent/config/auth.json). Após a importação, as credenciais ficam no gateway e podem ser encaminhadas de forma independente — sem depender mais do cliente desta máquina.", "选择提供商": "Selecionar provedor", "选择的文件不是合法 JSON": "O arquivo selecionado não é um JSON válido", "选择要添加账号的提供商": "Selecione o provedor para adicionar uma conta", "重新扫描": "Escanear novamente", "鉴权": "Autenticação", "阿里云 Token Plan 套餐(国际站)": "Plano Token Plan do Alibaba Cloud (site internacional)", "阿里云百炼 Coding 套餐(国内站)": "Plano Coding do Alibaba Cloud Model Studio (site da China)", "阿里云百炼 Coding 套餐(国际站)": "Plano Coding do Alibaba Cloud Model Studio (site internacional)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "Serviço de modelos Alibaba Cloud Model Studio (site internacional, modo compatível com OpenAI)", "需要图形验证码:登录窗口已弹出,请填写后继续": "Captcha necessário: a janela de login foi aberta; preencha para continuar", "预置 API": "API predefinida", "领取 CodeArts 每日福利": "Resgatar benefício diário do CodeArts", "领取失败:{message}": "Falha ao resgatar: {message}", "领取并让官方确认": "Resgatar e aguardar confirmação oficial", "风控验证配置不完整,请稍后重试": "Configuração de verificação de controle de risco incompleta; tente novamente mais tarde", "验证码": "Código de verificação", "验证码已发送。收到后填入下方并点「登录并添加」": "Código enviado. Informe-o abaixo e clique em \"Entrar e adicionar\"", "验证码已发送,请查看手机短信": "Código enviado; verifique o SMS", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "Código enviado; verifique o SMS. Informe-o abaixo e clique em \"Entrar e adicionar\" para concluir o login", "验证码已发送,请查看短信": "Código enviado; verifique as mensagens", "验证码校验失败,请重试": "Falha na verificação do captcha; tente novamente", "验证码校验超时,请重试": "Tempo esgotado na verificação do captcha; tente novamente", "验证码组件不可用,请重试": "Componente de captcha indisponível; tente novamente", "验证码组件初始化超时,请重试": "Tempo esgotado ao inicializar o componente de captcha; tente novamente", "验证码组件加载失败,请检查网络后重试": "Falha ao carregar o componente de captcha; verifique a rede e tente novamente", "验证码组件加载异常,请重试": "Erro ao carregar o componente de captcha; tente novamente", "验证码组件加载超时,请检查网络后重试": "Tempo esgotado ao carregar o componente de captcha; verifique a rede e tente novamente", "验证码组件未加载,请重启应用后重试": "O componente de captcha não foi carregado; reinicie o aplicativo e tente novamente", "(免费额度池,模型名带 cline-free/ 前缀)。": " (pool de cota gratuita; nomes de modelo com o prefixo cline-free/).", "(其中 {n} 把恢复为不限制)": " ({n} das quais voltaram a ser ilimitadas)", "(必填)": " (obrigatório)", "(有效期 {window})": "(validade {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": " (pool de assinatura; nomes de modelo com o prefixo cline-pass/, e a conta precisa da assinatura correspondente).", ",下一次最快 {minutes} 分钟后": ", próxima tentativa em pelo menos {minutes} min", ",并从 {n} 把 Key 的可用提供商里移除": ", e removido dos provedores permitidos de {n} keys" }); diff --git a/desktop-tauri/ui/i18n/pt-BR/checkin.js b/desktop-tauri/ui/i18n/pt-BR/checkin.js index 0de0c780..a8be7503 100644 --- a/desktop-tauri/ui/i18n/pt-BR/checkin.js +++ b/desktop-tauri/ui/i18n/pt-BR/checkin.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:pt-BR/checkin —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "Resgate de checkin_credits do SOLO · redefinido às 0h do dia natural", "UMID 组件安装失败:{error}": "Falha ao instalar o componente UMID: {error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy CN · Consulte a árvore de tarefas e acenda / resgate com um clique · inclui o evento de volta às aulas e a viagem do gato · clique na linha para detalhes", "WorkBuddy 国际版保活模型,按顺序回退": "Modelos do WorkBuddy internacional para manter ativo, com fallback em ordem", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "Modelos gratuitos da atividade diária do WorkBuddy Internacional · uma configuração global, independente dos agendamentos", "{date}(每天 {time})": "{date} (todos os dias às {time})", "{label} ×{count}({reason})": "{label} ×{count} ({reason})", "{n} 项可完成": "{n} para concluir", "{n} 项待领": "{n} itens a resgatar", "{total} 账号 · {done} 已签": "{total} contas · {done} com check-in", "{total} 项任务 · {pending} 项可完成": "{total} tarefas · {pending} para concluir", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ Componente UMID instalado; no próximo check-in já dá para resgatar os pontos da edição internacional", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ Check-in agendado ativado", "✅ 开学季任务执行完成": "✅ Tarefas de volta às aulas concluídas", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ Tarefas de crescimento concluídas: créditos +{credit}, energia +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ Benefícios iniciais resgatados, {n} pontos no total", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ Check-in concluído: {succeeded}/{total} contas resgataram com sucesso{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "A \"cadeia de modelos de keep-alive\" são os modelos gratuitos usados para manter contas do WorkBuddy Internacional ativas na atividade diária — tentados em ordem, parando no primeiro sucesso; envie vazio para restaurar o padrão ({defaults}). Deduplicação no dia + resgate idempotente: repetir a execução só retorna \"já resgatado\" e nunca pontua duas vezes.", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "A \"cadeia de modelos de keep-alive\" são os modelos gratuitos usados para manter contas do WorkBuddy Internacional ativas na atividade diária — tentados em ordem, parando no primeiro sucesso; limpar a lista e salvar restaura a cadeia padrão (padrão atual: {defaults}). Deduplicação no dia + resgate idempotente: repetir a execução só retorna \"já resgatado\" e nunca pontua duas vezes.", "「免费领积分」的每日任务 · 逐个领取": "Tarefa diária do “Ganhe pontos grátis” · resgate um a um", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "Benefício único · consultado e resgatado automaticamente após o check-in; depois de resgatado, fica registrado localmente e o upstream não é mais consultado · clique na linha para expandir a lista de tarefas", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "Resgata todas as recompensas do dia em uma única ação (check-in diário + presente de novos usuários) · idempotência garantida pelo upstream", "一键安装组件": "Instalar componente", "一键完成": "Concluir tudo", "一键领取({n})": "Resgatar todos ({n})", "上次执行:{line}": "Última execução: {line}", "上次签到时间": "Último check-in", "上次领取 {time} · 领取需通过滑块验证码": "Último resgate: {time} · o resgate exige captcha deslizante", "下次 {date}": "Próxima {date}", "下次 {date} · 点此管理条目": "Próxima {date} · clique para gerenciar os agendamentos", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "Fora do check-in diário: {list}. As recompensas únicas do CodeArts ficam em \"Benefícios iniciais\" abaixo; o resgate diário/de planos dele e do ZCode fica em \"Benefícios de atividade\".", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "Fora do check-in diário: {list}. As recompensas únicas do CodeArts ficam em \"Benefícios iniciais\" abaixo, e o benefício diário dele fica logo acima em \"Check-in diário\"; o resgate de planos do ZCode fica em \"Benefícios de atividade\".", "与国内版同一套任务接口 · 站点不同": "Mesma interface de tarefas da edição da China · site diferente", "今天已领 {n} 份": "{n} resgatado(s) hoje", "今天未领": "Não resgatado hoje", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "Resgatado hoje (horário de Pequim, {day}) · {n} itens confirmados oficialmente · amanhã é possível resgatar novamente", "今日已执行": "Executado hoje", "今日已派出": "Já enviado hoje", "今日已领取": "Resgatado hoje", "今日签到": "Check-in de hoje", "今日签到进度": "Progresso do check-in de hoje", "从清单里移除": "Remover da lista", "保活": "Manter ativo", "保活 {n}": "{n} mantidos ativos", "保活+领取": "Manter ativo + Resgatar", "保活中…": "Mantendo ativo…", "保活模型链": "Cadeia de modelos para manter ativo", "全选": "Selecionar tudo", "全部 {n} 家": "Todos os {n} provedores", "全部完成": "Tudo concluído", "全部查询": "Consultar todos", "全部结果": "Todos os resultados", "全部账号均可签到": "Todas as contas podem fazer check-in", "全部领取": "Resgatar todos", "关着:所有条目都不执行": "Desligado: nenhum agendamento é executado", "删除失败:{error}": "Falha ao excluir: {error}", "删除定时条目": "Excluir agendamento", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "No horário marcado, faz o check-in automático das contas habilitadas dos provedores marcados (WorkBuddy CN usa a API de check-in diário; a versão internacional usa a tarefa de atividade diária: detecta o evento, recebe a recompensa de atividade diária, mantém-se ativo com o modelo gratuito e abre uma sessão pelo canal web para acender a atividade do dia; o Raccoon usa o fluxo de pontos diários do desktop; o AutoClaw usa a tarefa de check-in diário do cliente oficial; o Qoder CN reivindica via evento, e contas sem evento atribuído recebem um aviso neutro; o Qoder internacional precisa primeiro de uma identidade de risco do dispositivo (gerada pelo componente UMID do cliente Qoder local / qodercli) para sequer ver o evento \"100 Credits diários\" — sem o componente, chega uma explicação clara em vez de um erro; o Trae recebe os pontos de check-in diário do SOLO (reiniciam à meia-noite), e quando o upstream não tem evento para a conta ou as credenciais não têm ID de dispositivo, chega \"não recebido + motivo\" em vez de erro; o Loomy credita os pontos de primeiro login uma vez por dia para a conta; o KukuAI recebe a tarefa diária \"Pontos grátis\"; o CodeArts recebe as vantagens operacionais do dia (receber → confirmar → verificar relendo; execuções automáticas limitadas a 6 requisições de escrita por dia, com 10 minutos de intervalo); o OfficeAce recebe todas as recompensas do dia de uma vez (check-in diário + brinde de novato)). Se a máquina estava desligada no horário, um check-in de reposição roda ao ligar — nada fica para trás. A API de check-in de cada provedor é idempotente: repetir nunca recebe duas vezes.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "No horário definido, o check-in automático é feito nas contas disponíveis dos provedores marcados (o WorkBuddy edição da China usa a interface de check-in diário; a edição internacional usa as tarefas de atividade diária: detectar o evento, resgatar a recompensa de atividade diária e então manter a conta ativa com modelos gratuitos; o Raccoon usa o fluxo diário de pontos do aplicativo desktop; o AutoClaw usa a tarefa de check-in diário do cliente oficial; o Qoder China usa o resgate de evento, e contas sem evento distribuído recebem um aviso neutro; o Qoder internacional precisa primeiro da identidade de controle de risco do dispositivo (gerada pelo componente UMID do cliente Qoder / qodercli local) para enxergar o evento “100 Credits diários”, e sem o componente recebe uma explicação clara em vez de um erro; o Trae resgata os pontos de check-in diário do SOLO (redefinidos às 0h do dia natural), e quando o upstream não abriu o evento para a conta ou a credencial não tem o ID do dispositivo, o resultado é “não resgatado + motivo específico” em vez de um erro; o Loomy credita uma vez por dia os pontos de primeiro login da conta; o KukuAI resgata a tarefa diária do “Ganhe pontos grátis”); o CodeArts resgata o benefício de campanha do dia (resgatar → confirmar → reler para verificar; execuções automáticas têm limite de 6 gravações por dia com intervalo de 10 minutos); o OfficeAce resgata todas as recompensas do dia em uma única ação (check-in diário + presente de novos usuários)). Se o horário for perdido, o check-in é compensado automaticamente após o computador ser ligado, sem que nada se perca por o computador estar desligado no horário. As interfaces de check-in de cada provedor são idempotentes; execuções repetidas não resgatam duas vezes.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "No horário definido, o check-in automático é feito nas contas disponíveis dos provedores marcados (o WorkBuddy edição da China usa a interface de check-in diário; a edição internacional usa as tarefas de atividade diária: detectar o evento, resgatar a recompensa de atividade diária e então manter a conta ativa com modelos gratuitos; o Raccoon usa o fluxo diário de pontos do aplicativo desktop; o AutoClaw usa a tarefa de check-in diário do cliente oficial; o Qoder China usa o resgate de evento, e contas sem evento distribuído recebem um aviso neutro; o Qoder internacional precisa primeiro da identidade de controle de risco do dispositivo (gerada pelo componente UMID do cliente Qoder / qodercli local) para enxergar o evento “100 Credits diários”, e sem o componente recebe uma explicação clara em vez de um erro; o Trae resgata os pontos de check-in diário do SOLO (redefinidos às 0h do dia natural), e quando o upstream não abriu o evento para a conta ou a credencial não tem o ID do dispositivo, o resultado é “não resgatado + motivo específico” em vez de um erro; o Loomy credita uma vez por dia os pontos de primeiro login da conta; o KukuAI resgata a tarefa diária do “Ganhe pontos grátis”); o OfficeAce resgata todas as recompensas do dia em uma única ação (check-in diário + presente de novos usuários)). Se o horário for perdido, o check-in é compensado automaticamente após o computador ser ligado, sem que nada se perca por o computador estar desligado no horário. As interfaces de check-in de cada provedor são idempotentes; execuções repetidas não resgatam duas vezes.", "到点时逐个签到,已勾 {n} / {total} 家": "{n} de {total} marcados — o check-in é feito um por um no horário", "北京时间 · 错过时点开机后会自动补签": "Horário de Pequim · execuções perdidas são compensadas automaticamente ao iniciar", "去领取": "Resgatar", "另有 {n} 个账号不参与每日签到": "Outras {n} contas não participam do check-in diário", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "Resgatar apenas recompensas de tarefas concluídas (idempotente; cliques repetidos não creditam em dobro)", "可完成": "Pode concluir", "可派出": "Pode enviar", "可选 · 缺省显示时刻": "Opcional · usa o horário como padrão", "可领奖": "Pode resgatar", "后端未返回定时签到数据": "O backend não retornou dados de agendamento", "后端未返回签到中心数据": "O backend não retornou os dados da central de check-in", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "O check-in da edição internacional exige o componente UMID para gerar a identidade de controle de risco do dispositivo (não detectado nesta máquina).", "在途": "Em viagem", "填入缺省链": "Preencher cadeia padrão", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "Escolha o horário e os provedores e clique em Salvar; o nome é opcional (quando vazio, mostra-se o horário)", "失败 {n}": "{n} com falha", "套餐明细": "Detalhes dos planos", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "Basta instalar o cliente Qoder ou o qodercli (não é preciso reiniciar o gateway).", "安装中…": "Instalando…", "官方客户端的每日签到任务": "Tarefa de check-in diário do cliente oficial", "定时签到": "Check-in agendado", "定时签到已关闭": "Check-in agendado desativado", "尚未查询": "Ainda não consultado", "尚未查询任务状态": "Status das tarefas ainda não consultado", "巡检一次": "Executar uma rodada", "已保存:{label}": "Salvo: {label}", "已保存:保活模型链": "Salvo: cadeia de modelos para manter ativo", "已保存:定时条目": "Salvo: agendamento", "已删除定时条目": "Agendamento excluído", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "Atividade reportada (ofensiva acesa), mas a campanha não está ativa (nada para resgatar desta vez)", "已抽 {n} 次": "Sorteou {n} vezes", "已有结果 {checked} / 共 {total} 个账号": "Já com resultado: {checked} / {total} contas", "已签": "Com check-in", "已领 {claimed}/{total} · 累计 {earned} 积分": "Resgatado {claimed}/{total} · {earned} pontos acumulados", "已领养": "Adotado", "已领取": "Resgatado", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "Resgatar “100 Credits diários” com a identidade de controle de risco do dispositivo · requer o componente UMID", "开学季执行失败:{error}": "Falha na execução de volta às aulas: {error}", "开学季执行完成:{message}": "Execução de volta às aulas concluída: {message}", "开学季活动": "Evento de volta às aulas", "开着:启用的条目按各自时刻执行": "Ligado: agendamentos habilitados rodam em seus próprios horários", "待签": "Pendente", "待领新手福利": "Benefícios iniciais pendentes", "总开关": "Interruptor principal", "总开关已关闭 · 在「定时签到」页打开": "Interruptor principal desligado · ative na aba \"Check-in agendado\"", "成功 {n}": "{n} com sucesso", "成长任务": "Tarefas de crescimento", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "Tarefas de crescimento concluídas ({done} com sucesso, {failed} com falha): créditos +{credit}, energia +{energy}", "成长任务执行失败:{error}": "Falha na execução das tarefas de crescimento: {error}", "执行失败:{error}": "Falha na execução: {error}", "执行并抽奖": "Executar e sortear", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "Executar as tarefas de volta às aulas e gastar todas as chances de sorteio (compartilhar / conversar / eventos de especialista)", "把缺省链填进清单,再点「保存」生效": "Coloca a cadeia padrão na lista; clique em Salvar para aplicar", "抽奖机会 {n} 次": "{n} chances de sorteio", "按住拖动调整顺序": "Pressione e arraste para reordenar", "按住拖动,调整这个模型在链里的顺序": "Pressione e arraste para mudar a posição deste modelo na cadeia", "按序逐个尝试,共 {n} 个": "{n} modelos, tentados em ordem", "按结果筛选": "Filtrar por resultado", "探测 + 领取 + 保活 · 与定时签到同一套组合": "Detectar + resgatar + manter ativo · mesma combinação do check-in agendado", "探测活动并领取日活奖励 · 不做保活": "Detectar o evento e resgatar a recompensa de atividade diária · sem manter ativo", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "Aceitar + acender + resgatar (apenas tarefas com receita verificada)", "搜账号 / 收益 / 错误 / 触发原因": "Pesquisar conta / ganho / erro / motivo do disparo", "收起新建": "Fechar novo item", "新建定时条目": "Nova entrada agendada", "新手福利": "Benefícios iniciais", "新手福利有 {n} 项领取失败,可重试": "{n} item(ns) dos benefícios iniciais falharam no resgate — é possível tentar novamente", "无": "Nenhum", "无独立签到接口 · 每天替账号打一次首次登录积分": "Sem interface de check-in própria · credita uma vez por dia os pontos de primeiro login da conta", "无账号": "Sem contas", "暂不可领": "Indisponível", "暂不支持": "Ainda não suportado", "暂无启用的条目 · 点此添加": "Nenhum agendamento habilitado · clique para adicionar", "有未保存的改动": "Alterações não salvas", "未勾选提供商": "Nenhum provedor selecionado", "未开启": "Desativado", "未解锁": "Bloqueado", "未领养(领养需先完成当日对话量)": "Não adotado (a adoção exige cumprir a cota diária de conversas primeiro)", "未领取": "Não resgatado", "本地台账里今天还没领过;活动期内每天发一份新套餐": "O registro local ainda não tem resgate nenhum hoje; um novo plano é emitido todo dia durante o evento", "本地台账里今天(北京时间)领过的套餐:{plans}": "Planos resgatados hoje (horário de Pequim) conforme o registro local: {plans}", "条启用": "habilitado(s)", "查询于 {time}": "Consultado em {time}", "查询任务": "Consultar tarefas", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "Consulte a árvore de tarefas e acenda / resgate com um clique (inclui volta às aulas e viagem do gato)", "查询失败:{error}": "Falha na consulta: {error}", "桌面端每日积分链路": "Fluxo diário de pontos do aplicativo desktop", "正在读取定时签到数据…": "Carregando dados de agendamento…", "正在读取签到数据…": "Lendo os dados de check-in…", "每天 {time}": "Todos os dias às {time}", "每天 {time} · {scope}": "Diário {time} · {scope}", "每天时刻": "Horário diário", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "Uma linha por conta a cada execução · resultados e ganhos conforme registrado pelo backend", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "Tarefas de atividade diária · uma conversa no canal web acende a atividade diária, só o resgate adiciona pontos · os dois podem ser executados separadamente", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "Pontos de login diário · resgata atividades de membro junto · contas de visitante não têm sistema de pontos (ignorado)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "Benefício diário · resgatar → confirmar → reler para verificar · redefinido no dia natural (horário de Pequim)", "每日签到": "Check-in diário", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "Cada agendamento tem horário e escopo próprios · deduplicação diária por item · execuções perdidas são compensadas ao iniciar", "每账号一条明细 · 点此查看「签到记录」": "Uma linha por conta · abra \"Registros de check-in\"", "没有可领套餐的账号(ZCode 未添加)。": "Nenhuma conta com planos resgatáveis (ZCode não adicionado).", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "Nenhuma conta com benefícios para resgatar (CodeArts / ZCode não foram adicionados).", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "Nenhuma conta suporta tarefas de crescimento (requer WorkBuddy CN).", "没有支持新手福利的账号": "Nenhuma conta suporta benefícios iniciais", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "Nenhuma conta suporta benefícios iniciais — atualmente Loomy, Raccoon e CodeArts.", "没有符合筛选条件的签到记录": "Nenhum registro de check-in corresponde aos filtros", "没有需要执行的任务": "Nada para executar", "活动福利": "Recompensas de evento", "活动(campaign)领取 · 每天 10:00 刷新": "Resgate de eventos (campaign) · atualizado todos os dias às 10:00", "活跃上报与保活均未成功,且活动未开启": "Tanto o relatório de atividade quanto o keep-alive falharam, e a campanha não está ativa", "活跃上报完成,但保活未成功且活动未开启": "Atividade reportada, mas o keep-alive falhou e a campanha não está ativa", "活跃上报完成,但活动未开启": "Atividade reportada, mas a campanha não está ativa", "活跃上报成功": "Atividade reportada com sucesso", "活跃保活失败": "Falha ao manter a atividade", "活跃保活完成": "Atividade mantida", "活跃保活完成,但活动未开启": "Atividade mantida, mas o evento não está aberto", "活跃保活完成,但活跃上报失败且活动未开启": "Keep-alive concluído, mas o relatório de atividade falhou e a campanha não está ativa", "添加条目": "Adicionar agendamento", "添加模型": "Adicionar modelo", "清单为空 —— 保存后恢复缺省链": "A lista está vazia — salvar restaura a cadeia padrão", "清单里已经有「{name}」": "A lista já contém \"{name}\"", "清空失败:{error}": "Falha ao limpar: {error}", "清空签到记录": "Limpar registros de check-in", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "Clique em \"Detalhes dos planos\" para ver quais você recebeu e quando entram em vigor; dá para resgatar de novo todo dia durante o evento", "点击行展开账号明细 · 单账号签到不受范围限制": "Clique na linha para expandir os detalhes das contas · o check-in individual não é limitado pelo escopo", "独立链路 · 只提供手动入口 · 不进自动签到": "Fluxo independente · apenas entrada manual · não participa do check-in automático", "猫猫旅行": "Viagem do gato", "猫猫旅行失败:{error}": "Falha na viagem do gato: {error}", "猫猫旅行失败:{message}": "Falha na viagem do gato: {message}", "猫猫旅行:{message}": "Viagem do gato: {message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "Manter a conta ativa com modelos gratuitos e uma conversa no canal web · sem resgatar recompensas", "确定删除「{name}」?删除后到点不再执行。": "Excluir \"{name}\"? Ele não será mais executado no horário agendado.", "确定清空全部签到记录?清空后无法恢复。": "Limpar todos os registros de check-in? Isso não pode ser desfeito.", "确定清空当前筛选出的签到记录?清空后无法恢复。": "Limpar os registros de check-in filtrados? Isso não pode ser desfeito.", "移除 {name}": "Remover {name}", "立即全部签到": "Fazer check-in de todos agora", "签到": "Check-in", "签到中…": "Fazendo check-in…", "签到中心分区": "Seções do centro de check-in", "签到失败:{error}": "Falha no check-in: {error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "Check-in concluído: {succeeded}/{total} com sucesso{active}; {failed} com falha", "签到成功": "Check-in bem-sucedido", "签到提供商": "Provedores de check-in", "签到范围": "Escopo do check-in", "签到触发时刻": "Horário de disparo do check-in", "签到记录": "Registros de check-in", "签到记录时间范围": "Período dos registros de check-in", "签到记录表": "Tabela de registros de check-in", "累计签到记录": "Total de registros de check-in", "结算于 {time}": "Liquidado em {time}", "能量 {n}": "Energia {n}", "腾讯每日签到接口 · 仅国内版": "Interface de check-in diário da Tencent · apenas edição da China", "至少勾一家才能保存(不勾等于这条条目不签到)": "Selecione ao menos um provedor para salvar (sem seleção, esta entrada não faz check-in)", "读取定时签到数据失败:{error}": "Falha ao carregar dados de agendamento: {error}", "读取签到数据失败:{error}": "Falha ao ler os dados de check-in: {error}", "读取签到记录失败:{error}": "Falha ao carregar registros de check-in: {error}", "跳过 {n}": "{n} ignorados", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "Entrega de eventos oficiais (resgatar → confirmar → reler para verificar) · resgate dos pontos de bônus do plano", "还没执行过": "Ainda não executado", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "Nenhum agendamento ainda — clique em \"Adicionar agendamento\" para criar um, ou faça check-in manualmente no \"Centro de check-in\".", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "Nenhum registro de check-in ainda — os detalhes aparecem aqui após um check-in manual ou uma execução agendada.", "连登 {n} 天": "Sequência de {n} dias", "部分": "Parcial", "重签": "Refazer check-in", "重试": "Tentar de novo", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "Plano de teste por tempo limitado · o resgate exige CAPTCHA de arrastar · veja e resgate um a um", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "Plano de teste por tempo limitado (start-plan), um por dia durante o evento · o resgate exige captcha deslizante", "需真实操作": "Requer ação real", "非活动期": "Evento inativo", "项": "itens", "领取": "Resgatar", "领取中": "Resgatando", "领取中…": "Resgatando…", "领取失败": "Falha no resgate", "领取失败:{error}": "Falha no resgate: {error}", "(共 {n} 个账号)": "({n} contas no total)", "(能量 / 连登读数本次未取到)": "(Leituras de energia / sequência indisponíveis desta vez)", ",日活保活 {n} 个": ", {n} mantidas ativas" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "Resgate de checkin_credits do SOLO · redefinido às 0h do dia natural", "UMID 组件安装失败:{error}": "Falha ao instalar o componente UMID: {error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy CN · Consulte a árvore de tarefas e acenda / resgate com um clique · inclui o evento de volta às aulas e a viagem do gato · clique na linha para detalhes", "WorkBuddy 国际版保活模型,按顺序回退": "Modelos do WorkBuddy internacional para manter ativo, com fallback em ordem", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "Modelos gratuitos da atividade diária do WorkBuddy Internacional · uma configuração global, independente dos agendamentos", "{date}(每天 {time})": "{date} (todos os dias às {time})", "{label} ×{count}({reason})": "{label} ×{count} ({reason})", "{n} 项可完成": "{n} para concluir", "{n} 项待领": "{n} itens a resgatar", "{total} 账号 · {done} 已签": "{total} contas · {done} com check-in", "{total} 项任务 · {pending} 项可完成": "{total} tarefas · {pending} para concluir", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ Componente UMID instalado; no próximo check-in já dá para resgatar os pontos da edição internacional", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ Check-in agendado ativado", "✅ 开学季任务执行完成": "✅ Tarefas de volta às aulas concluídas", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ Tarefas de crescimento concluídas: créditos +{credit}, energia +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ Benefícios iniciais resgatados, {n} pontos no total", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ Check-in concluído: {succeeded}/{total} contas resgataram com sucesso{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "A \"cadeia de modelos de keep-alive\" são os modelos gratuitos usados para manter contas do WorkBuddy Internacional ativas na atividade diária — tentados em ordem, parando no primeiro sucesso; envie vazio para restaurar o padrão ({defaults}). Deduplicação no dia + resgate idempotente: repetir a execução só retorna \"já resgatado\" e nunca pontua duas vezes.", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "A \"cadeia de modelos de keep-alive\" são os modelos gratuitos usados para manter contas do WorkBuddy Internacional ativas na atividade diária — tentados em ordem, parando no primeiro sucesso; limpar a lista e salvar restaura a cadeia padrão (padrão atual: {defaults}). Deduplicação no dia + resgate idempotente: repetir a execução só retorna \"já resgatado\" e nunca pontua duas vezes.", "「免费领积分」的每日任务 · 逐个领取": "Tarefa diária do “Ganhe pontos grátis” · resgate um a um", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "Benefício único · consultado e resgatado automaticamente após o check-in; depois de resgatado, fica registrado localmente e o upstream não é mais consultado · clique na linha para expandir a lista de tarefas", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "Resgata todas as recompensas do dia em uma única ação (check-in diário + presente de novos usuários) · idempotência garantida pelo upstream", "一键安装组件": "Instalar componente", "一键完成": "Concluir tudo", "一键领取({n})": "Resgatar todos ({n})", "上次执行:{line}": "Última execução: {line}", "上次签到时间": "Último check-in", "上次领取 {time} · 领取需通过滑块验证码": "Último resgate: {time} · o resgate exige captcha deslizante", "下次 {date}": "Próxima {date}", "下次 {date} · 点此管理条目": "Próxima {date} · clique para gerenciar os agendamentos", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "Fora do check-in diário: {list}. As recompensas únicas do CodeArts ficam em \"Benefícios iniciais\" abaixo; o resgate diário/de planos dele e do ZCode fica em \"Benefícios de atividade\".", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "Fora do check-in diário: {list}. As recompensas únicas do CodeArts ficam em \"Benefícios iniciais\" abaixo, e o benefício diário dele fica logo acima em \"Check-in diário\"; o resgate de planos do ZCode fica em \"Benefícios de atividade\".", "与国内版同一套任务接口 · 站点不同": "Mesma interface de tarefas da edição da China · site diferente", "与国内版同一套链路 · 站点不同、令牌不通用": "Mesmo fluxo da edição China · site diferente, tokens não intercambiáveis", "今天已领 {n} 份": "{n} resgatado(s) hoje", "今天未领": "Não resgatado hoje", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "Resgatado hoje (horário de Pequim, {day}) · {n} itens confirmados oficialmente · amanhã é possível resgatar novamente", "今日已执行": "Executado hoje", "今日已派出": "Já enviado hoje", "今日已领取": "Resgatado hoje", "今日签到": "Check-in de hoje", "今日签到进度": "Progresso do check-in de hoje", "从清单里移除": "Remover da lista", "保活": "Manter ativo", "保活 {n}": "{n} mantidos ativos", "保活+领取": "Manter ativo + Resgatar", "保活中…": "Mantendo ativo…", "保活模型链": "Cadeia de modelos para manter ativo", "全选": "Selecionar tudo", "全部 {n} 家": "Todos os {n} provedores", "全部完成": "Tudo concluído", "全部查询": "Consultar todos", "全部结果": "Todos os resultados", "全部账号均可签到": "Todas as contas podem fazer check-in", "全部领取": "Resgatar todos", "关着:开机后等到窗口起点再签,随机窗口当天生效": "Desligado: após iniciar, esperar o início da janela para que a janela aleatória valha hoje", "关着:所有条目都不执行": "Desligado: nenhum agendamento é executado", "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "minutos · contas executam em momentos aleatórios dentro da janela; 0 = executar imediatamente no horário", "删除失败:{error}": "Falha ao excluir: {error}", "删除定时条目": "Excluir agendamento", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "Faz check-in nas contas disponíveis dos provedores marcados quando chega a hora (WorkBuddy CN usa a API de check-in diário; WorkBuddy Intl usa a tarefa de atividade diária: sondar atividades, resgatar a recompensa diária, manter um modelo gratuito ativo e abrir uma sessão web para acender a sequência; Raccoon usa a cadeia diária de pontos do desktop; AutoClaw usa a tarefa diária de sign-in do cliente oficial; Qoder CN resgata campanhas e mostra um aviso neutro para contas sem campanha; Qoder Intl precisa de uma identidade de risco do dispositivo (gerada pelo componente UMID do cliente Qoder / qodercli local) para ver a campanha de '100 Credits diários' e mostra uma explicação clara em vez de erro quando o componente falta; Trae resgata os créditos de check-in diário do SOLO (reset à meia-noite local) e informa 'não resgatado + motivo' em vez de erro quando o upstream não tem campanha para a conta ou a credencial não tem device id; Loomy chama o endpoint de pontos do primeiro login uma vez por dia; KukuAI resgata as tarefas diárias de 'pontos grátis'; CodeArts resgata o benefício diário de operações (resgatar → confirmar → reler, com execuções automáticas limitadas a 6 escritas por dia e 10 minutos de intervalo; OfficeAce resgata todas as recompensas do dia (check-in diário + presente de novato) em uma chamada). Com 'margem aleatória de N minutos', as contas de uma rodada executam espalhadas dentro da própria janela (limitada a 0:00-23:59 do mesmo dia) em vez de todas no mesmo minuto; se a janela já passou, todas executam imediatamente. Execuções perdidas são recuperadas após iniciar, então nada se perde quando a máquina estava desligada (desligue 'Recuperação na inicialização' para esperar o início da janela). A API de check-in de cada provedor é idempotente, então execuções repetidas nunca resgatam duas vezes.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "No horário definido, o check-in automático é feito nas contas disponíveis dos provedores marcados (o WorkBuddy edição da China usa a interface de check-in diário; a edição internacional usa as tarefas de atividade diária: detectar o evento, resgatar a recompensa de atividade diária e então manter a conta ativa com modelos gratuitos; o Raccoon usa o fluxo diário de pontos do aplicativo desktop; o AutoClaw usa a tarefa de check-in diário do cliente oficial; o Qoder China usa o resgate de evento, e contas sem evento distribuído recebem um aviso neutro; o Qoder internacional precisa primeiro da identidade de controle de risco do dispositivo (gerada pelo componente UMID do cliente Qoder / qodercli local) para enxergar o evento “100 Credits diários”, e sem o componente recebe uma explicação clara em vez de um erro; o Trae resgata os pontos de check-in diário do SOLO (redefinidos às 0h do dia natural), e quando o upstream não abriu o evento para a conta ou a credencial não tem o ID do dispositivo, o resultado é “não resgatado + motivo específico” em vez de um erro; o Loomy credita uma vez por dia os pontos de primeiro login da conta; o KukuAI resgata a tarefa diária do “Ganhe pontos grátis”); o CodeArts resgata o benefício de campanha do dia (resgatar → confirmar → reler para verificar; execuções automáticas têm limite de 6 gravações por dia com intervalo de 10 minutos); o OfficeAce resgata todas as recompensas do dia em uma única ação (check-in diário + presente de novos usuários)). Se o horário for perdido, o check-in é compensado automaticamente após o computador ser ligado, sem que nada se perca por o computador estar desligado no horário. As interfaces de check-in de cada provedor são idempotentes; execuções repetidas não resgatam duas vezes.", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "No horário definido, o check-in automático é feito nas contas disponíveis dos provedores marcados (o WorkBuddy edição da China usa a interface de check-in diário; a edição internacional usa as tarefas de atividade diária: detectar o evento, resgatar a recompensa de atividade diária e então manter a conta ativa com modelos gratuitos; o Raccoon usa o fluxo diário de pontos do aplicativo desktop; o AutoClaw usa a tarefa de check-in diário do cliente oficial; o Qoder China usa o resgate de evento, e contas sem evento distribuído recebem um aviso neutro; o Qoder internacional precisa primeiro da identidade de controle de risco do dispositivo (gerada pelo componente UMID do cliente Qoder / qodercli local) para enxergar o evento “100 Credits diários”, e sem o componente recebe uma explicação clara em vez de um erro; o Trae resgata os pontos de check-in diário do SOLO (redefinidos às 0h do dia natural), e quando o upstream não abriu o evento para a conta ou a credencial não tem o ID do dispositivo, o resultado é “não resgatado + motivo específico” em vez de um erro; o Loomy credita uma vez por dia os pontos de primeiro login da conta; o KukuAI resgata a tarefa diária do “Ganhe pontos grátis”); o OfficeAce resgata todas as recompensas do dia em uma única ação (check-in diário + presente de novos usuários)). Se o horário for perdido, o check-in é compensado automaticamente após o computador ser ligado, sem que nada se perca por o computador estar desligado no horário. As interfaces de check-in de cada provedor são idempotentes; execuções repetidas não resgatam duas vezes.", "到点时逐个签到,已勾 {n} / {total} 家": "{n} de {total} marcados — o check-in é feito um por um no horário", "北京时间 · 错过时点开机后会自动补签": "Horário de Pequim · execuções perdidas são compensadas automaticamente ao iniciar", "去领取": "Resgatar", "另有 {n} 个账号不参与每日签到": "Outras {n} contas não participam do check-in diário", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "Resgatar apenas recompensas de tarefas concluídas (idempotente; cliques repetidos não creditam em dobro)", "可完成": "Pode concluir", "可派出": "Pode enviar", "可选 · 缺省显示时刻": "Opcional · usa o horário como padrão", "可领奖": "Pode resgatar", "后端未返回定时签到数据": "O backend não retornou dados de agendamento", "后端未返回签到中心数据": "O backend não retornou os dados da central de check-in", "启动补签": "Recuperação na inicialização", "启动补签已关闭": "Recuperação na inicialização desativada", "启动补签已开启": "Recuperação na inicialização ativada", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "O check-in da edição internacional exige o componente UMID para gerar a identidade de controle de risco do dispositivo (não detectado nesta máquina).", "在途": "Em viagem", "填入缺省链": "Preencher cadeia padrão", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "Escolha o horário e os provedores e clique em Salvar; o nome é opcional (quando vazio, mostra-se o horário)", "失败 {n}": "{n} com falha", "套餐明细": "Detalhes dos planos", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "Basta instalar o cliente Qoder ou o qodercli (não é preciso reiniciar o gateway).", "安装中…": "Instalando…", "官方客户端的每日签到任务": "Tarefa de check-in diário do cliente oficial", "定时签到": "Check-in agendado", "定时签到已关闭": "Check-in agendado desativado", "尚未查询": "Ainda não consultado", "尚未查询任务状态": "Status das tarefas ainda não consultado", "巡检一次": "Executar uma rodada", "已保存:{label}": "Salvo: {label}", "已保存:保活模型链": "Salvo: cadeia de modelos para manter ativo", "已保存:定时条目": "Salvo: agendamento", "已删除定时条目": "Agendamento excluído", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "Atividade reportada (ofensiva acesa), mas a campanha não está ativa (nada para resgatar desta vez)", "已抽 {n} 次": "Sorteou {n} vezes", "已有结果 {checked} / 共 {total} 个账号": "Já com resultado: {checked} / {total} contas", "已签": "Com check-in", "已领 {claimed}/{total} · 累计 {earned} 积分": "Resgatado {claimed}/{total} · {earned} pontos acumulados", "已领养": "Adotado", "已领取": "Resgatado", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "Resgatar “100 Credits diários” com a identidade de controle de risco do dispositivo · requer o componente UMID", "开学季执行失败:{error}": "Falha na execução de volta às aulas: {error}", "开学季执行完成:{message}": "Execução de volta às aulas concluída: {message}", "开学季活动": "Evento de volta às aulas", "开着:启用的条目按各自时刻执行": "Ligado: agendamentos habilitados rodam em seus próprios horários", "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "Ligado: agendamentos ainda não executados hoje são recuperados logo após iniciar, ignorando a janela aleatória", "待签": "Pendente", "待领新手福利": "Benefícios iniciais pendentes", "总开关": "Interruptor principal", "总开关已关闭 · 在「定时签到」页打开": "Interruptor principal desligado · ative na aba \"Check-in agendado\"", "成功 {n}": "{n} com sucesso", "成长任务": "Tarefas de crescimento", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "Tarefas de crescimento concluídas ({done} com sucesso, {failed} com falha): créditos +{credit}, energia +{energy}", "成长任务执行失败:{error}": "Falha na execução das tarefas de crescimento: {error}", "执行失败:{error}": "Falha na execução: {error}", "执行并抽奖": "Executar e sortear", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "Executar as tarefas de volta às aulas e gastar todas as chances de sorteio (compartilhar / conversar / eventos de especialista)", "把缺省链填进清单,再点「保存」生效": "Coloca a cadeia padrão na lista; clique em Salvar para aplicar", "抽奖机会 {n} 次": "{n} chances de sorteio", "按住拖动调整顺序": "Pressione e arraste para reordenar", "按住拖动,调整这个模型在链里的顺序": "Pressione e arraste para mudar a posição deste modelo na cadeia", "按序逐个尝试,共 {n} 个": "{n} modelos, tentados em ordem", "按结果筛选": "Filtrar por resultado", "探测 + 领取 + 保活 · 与定时签到同一套组合": "Detectar + resgatar + manter ativo · mesma combinação do check-in agendado", "探测活动并领取日活奖励 · 不做保活": "Detectar o evento e resgatar a recompensa de atividade diária · sem manter ativo", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "Aceitar + acender + resgatar (apenas tarefas com receita verificada)", "搜账号 / 收益 / 错误 / 触发原因": "Pesquisar conta / ganho / erro / motivo do disparo", "收起新建": "Fechar novo item", "新建定时条目": "Nova entrada agendada", "新手福利": "Benefícios iniciais", "新手福利有 {n} 项领取失败,可重试": "{n} item(ns) dos benefícios iniciais falharam no resgate — é possível tentar novamente", "无": "Nenhum", "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "Sem API de check-in dedicada · acessa o endpoint de informações de login uma vez por dia por conta (o que concede os Magicubes diários)", "无独立签到接口 · 每天替账号打一次首次登录积分": "Sem interface de check-in própria · credita uma vez por dia os pontos de primeiro login da conta", "无账号": "Sem contas", "暂不可领": "Indisponível", "暂不支持": "Ainda não suportado", "暂无启用的条目 · 点此添加": "Nenhum agendamento habilitado · clique para adicionar", "有未保存的改动": "Alterações não salvas", "未勾选提供商": "Nenhum provedor selecionado", "未开启": "Desativado", "未解锁": "Bloqueado", "未领养(领养需先完成当日对话量)": "Não adotado (a adoção exige cumprir a cota diária de conversas primeiro)", "未领取": "Não resgatado", "本地台账里今天还没领过;活动期内每天发一份新套餐": "O registro local ainda não tem resgate nenhum hoje; um novo plano é emitido todo dia durante o evento", "本地台账里今天(北京时间)领过的套餐:{plans}": "Planos resgatados hoje (horário de Pequim) conforme o registro local: {plans}", "条启用": "habilitado(s)", "查询于 {time}": "Consultado em {time}", "查询任务": "Consultar tarefas", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "Consulte a árvore de tarefas e acenda / resgate com um clique (inclui volta às aulas e viagem do gato)", "查询失败:{error}": "Falha na consulta: {error}", "桌面端每日积分链路": "Fluxo diário de pontos do aplicativo desktop", "正在读取定时签到数据…": "Carregando dados de agendamento…", "正在读取签到数据…": "Lendo os dados de check-in…", "每天 {time}": "Todos os dias às {time}", "每天 {time} · {scope}": "Diário {time} · {scope}", "每天 {time} · 随机前后 {n} 分钟 · {scope}": "Diariamente {time} ± {n} min · {scope}", "每天时刻": "Horário diário", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "Uma linha por conta a cada execução · resultados e ganhos conforme registrado pelo backend", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "Tarefas de atividade diária · uma conversa no canal web acende a atividade diária, só o resgate adiciona pontos · os dois podem ser executados separadamente", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "Pontos de login diário · resgata atividades de membro junto · contas de visitante não têm sistema de pontos (ignorado)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "Benefício diário · resgatar → confirmar → reler para verificar · redefinido no dia natural (horário de Pequim)", "每日签到": "Check-in diário", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "Cada agendamento tem horário e escopo próprios · deduplicação diária por item · execuções perdidas são compensadas ao iniciar", "每账号一条明细 · 点此查看「签到记录」": "Uma linha por conta · abra \"Registros de check-in\"", "没有可领套餐的账号(ZCode 未添加)。": "Nenhuma conta com planos resgatáveis (ZCode não adicionado).", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "Nenhuma conta com benefícios para resgatar (CodeArts / ZCode não foram adicionados).", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "Nenhuma conta suporta tarefas de crescimento (requer WorkBuddy CN).", "没有支持新手福利的账号": "Nenhuma conta suporta benefícios iniciais", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "Nenhuma conta suporta benefícios iniciais — atualmente Loomy, Raccoon e CodeArts.", "没有符合筛选条件的签到记录": "Nenhum registro de check-in corresponde aos filtros", "没有需要执行的任务": "Nada para executar", "活动福利": "Recompensas de evento", "活动(campaign)领取 · 每天 10:00 刷新": "Resgate de eventos (campaign) · atualizado todos os dias às 10:00", "活跃上报与保活均未成功,且活动未开启": "Tanto o relatório de atividade quanto o keep-alive falharam, e a campanha não está ativa", "活跃上报完成,但保活未成功且活动未开启": "Atividade reportada, mas o keep-alive falhou e a campanha não está ativa", "活跃上报完成,但活动未开启": "Atividade reportada, mas a campanha não está ativa", "活跃上报成功": "Atividade reportada com sucesso", "活跃保活失败": "Falha ao manter a atividade", "活跃保活完成": "Atividade mantida", "活跃保活完成,但活动未开启": "Atividade mantida, mas o evento não está aberto", "活跃保活完成,但活跃上报失败且活动未开启": "Keep-alive concluído, mas o relatório de atividade falhou e a campanha não está ativa", "添加条目": "Adicionar agendamento", "添加模型": "Adicionar modelo", "清单为空 —— 保存后恢复缺省链": "A lista está vazia — salvar restaura a cadeia padrão", "清单里已经有「{name}」": "A lista já contém \"{name}\"", "清空失败:{error}": "Falha ao limpar: {error}", "清空签到记录": "Limpar registros de check-in", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "Clique em \"Detalhes dos planos\" para ver quais você recebeu e quando entram em vigor; dá para resgatar de novo todo dia durante o evento", "点击行展开账号明细 · 单账号签到不受范围限制": "Clique na linha para expandir os detalhes das contas · o check-in individual não é limitado pelo escopo", "独立链路 · 只提供手动入口 · 不进自动签到": "Fluxo independente · apenas entrada manual · não participa do check-in automático", "猫猫旅行": "Viagem do gato", "猫猫旅行失败:{error}": "Falha na viagem do gato: {error}", "猫猫旅行失败:{message}": "Falha na viagem do gato: {message}", "猫猫旅行:{message}": "Viagem do gato: {message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "Manter a conta ativa com modelos gratuitos e uma conversa no canal web · sem resgatar recompensas", "确定删除「{name}」?删除后到点不再执行。": "Excluir \"{name}\"? Ele não será mais executado no horário agendado.", "确定清空全部签到记录?清空后无法恢复。": "Limpar todos os registros de check-in? Isso não pode ser desfeito.", "确定清空当前筛选出的签到记录?清空后无法恢复。": "Limpar os registros de check-in filtrados? Isso não pode ser desfeito.", "移除 {name}": "Remover {name}", "立即全部签到": "Fazer check-in de todos agora", "签到": "Check-in", "签到中…": "Fazendo check-in…", "签到中心分区": "Seções do centro de check-in", "签到失败:{error}": "Falha no check-in: {error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "Check-in concluído: {succeeded}/{total} com sucesso{active}; {failed} com falha", "签到成功": "Check-in bem-sucedido", "签到提供商": "Provedores de check-in", "签到范围": "Escopo do check-in", "签到触发时刻": "Horário de disparo do check-in", "签到记录": "Registros de check-in", "签到记录时间范围": "Período dos registros de check-in", "签到记录表": "Tabela de registros de check-in", "累计签到记录": "Total de registros de check-in", "结算于 {time}": "Liquidado em {time}", "能量 {n}": "Energia {n}", "腾讯每日签到接口 · 仅国内版": "Interface de check-in diário da Tencent · apenas edição da China", "至少勾一家才能保存(不勾等于这条条目不签到)": "Selecione ao menos um provedor para salvar (sem seleção, esta entrada não faz check-in)", "读取定时签到数据失败:{error}": "Falha ao carregar dados de agendamento: {error}", "读取签到数据失败:{error}": "Falha ao ler os dados de check-in: {error}", "读取签到记录失败:{error}": "Falha ao carregar registros de check-in: {error}", "跳过 {n}": "{n} ignorados", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "Entrega de eventos oficiais (resgatar → confirmar → reler para verificar) · resgate dos pontos de bônus do plano", "还没执行过": "Ainda não executado", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "Nenhum agendamento ainda — clique em \"Adicionar agendamento\" para criar um, ou faça check-in manualmente no \"Centro de check-in\".", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "Nenhum registro de check-in ainda — os detalhes aparecem aqui após um check-in manual ou uma execução agendada.", "连登 {n} 天": "Sequência de {n} dias", "部分": "Parcial", "重签": "Refazer check-in", "重试": "Tentar de novo", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "Plano de teste por tempo limitado · o resgate exige CAPTCHA de arrastar · veja e resgate um a um", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "Plano de teste por tempo limitado (start-plan), um por dia durante o evento · o resgate exige captcha deslizante", "随机前后": "Margem aleatória", "需真实操作": "Requer ação real", "非活动期": "Evento inativo", "项": "itens", "领取": "Resgatar", "领取中": "Resgatando", "领取中…": "Resgatando…", "领取失败": "Falha no resgate", "领取失败:{error}": "Falha no resgate: {error}", "(共 {n} 个账号)": "({n} contas no total)", "(能量 / 连登读数本次未取到)": "(Leituras de energia / sequência indisponíveis desta vez)", ",日活保活 {n} 个": ", {n} mantidas ativas" }); diff --git a/desktop-tauri/ui/i18n/zh-Hant/add-account.js b/desktop-tauri/ui/i18n/zh-Hant/add-account.js index 93b9b262..47d69dc7 100644 --- a/desktop-tauri/ui/i18n/zh-Hant/add-account.js +++ b/desktop-tauri/ui/i18n/zh-Hant/add-account.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:zh-Hant/add-account —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · 模型 {head}{rest}", " 等 {n} 个": " 等 {n} 個", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "1// 開頭的 Google refresh token(也可直接貼上 refresh_token=… 整行)", "11 位大陆手机号": "11 位大陸手機號", "1~64 个字符,账号列表里按它分组显示": "1~64 個字元,帳號列表裡按它分組顯示", "6 位数字": "6 位數字", "

  • 没有可自动领的活动
  • ": "
  • 沒有可自動領的活動
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    領到的是套餐贈送積分,不會增加福利模型的 token 池;", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "Anthropic 相容端點在 https://api.deepseek.com/anthropic(協議換 anthropic 時填它)", "Anthropic 协议填根地址,不要带 /v1": "Anthropic 協議填根地址,不要帶 /v1", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw 國內版", "AutoClaw 国际版": "AutoClaw 國際版", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS 必填;請貼上**完整 Cookie**(Cookie 編輯器一鍵匯出即可)—— 其中 **PTOKEN 必須保留**,閘道器要用它向百度換髮 KukuAI 業務會話權杖,缺了它模型重新整理會報「未登入」。支援整段 Cookie 頭、Cookie 編輯器匯出的 JSON 陣列,或 {BDUSS, STOKEN} 物件。KukuAI 沒有重新整理機制,登入態過期後重新貼上即可。", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=…(或 Cookie 編輯器匯出的 JSON)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "CatPaw 的 X-Passport-Token(登入態 Cookie)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Cline Pass 的 API Key 在 app.cline.bot 獲取(訂閱制);端點為 OpenAI 相容,模型清單以 Cline 控制台為準,模型名在模型管理裡按裸名新增(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客戶端形態校驗,所需的客戶端請求頭已隨卡預置", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT(三段點分)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT(三段點分;也可直接貼上 Bearer 整行或 data.bin 內容)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT(三段點分;也可直接貼上 chatglm_token=… 整行)", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode 國際版", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM 託管端點,Key 在 integrate.api.nvidia.com 申請", "OfficeAce 果办": "OfficeAce 果辦", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken 是 Accio 的登入憑證(一長串不透明 token,不是 JWT);refreshToken 可選,填了之後到期能自動續期。請填寫 {label}帳號的憑證 —— {siteNote}(最容易拿到的辦法:直接用上方的「網頁登入」,不需要手工找 token。)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken 是 Trae 的 Cloud-IDE-JWT(三段點分),refreshToken 用於到期自動續期(本家 refreshToken 一次一換:換髮一次舊的即作廢,所以兩份程式別同時刷同一個帳號)。
    手工貼上時請連 machineId / deviceId 一起填:上游把它們與登入時上傳的裝置公鑰綁在一起判裝置,憑空換一對會撞 2xxxx 那族裝置繫結拒絕。
    沒有這三樣時的正路是用上方的「網頁登入」;容器 / 遠端部署形態按提示貼上位址列回撥地址即可。", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "monkeycode_ai_session 的值(也可直接貼上整段 Cookie)", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken 可選,填了到期可自動續期;兩者都能從小浣熊客戶端登入態檔案裡取到。", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken 可選,填了可自動續期;兩者都能從客戶端登入態檔案取到。同一個 Cline 帳號兩個池都能用,這裡歸入 {label}。", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token 支援 enc: 字首(Windows 上自動解密)。未填 refreshToken 無法自動續期。", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "token 是登入態 Cookie;CatPaw 沒有重新整理機制,過期後需在客戶端重新登入。", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "user_ 開頭的 API Key(也可直接貼上 Authorization: Bearer … 整行)", "{label} 网页登录的打开方式": "{label} 網頁登入的開啟方式", "{label} 账号地区": "{label} 帳號地區", "{label} 账号的添加方式": "{label} 帳號的新增方式", "{name} 不是合法 JSON:{reason}": "{name} 不是合法 JSON:{reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name}要粘一個 JSON 物件(形如 {sample})", "{n} 个账号": "{n} 個帳號", "{n} 个账号,点击添加": "{n} 個帳號,點擊新增", "{seconds}s 后重发": "{seconds}s 後重發", "✅ {label}账号已添加": "✅ {label}帳號已新增", "✅ {label}账号已添加{name}": "✅ {label}帳號已新增{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ 已從 cc-switch 匯入 {n} 個供應商", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ 已建立自定義提供商「{name}」並新增帳號", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ 已刪除自定義提供商「{name}」{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ 已更新已有帳號{name}(同一把 API Key 只保留一條,重複新增會合並)", "✅ 登录成功,{edition}账号已加入列表": "✅ 登入成功,{edition}帳號已加入列表", "✅ 领取成功:{planId}{period}": "✅ 領取成功:{planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " 同一家可以放多把 key,按優先順序輪換。", "「{name}」的账号添加功能还在开发中,敬请期待。": "「{name}」的帳號新增功能還在開發中,敬請期待。", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "一個 Key 用遍多家模型,模型名用「廠商/模型」全稱(如 deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "上游不要鑑權時留空,並勾選下面一項(留空又不勾會被當成未配置憑證)", "上游信息": "上游資訊", "不可领({status})": "不可領({status})", "不支持导入": "不支援匯入", "不是有效的凭证文件:内容要是一个 JSON 对象": "不是有效的憑證檔案:內容要是一個 JSON 物件", "不是有效的凭证文件:需要包含 accessToken 与 uid": "不是有效的憑證檔案:需要包含 accessToken 與 uid", "不是自定义提供商": "不是自定義提供商", "不需要 Key:转发与拉取模型都不发送鉴权头": "不需要 Key:轉發與拉取模型都不傳送鑑權頭", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "不需要登入:點下面的按鈕,閘道器會直接在智譜清言換髮一份訪客憑證並加入帳號列表(也可以先填個備註名)。訪客憑證可以直接用來對話,免費額度由上游按裝置發放。

    注意:訪客帳號沒有積分體系 —— 它與「會員積分」「每日登入積分」「活動領取」相關的介面一律需要登入,因此那些能力對訪客會如實跳過(帳號頁的積分、簽到中心都不顯示讀數)。想要積分就用「填寫憑證」粘一個已登入帳號的權杖,或「匯入桌面版登入態」。", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "兩版帳號可同時儲存,各自一份模型清單(國內版與國際版是兩家提供商,可分別啟用與對映)。", "中国版": "中國版", "今天没有需要领的活动(都已到账)": "今天沒有需要領的活動(都已到賬)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "今天(北京時間 {day})已試 {attempts} 次,還能試 {left} 次{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "從別的機器(或 OfficeAce 桌面版 models.json)取三項貼進來:模型閘道器基址(baseUrl,形如 https://modelgw-…/v2)與 modelAppKey / modelAppSecret。這三項就能轉發(閘道器憑據不過期);控制面臨時憑據(accessKeyId 等)可選,留空則額度/自動續期不可用,但不影響轉發。", "从本机导入桌面端登录态": "從本機匯入桌面版登入態", "任务镜像 id": "任務映象 id", "余额查询": "餘額查詢", "使用 Google 账号登录": "使用 Google 帳號登入", "使用 Zai 账号登录": "使用 Zai 帳號登入", "使用个人访问令牌(PAT)": "使用個人存取權杖(PAT)", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "免費模型不用填 Key(預設勾上「該上游無需鑑權」,閘道器自動用匿名憑證);付費模型則填 Zen 的 API Key。免費檔上游只認官方客戶端形態,已預設開啟「偽裝 OpenCode 官方客戶端」", "内嵌窗口": "內嵌視窗", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "內嵌視窗開啟;關窗即取消等待(Google 帳號被拒時改用系統瀏覽器)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "內嵌視窗開啟;完成後自動加入列表,關窗即取消等待", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "內嵌視窗開啟;掃碼完成後自動加入列表,關窗即取消等待", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "內嵌視窗用全新環境,多帳號互不影響;關窗即取消等待", "内嵌窗口(推荐)": "內嵌視窗(推薦)", "准备验证…": "準備驗證…", "凭据 JSON": "憑據 JSON", "凭证文件在哪?": "憑證檔案在哪?", "创建并添加账号": "建立並新增帳號", "创建这个提供商,并同时建立它的第一个账号。": "建立這個提供商,並同時建立它的第一個帳號。", "删除功能不可用(脚本未就绪)": "刪除功能不可用(指令碼未就緒)", "删除失败:{reason}": "刪除失敗:{reason}", "删除此提供商": "刪除此提供商", "及 {n} 个账号": "及 {n} 個帳號", "发送中…": "傳送中…", "发送失败:{message}": "傳送失敗:{message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "傳送未確認:登入視窗已彈出,請在彈出的視窗中手動完成登入", "取消失败:{message}": "取消失敗:{message}", "取消等待": "取消等待", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "只有「內嵌視窗」能恢復第三方入口:系統瀏覽器裡我們無法改動登入頁", "可选": "可選", "可选(cloudaicompanionProject):留空由网关自动发现": "可選(cloudaicompanionProject):留空由閘道器自動發現", "可选,展示用": "可選,展示用", "可选,没有则无法自动续期": "可選,沒有則無法自動續期", "可选,留空使用凭据里的 user_name": "可選,留空使用憑據裡的 user_name", "可选,留空使用账号姓名、邮箱或令牌指纹": "可選,留空使用帳號姓名、郵箱或權杖指紋", "可选,留空使用账号昵称或邮箱": "可選,留空使用帳號暱稱或郵箱", "可选,留空则用 key 尾号": "可選,留空則用 key 尾號", "可选,留空则用 userId": "可選,留空則用 userId", "可选,留空则用上游返回的账号名或账号 id": "可選,留空則用上游返回的帳號名或帳號 id", "可选,留空则用凭证里的账号名": "可選,留空則用憑證裡的帳號名", "可选,留空则用文件里的昵称": "可選,留空則用檔案裡的暱稱", "可选,留空则用登录名或 uid": "可選,留空則用登入名或 uid", "可选,留空则用脱敏手机号": "可選,留空則用脫敏手機號", "可选,留空则用脱敏手机号或 userId": "可選,留空則用脫敏手機號或 userId", "可选,留空则用账号 uk": "可選,留空則用帳號 uk", "可选,留空则用账号昵称": "可選,留空則用帳號暱稱", "可选,留空则用账号昵称或 userId": "可選,留空則用帳號暱稱或 userId", "可选,留空则用邮箱或令牌尾号": "可選,留空則用郵箱或權杖尾號", "可选,留空用「OfficeAce 果办」": "可選,留空用「OfficeAce 果辦」", "可选,留空自动生成": "可選,留空自動生成", "可选,留空自动用昵称": "可選,留空自動用暱稱", "可选,给这个访客账号起个备注名": "可選,給這個訪客帳號起個備註名", "可选,续期时带上": "可選,續期時帶上", "可选,讯飞侧 userid": "可選,訊飛側 userid", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "可選:發起對話必需,留空則由閘道器從該帳號已有任務裡自動發現,發現不到時之後手動補", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "可選:帳號郵箱,用於展示與身份識別(換新權杖也能認回同一帳號)", "可选;UUID 形态,与凭据同生共死": "可選;UUID 形態,與憑據同生共死", "可选;填了才能到期自动续期": "可選;填了才能到期自動續期", "可选;用于去重与展示名(留空时网关会问一次上游)": "可選;用於去重與展示名(留空時閘道器會問一次上游)", "可选;用于生成账号 id 与展示名": "可選;用於生成帳號 id 與展示名", "可选;纯数字串(上游只收 8–24 位数字)": "可選;純數字串(上游只收 8–24 位數字)", "可领取": "可領取", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "同一家可以混著放:有 Key 的帳號與無鑑權帳號各按各的規則走;無需鑑權的帳號也能並存多條(各自可配不同的出網代理)", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "同地址換 anthropic 協議即走它的 Claude 相容端點。轉發必須填 OpenCode Go 的 API Key(訂閱制;獲取模型清單不需要 Key,但發請求上游會回 401「Missing API key」)", "响应为空": "響應為空", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "商湯日日新的 OpenAI 相容端點;餘額查詢走控制台帳號密碼(見下方「餘額查詢」一段)", "国内版": "國內版", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "國內版與**國際版是兩套獨立的帳號與套餐**,憑證與領取的套餐都不通用。", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "國內版登入頁沒有 Google / GitHub 入口(它用微信 / 手機號 / 郵箱登入)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "國內版的登入站點是 www.accio-ai.com,與國際版不是同一站。", "国内版(WorkBuddy)": "國內版(WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "國內站為 https://api.siliconflow.cn/v1", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "國內站(minimaxi.com);OpenAI 相容地址為 https://api.minimaxi.com/v1", "国际版": "國際版", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "國際版 z.ai 的 Coding 套餐;OpenAI 相容地址為 https://api.z.ai/api/coding/paas/v4", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "國際版與國內版是**兩套獨立的帳號**(同一帳號體系的兩個站點),憑證不通用。", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "國際版與國內版帳號體系獨立,請填國際版的憑證。未填 refreshToken 無法自動續期。", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "國際版登入頁預設只顯示郵箱登入,勾選後恢復 Google / GitHub / X 入口", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "國際版的推理站點是 api.z.ai,與國內版不是同一站;套餐也各自獨立。", "国际版(WorkBuddy AI)": "國際版(WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "國際站 Coding 套餐;OpenAI 相容地址為 https://api.minimax.io/v1", "在 cc-switch 里找到": "在 cc-switch 裡找到", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "在內嵌視窗裡完成官方登入,成功後自動加入帳號列表。", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "在{label}的 Qoder 帳號設定 → Integrations 生成 PAT(別填 Google / GitHub 的權杖)。兩個地區的帳號與憑證不通用。", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "在開啟的官方授權頁裡用微信掃碼登入(頁面會直接顯示二維碼)。掃碼成功後自動加入帳號列表。", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "在開啟的窗口裡用百度帳號登入 KukuAI 主站(手機驗證碼 / 掃碼均可),登入成功後自動加入帳號列表。閘道器會向百度換髮 KukuAI 業務會話權杖(依賴本機已安裝庫庫AI 客戶端)。", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "在開啟的窗口裡登入 Google 帳號(Antigravity 的授權頁),授權完成後自動加入帳號列表。", "在浏览器中打开登录页": "在瀏覽器中開啟登入頁", "地区": "地區", "填写凭证": "填寫憑證", "填写凭证添加": "填寫憑證新增", "备注名": "備註名", "套餐": "套餐", "如:智谱 GLM": "如:智譜 GLM", "完成登录后自动加入账号列表,昵称取自上游。": "完成登入後自動加入帳號列表,暱稱取自上游。", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "官方客戶端憑證目錄:Windows 是 C:\\Users\\<你的使用者名稱>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "官方已確認到賬", "导入": "匯入", "导入中…": "匯入中…", "导入凭证文件": "匯入憑證檔案", "导入失败": "匯入失敗", "导入失败:{reason}": "匯入失敗:{reason}", "导入所选": "匯入所選", "导入所选({n})": "匯入所選({n})", "导入桌面端登录态": "匯入桌面版登入態", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "將開啟內嵌視窗;授權完成後自動加入帳號列表。關掉視窗即取消等待。授權頁最後可能提示無法開啟 zcode:// 連結,這是正常的 —— 結果已由服務端記下", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "將開啟內嵌視窗;授權完成後自動加入帳號列表。遠端面板可貼上回撥地址。關掉視窗即取消等待。連結 5 分鐘內有效,超時或未點就會作廢(可重新發起)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "將開啟內嵌視窗;登入完成後自動加入帳號列表。關掉視窗即取消等待", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "將用系統預設瀏覽器開啟授權頁(會複用瀏覽器裡已登入的 Trae 帳號);同機完成後自動加入,Docker / 遠端面板按提示貼上位址列回撥地址。", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "將用系統預設瀏覽器開啟授權頁(會複用瀏覽器裡已登入的 ZCode 帳號);授權完成後自動加入帳號列表。頁面最後可能提示無法開啟 zcode:// 連結,屬正常現象", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "將用系統預設瀏覽器開啟授權頁(會複用瀏覽器裡已登入的華為雲帳號);授權碼由閘道器輪詢雲端取回,與瀏覽器跑在哪臺機器無關,完成後自動加入帳號列表", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "將用系統預設瀏覽器開啟授權頁(會複用瀏覽器裡已登入的華為雲帳號);瀏覽器與閘道器不在同一臺機器時,按上方說明把最終回撥地址貼上回面板", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "將用系統預設瀏覽器開啟登入頁(會複用瀏覽器裡已登入的 Accio 帳號);完成登入後自動加入帳號列表,關掉彈窗即取消等待", "小米 MiMo Token Plan 套餐(新加坡站)": "小米 MiMo Token Plan 套餐(新加坡站)", "已到账": "已到賬", "已取消登录等待": "已取消登入等待", "已取消领取": "已取消領取", "已取消验证码": "已取消驗證碼", "已填写手机号,正在发送验证码…": "已填寫手機號,正在傳送驗證碼…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "已宣告無需鑑權:帳號會被正常選路,出網時不帶任何鑑權頭", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "已匯入 {ok} 個,失敗 {fail} 個(失敗項已標註在列表裡)", "已建过 · {n} 个账号,点击继续添加": "已建過 · {n} 個帳號,點擊繼續新增", "已建过,点击继续添加账号": "已建過,點擊繼續新增帳號", "已打开官方登录页,请在窗口中完成登录…": "已開啟官方登入頁,請在視窗中完成登入…", "已点发送,等待短信…": "已點發送,等待簡訊…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "已用系統預設瀏覽器開啟登入頁,請在瀏覽器中完成登入…", "已领取,等官方确认": "已領取,等官方確認", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "當前殼版本不支援 AutoClaw 網頁登入,請更新應用", "当前没有可领取的套餐(活动尚未开始)": "當前沒有可領取的套餐(活動尚未開始)", "当前环境不支持领取(桥接方法缺失)": "當前環境不支援領取(橋接方法缺失)", "必填,CatPaw 账号标识": "必填,CatPaw 帳號標識", "恢复 Google / GitHub 入口": "恢復 Google / GitHub 入口", "手机号": "手機號", "手机验证码登录": "手機驗證碼登入", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "開啟 Trae SOLO 的官方授權頁(trae.cn)並用你的 Trae 帳號登入:授權完成後官方頁面會跳回本機的一個臨時連接埠;同機部署自動接收,Docker / 遠端面板請按提示覆制位址列回撥地址。", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "開啟 Accio {label}的官方登入頁({site})並用你的 Accio 帳號登入:登入成功後官方頁面會跳回本機;同機自動完成,Docker / 遠端面板按提示貼上回撥地址即可(授權碼只在本機傳給閘道器,介面不顯示明文 token)。", "打开 Accio {label}登录页": "開啟 Accio {label}登入頁", "打开 Antigravity 网页登录": "開啟 Antigravity 網頁登入", "打开 CatPaw 网页登录": "開啟 CatPaw 網頁登入", "打开 Cline 授权页": "開啟 Cline 授權頁", "打开 CodeArts 授权页": "開啟 CodeArts 授權頁", "打开 Qoder 网页登录": "開啟 Qoder 網頁登入", "打开 Trae 授权页": "開啟 Trae 授權頁", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "開啟 ZCode {label}的官方授權頁並用你的帳號登入。授權結果由 ZCode 服務端記錄,閘道器在後臺自動取回憑證並加入帳號列表。", "打开 ZCode {label}授权页": "開啟 ZCode {label}授權頁", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "開啟華為雲 CodeArts 的官方授權頁登入:登入完成後官方頁面會把瀏覽器帶回閘道器自己的 /oauth/callback,閘道器用一次性授權碼換取臨時憑據並加入帳號列表。
    閘道器跑在另一臺機器上時,網頁端會提示把位址列中的最終回撥地址直接貼上回面板。", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "開啟華為雲授權頁登入:登入完成後閘道器會自動輪詢雲端取回授權碼並加入帳號列表(不需要裝 OfficeAce 桌面版,也無需手工回填回撥地址)。", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "開啟官方授權頁完成裝置碼授權,登入的是{label}({site})的帳號。", "打开授权页": "開啟授權頁", "打开授权页完成确认,账号自动加入 {label}{note}": "開啟授權頁完成確認,帳號自動加入 {label}{note}", "打开方式": "開啟方式", "打开网页登录": "開啟網頁登入", "探测失败:{message}": "探測失敗:{message}", "接入一个兼容上游": "接入一個相容上游", "提交中…": "提交中…", "搜索提供商": "搜尋提供商", "搜索提供商…": "搜尋提供商…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "整份貼上官方外掛 / CLIProxyAPI 落盤的憑據 JSON(形如 {\"codearts_provider_credential\":{…}},鋪平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自動續期,必須連 refresh_token 與 oauth_context 一起粘 —— 臨時憑據約一小時到期,缺這半塊就續不回來,只能重新登入。", "文件是{edition}凭证,已按该版本导入": "檔案是{edition}憑證,已按該版本匯入", "新建自定义提供商": "新建自定義提供商", "方案:{label}": "方案:{label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "明文 JWT 或 auth.json 裡的 enc: 加密值(自動解密)", "明文 JWT(国际版账号的 access token)": "明文 JWT(國際版帳號的 access token)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "智譜 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys", "未知错误": "未知錯誤", "未能获取授权地址,请重试": "未能獲取授權地址,請重試", "未能读取 cc-switch 数据": "未能讀取 cc-switch 資料", "未领取成功": "未領取成功", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "本地 Ollama、OpenCode Zen 免費檔這類上游要勾上,否則帳號不可用", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "本家有兩個**互不替代**的憑證,按你要用的功能填,至少填一個:編碼套餐 API Key 用於轉發推理(打 {site})與查詢視窗限額(每 N 小時 / 每週的剩餘比例);jwt 用於領取套餐與查詢餘額(打 zcode.z.ai 的 billing 閘道器,官方叫 Coding Plan JWT,是一串三段點分的字串)。餘額兩把都能查、但讀到的東西不同:jwt 讀到餘額桶與套餐到期,API Key 讀到視窗限額;而領取只認 jwt、轉發只認 API Key。請填寫 {label}帳號的憑證 —— {plan}(最容易拿到的辦法:直接用上方的「網頁登入」—— 它會替你把這個 API Key 換好,兩個憑證一起拿到。)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "本機 Ollama 的 OpenAI 相容端點,無需 API Key(預設已勾上「該上游無需鑑權」,鑑權頭一個都不發)", "本次未确认到账": "本次未確認到賬", "条可导入": "條可匯入", "条配置,其中": "條配置,其中", "桌面运行时不可用(Tauri 未初始化)": "桌面執行時不可用(Tauri 未初始化)", "模型网关基址": "模型閘道器基址", "正在打开百度登录页…": "正在開啟百度登入頁…", "正在扫描本机 cc-switch…": "正在掃描本機 cc-switch…", "正在换发访客凭证…": "正在換髮訪客憑證…", "正在添加…": "正在新增…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "正在等待{name}登入完成;完成或取消後才能發起新的登入", "每周": "每週", "每日": "每日", "每月": "每月", "没有则无法自动续期": "沒有則無法自動續期", "没有匹配「{keyword}」的提供商": "沒有匹配「{keyword}」的提供商", "添加 {name} 账号": "新增 {name} 帳號", "添加中…": "新增中…", "添加到 ": "新增到 ", "添加失败:{reason}": "新增失敗:{reason}", "添加小浣熊账号": "新增小浣熊帳號", "添加方式": "新增方式", "添加访客账号": "新增訪客帳號", "添加账号": "新增帳號", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "火山引擎 Coding 套餐;通用推理接入點為 https://ark.cn-beijing.volces.com/api/v3", "点击添加账号": "點擊新增帳號", "点开即预填,填 Key 接入": "點開即預填,填 Key 接入", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "點按鈕後先過一次滑塊驗證(官方風控),隨後開啟登入頁,登入完成即自動新增帳號。
    這是國際版官方唯一的登入方式;已在客戶端登入過的,用「匯入桌面版登入態」更快。", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "用 AutoClaw 帳號繫結的手機號登入:點擊「獲取驗證碼」,收到簡訊後填入下方並登入。驗證碼由本機直接提交給官方介面,介面不顯示 token。", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "用 CatPaw 帳號完成登入(美團 passport),成功後自動加入帳號列表。", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "用 Loomy 帳號繫結的手機號登入:點「獲取驗證碼」後填入即可。這是本家最省事的入口。", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "用於轉發;形如 apiKey.secret 兩段點分(不填則這個帳號不能轉發)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "用於領取套餐與查詢餘額;不填則這個帳號不能領取與查餘額", "用户 ID": "使用者 ID", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "用繫結的手機號登入:點「獲取驗證碼」後填入即可。這是國內版官方唯一的登入方式。", "留空则用提供商名称": "留空則用提供商名稱", "登录 / 添加 {name} 账号": "登入 / 新增 {name} 帳號", "登录 session(一长串)": "登入 session(一長串)", "登录中…": "登入中…", "登录失败:{message}": "登入失敗:{message}", "登录已结束": "登入已結束", "登录并添加": "登入並新增", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "登入態檔案路徑:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的使用者名稱>\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "確定刪除自定義提供商「{name}」?將同時刪除該提供商下 {count} 個帳號,刪除後無法恢復。", "等待 Accio {label}登录完成…": "等待 Accio {label}登入完成…", "等待 CatPaw 登录完成…": "等待 CatPaw 登入完成…", "等待 Cline 授权确认…": "等待 Cline 授權確認…", "等待 CodeArts 登录完成…": "等待 CodeArts 登入完成…", "等待 Google 授权完成…": "等待 Google 授權完成…", "等待 KukuAI 登录完成…": "等待 KukuAI 登入完成…", "等待 OfficeAce 登录完成…": "等待 OfficeAce 登入完成…", "等待 OrcaTerm 登录完成…": "等待 OrcaTerm 登入完成…", "等待 Qoder 授权完成…": "等待 Qoder 授權完成…", "等待 Trae 授权完成…": "等待 Trae 授權完成…", "等待 ZCode {label}授权完成…": "等待 ZCode {label}授權完成…", "等待小浣熊登录完成…": "等待小浣熊登入完成…", "等待登录完成…": "等待登入完成…", "等待网页登录…": "等待網頁登入…", "粘贴 API Key": "貼上 API Key", "粘贴 Accio 的 accessToken": "貼上 Accio 的 accessToken", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "貼上 Antigravity 的 Google refresh token(以 1// 開頭;直接貼上含 refresh_token= 的整行也行)。
    這是網頁登入之外的手工入口(例如從已登入的官方 IDE 裡匯出)。refresh token 不會過期,access token 到期由閘道器自動續期;權杖丟了只能重新走 Google 授權,請妥善儲存。", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "貼上 Command Code 的 API Key(user_ 開頭;從官方 CLI 的 ~/.commandcode/auth.json 或網頁 studio 獲取)。整行 / 帶引號 / 帶 Bearer 字首地粘都行,閘道器會自己剝成裸 key。key 不過期、也沒有續期介面,失效後重新獲取即可;新增時閘道器會做一次輕量探活,失敗不影響新增。", "粘贴 Cookie": "貼上 Cookie", "粘贴 Google refresh token": "貼上 Google refresh token", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "貼上 OrcaTerm 的 OAuth accessToken(JWT,三段點分;從桌面客戶端 data.bin 或 Web 版 Cookie ot_session 獲取)。直接貼上含 Bearer / ot_session= 的整行也行,閘道器會自己剝成裸 token。新增後由閘道器自動續期(上游有續期介面),無需跟隨 2 小時時效手動更換。", "粘贴 Qoder 个人访问令牌(pt-…)": "貼上 Qoder 個人存取權杖(pt-…)", "粘贴 accessToken": "貼上 accessToken", "粘贴 access_token(一长串 JWT)": "貼上 access_token(一長串 JWT)", "粘贴 session cookie": "貼上 session cookie", "粘贴 token / refreshToken": "貼上 token / refreshToken", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "貼上 workos:… 開頭的權杖(不帶字首也會自動補上)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "貼上智譜清言的存取權杖(JWT,三段點分)。獲取方式:瀏覽器開啟 chatglm.cn 並登入後,在開發者工具的 Application → Cookies 裡複製 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘貼後會先向上游校驗一次,校驗通過才落帳號;登入帳號的積分、簽到能力都能用,之後由閘道器自動續期(上游有續期介面)。", "粘贴登录凭据": "貼上登入憑據", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "貼上的是登入 session(同時是模型閘道器的 token)。Loomy 沒有續期介面,session 有效期約 14 天,過期後重新登入即可。", "粘贴网关凭据": "貼上閘道器憑據", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "貼上網頁登入態 cookie monkeycode_ai_session 的值(在瀏覽器裡複製整段 Cookie 直接貼上也行,閘道器會自己剝出值)。
    {siteNote}
    MonkeyCode 沒有續期介面:session 有效期約 30 天(硬限制),過期後重新登入網頁、再貼上一次即可。", "粘贴访问令牌": "貼上存取權杖", "系统浏览器": "系統瀏覽器", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "系統瀏覽器可複用已有登入態(國際版推薦);內嵌視窗更乾淨。", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入的 Cline 帳號);完成後自動加入列表", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入的 Google 帳號);完成後自動加入列表", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入的 Zai / Google 帳號);完成後自動加入列表", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入的美團帳號);完成後自動加入列表", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入帳號);完成後自動加入列表", "系统默认浏览器": "系統預設瀏覽器", "编码套餐 API Key": "編碼套餐 API Key", "网关 Secret": "閘道器 Secret", "网页登录": "網頁登入", "网页登录的打开方式": "網頁登入的開啟方式", "网页登录(Zai / Google)": "網頁登入(Zai / Google)", "自定义": "自定義", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "自建聚合面板:填你自己的站點地址。餘額查詢用該帳號的 API Key 打 {base}/v1/usage,不需要額外配置", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "自建聚合面板:填你自己的站點地址;餘額查詢要另填 NewAPI 的個人存取權杖(見下方「餘額查詢」一段)", "获取风控配置失败,将直接尝试领取:{message}": "獲取風控配置失敗,將直接嘗試領取:{message}", "获取验证码": "獲取驗證碼", "访客模式": "訪客模式", "访客模式(免登录)": "訪客模式(免登入)", "该上游无需鉴权(不发送鉴权头)": "該上游無需鑑權(不傳送鑑權頭)", "该提供商": "該提供商", "该提供商账号添加功能即将上线": "該提供商帳號新增功能即將上線", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "該自定義提供商已不存在(可能已被刪除),請重新整理後重試", "请先选择一个自定义提供商": "請先選擇一個自定義提供商", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "請在彈出的滑塊中完成驗證(官方要求的風控步驟)", "请填写 11 位大陆手机号": "請填寫 11 位大陸手機號", "请填写 6 位数字验证码": "請填寫 6 位數字驗證碼", "请填写 Base URL": "請填寫 Base URL", "请填写 {label}": "請填寫 {label}", "请填写名称": "請填寫名稱", "请完成验证…": "請完成驗證…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "讀取 %APPDATA%/AutoClaw/auth.json 並解密,僅 Windows", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "讀取 ~/.cline/data/settings/providers.json,需已在 Cline 客戶端登入", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "讀取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客戶端登入", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "讀取本機 KukuAI 客戶端登入態(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客戶端登入", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "讀取本機 OrcaTerm 客戶端登入態(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客戶端登入", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "讀取本機智譜清言客戶端登入態(%APPDATA%\\chatglm\\Network\\Cookies),需已在客戶端登入", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "讀本機官方客戶端(Tencent WorkBuddy / WorkBuddy AI)當前登入的帳號:自動定位其憑證目錄裡最新的登入態檔案(需已在本機官方客戶端登入)。匯入後由閘道器自動續期,無需跟隨 2 小時時效手動換權杖。", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "讀本機客戶端當前登入態(明文 Cookie,無需解密)。客戶端執行時 Cookies 檔案被獨佔佔用,匯入前請先關閉 KukuAI 客戶端。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。客戶端重新登入後點「重新整理 Token」同步。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。客戶端重新登入後重新匯入即可。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。用 Zai / Google 登入客戶端的使用者走這一條。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。這一條歸入 {label}。", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "讀本機客戶端當前登入的 OAuth 權杖(明文 JSON,無需解密)。匯入後由閘道器自動續期,無需跟隨客戶端的 2 小時時效手動換權杖。", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "讀本機客戶端當前的登入態。客戶端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此僅 Windows 可用;客戶端正在執行時可能讀不到該檔案,先退出客戶端再試即可(也可改用「填寫憑證」貼上權杖)。", "账号信息": "帳號資訊", "账号信息不完整,请刷新后重试": "帳號資訊不完整,請重新整理後重試", "账号已添加,但请留意:{warning}": "帳號已新增,但請留意:{warning}", "账号版本": "帳號版本", "账号类型": "帳號型別", "账号:{name}
    ": "帳號:{name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 建立", "还没有账号": "還沒有帳號", "这一家当前不支持网页登录,请改用填写凭证": "這一家當前不支援網頁登入,請改用填寫憑證", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "這個帳號當前沒有可自動領的活動(只自動領每日登入贈送積分)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "這份額度走「活動套餐」通道:若轉發時提示編碼套餐已到期,", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "這裡填國內站(monkeycode-ai.com)的帳號:請貼上國內站的 session。國際站(monkeycode-ai.net)是另一家 provider、另一套帳號,兩邊的憑證不通用。", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "這裡填國際站(monkeycode-ai.net)的帳號:請貼上國際站的 session。國內站(monkeycode-ai.com)是另一家 provider、另一套帳號,兩邊的憑證不通用。", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "選擇 CatPaw 客戶端的登入態檔案 auth.json(Windows:C:\\Users\\<你的使用者名稱>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。匯入後憑證直接落在閘道器、可獨立轉發,不再依賴本機客戶端。", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "選擇 Cline 客戶端的登入態檔案 providers.json(Windows:C:\\Users\\<你的使用者名稱>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。匯入後憑證直接落在閘道器、可獨立轉發,不再依賴本機客戶端;這一條歸入 {label}。", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "選擇 KukuAI 客戶端的 Cookies 檔案(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二進位制** SQLite 資料庫(無副檔名,不是 JSON)。匯入時讀的是你選中檔案的副本、不和執行中的客戶端搶佔用,因此**無需先關閉客戶端**。匯入後憑證直接落在閘道器、可獨立轉發。", "选择凭证文件导入": "選擇憑證檔案匯入", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "選擇官方客戶端的登入態憑證檔案(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 匯出的帳號 JSON(巢狀 / 扁平形均可)。", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "選擇小浣熊客戶端的登入態檔案 auth.json(Windows:C:\\Users\\<你的使用者名稱>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。匯入後憑證直接落在閘道器、可獨立轉發,不再依賴本機客戶端。", "选择提供商": "選擇提供商", "选择的文件不是合法 JSON": "選擇的檔案不是合法 JSON", "选择要添加账号的提供商": "選擇要新增帳號的提供商", "重新扫描": "重新掃描", "鉴权": "鑑權", "阿里云 Token Plan 套餐(国际站)": "阿里雲 Token Plan 套餐(國際站)", "阿里云百炼 Coding 套餐(国内站)": "阿里雲百鍊 Coding 套餐(國內站)", "阿里云百炼 Coding 套餐(国际站)": "阿里雲百鍊 Coding 套餐(國際站)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "阿里雲百鍊模型服務(國際站,OpenAI 相容模式)", "需要图形验证码:登录窗口已弹出,请填写后继续": "需要圖形驗證碼:登入視窗已彈出,請填寫後繼續", "预置 API": "預置 API", "领取 CodeArts 每日福利": "領取 CodeArts 每日福利", "领取失败:{message}": "領取失敗:{message}", "领取并让官方确认": "領取並讓官方確認", "风控验证配置不完整,请稍后重试": "風控驗證配置不完整,請稍後重試", "验证码": "驗證碼", "验证码已发送。收到后填入下方并点「登录并添加」": "驗證碼已傳送。收到後填入下方並點「登入並新增」", "验证码已发送,请查看手机短信": "驗證碼已傳送,請檢視手機簡訊", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "驗證碼已傳送,請檢視手機簡訊。填入下方並點「登入並新增」即完成登入", "验证码已发送,请查看短信": "驗證碼已傳送,請檢視簡訊", "验证码校验失败,请重试": "驗證碼校驗失敗,請重試", "验证码校验超时,请重试": "驗證碼校驗超時,請重試", "验证码组件不可用,请重试": "驗證碼元件不可用,請重試", "验证码组件初始化超时,请重试": "驗證碼元件初始化超時,請重試", "验证码组件加载失败,请检查网络后重试": "驗證碼元件載入失敗,請檢查網路後重試", "验证码组件加载异常,请重试": "驗證碼元件載入異常,請重試", "验证码组件加载超时,请检查网络后重试": "驗證碼元件載入超時,請檢查網路後重試", "验证码组件未加载,请重启应用后重试": "驗證碼元件未載入,請重啟應用後重試", "(免费额度池,模型名带 cline-free/ 前缀)。": "(免費額度池,模型名帶 cline-free/ 字首)。", "(其中 {n} 把恢复为不限制)": "(其中 {n} 把恢復為不限制)", "(必填)": "(必填)", "(有效期 {window})": "(有效期 {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": "(訂閱池,模型名帶 cline-pass/ 字首,需要帳號有對應訂閱)。", ",下一次最快 {minutes} 分钟后": ",下一次最快 {minutes} 分鐘後", ",并从 {n} 把 Key 的可用提供商里移除": ",並從 {n} 把 Key 的可用提供商裡移除" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · 模型 {head}{rest}": " · 模型 {head}{rest}", " 等 {n} 个": " 等 {n} 個", "1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)": "1// 開頭的 Google refresh token(也可直接貼上 refresh_token=… 整行)", "11 位大陆手机号": "11 位大陸手機號", "1~64 个字符,账号列表里按它分组显示": "1~64 個字元,帳號列表裡按它分組顯示", "6 位数字": "6 位數字", "

  • 没有可自动领的活动
  • ": "
  • 沒有可自動領的活動
  • ", "

    领到的是套餐赠送积分,不会增加福利模型的 token 池;": "

    領到的是套餐贈送積分,不會增加福利模型的 token 池;", "Anthropic 兼容端点在 https://api.deepseek.com/anthropic(协议换 anthropic 时填它)": "Anthropic 相容端點在 https://api.deepseek.com/anthropic(協議換 anthropic 時填它)", "Anthropic 协议填根地址,不要带 /v1": "Anthropic 協議填根地址,不要帶 /v1", "Antigravity": "Antigravity", "AutoClaw 国内版": "AutoClaw 國內版", "AutoClaw 国际版": "AutoClaw 國際版", "BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。": "BDUSS 必填;請貼上**完整 Cookie**(Cookie 編輯器一鍵匯出即可)—— 其中 **PTOKEN 必須保留**,閘道器要用它向百度換髮 KukuAI 業務會話權杖,缺了它模型重新整理會報「未登入」。支援整段 Cookie 頭、Cookie 編輯器匯出的 JSON 陣列,或 {BDUSS, STOKEN} 物件。KukuAI 沒有重新整理機制,登入態過期後重新貼上即可。", "BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)": "BDUSS=…; STOKEN=…(或 Cookie 編輯器匯出的 JSON)", "CatPaw 的 X-Passport-Token(登录态 Cookie)": "CatPaw 的 X-Passport-Token(登入態 Cookie)", "Cline Pass 的 API Key 在 app.cline.bot 获取(订阅制);端点为 OpenAI 兼容,模型清单以 Cline 控制台为准,模型名在模型管理里按裸名添加(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客户端形态校验,所需的客户端请求头已随卡预置": "Cline Pass 的 API Key 在 app.cline.bot 獲取(訂閱制);端點為 OpenAI 相容,模型清單以 Cline 控制台為準,模型名在模型管理裡按裸名新增(如 glm-5.2 / kimi-k2.7-code / deepseek-v4-pro);上游按客戶端形態校驗,所需的客戶端請求頭已隨卡預置", "Cloud-IDE-JWT(三段点分)": "Cloud-IDE-JWT(三段點分)", "Command Code": "Command Code", "JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)": "JWT(三段點分;也可直接貼上 Bearer 整行或 data.bin 內容)", "JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)": "JWT(三段點分;也可直接貼上 chatglm_token=… 整行)", "ModelScope 国内版": "ModelScope 國內版", "ModelScope 国际版": "ModelScope 國際版", "MonkeyCode": "MonkeyCode", "MonkeyCode 国际版": "MonkeyCode 國際版", "NVIDIA NIM 托管端点,Key 在 integrate.api.nvidia.com 申请": "NVIDIA NIM 託管端點,Key 在 integrate.api.nvidia.com 申請", "OfficeAce 果办": "OfficeAce 果辦", "accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)": "accessToken 是 Accio 的登入憑證(一長串不透明 token,不是 JWT);refreshToken 可選,填了之後到期能自動續期。請填寫 {label}帳號的憑證 —— {siteNote}(最容易拿到的辦法:直接用上方的「網頁登入」,不需要手工找 token。)", "accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。": "accessToken 是 Trae 的 Cloud-IDE-JWT(三段點分),refreshToken 用於到期自動續期(本家 refreshToken 一次一換:換髮一次舊的即作廢,所以兩份程式別同時刷同一個帳號)。
    手工貼上時請連 machineId / deviceId 一起填:上游把它們與登入時上傳的裝置公鑰綁在一起判裝置,憑空換一對會撞 2xxxx 那族裝置繫結拒絕。
    沒有這三樣時的正路是用上方的「網頁登入」;容器 / 遠端部署形態按提示貼上位址列回撥地址即可。", "monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)": "monkeycode_ai_session 的值(也可直接貼上整段 Cookie)", "ms- 开头的 API 令牌": "ms- 開頭的 API 權杖", "refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。": "refreshToken 可選,填了到期可自動續期;兩者都能從小浣熊客戶端登入態檔案裡取到。", "refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。": "refreshToken 可選,填了可自動續期;兩者都能從客戶端登入態檔案取到。同一個 Cline 帳號兩個池都能用,這裡歸入 {label}。", "token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。": "token 支援 enc: 字首(Windows 上自動解密)。未填 refreshToken 無法自動續期。", "token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。": "token 是登入態 Cookie;CatPaw 沒有重新整理機制,過期後需在客戶端重新登入。", "user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)": "user_ 開頭的 API Key(也可直接貼上 Authorization: Bearer … 整行)", "{label} 网页登录的打开方式": "{label} 網頁登入的開啟方式", "{label} 账号地区": "{label} 帳號地區", "{label} 账号的添加方式": "{label} 帳號的新增方式", "{name} 不是合法 JSON:{reason}": "{name} 不是合法 JSON:{reason}", "{name}要粘一个 JSON 对象(形如 {sample})": "{name}要粘一個 JSON 物件(形如 {sample})", "{n} 个账号": "{n} 個帳號", "{n} 个账号,点击添加": "{n} 個帳號,點擊新增", "{seconds}s 后重发": "{seconds}s 後重發", "✅ {label}账号已添加": "✅ {label}帳號已新增", "✅ {label}账号已添加{name}": "✅ {label}帳號已新增{name}", "✅ 已从 cc-switch 导入 {n} 个供应商": "✅ 已從 cc-switch 匯入 {n} 個供應商", "✅ 已创建自定义提供商「{name}」并添加账号": "✅ 已建立自定義提供商「{name}」並新增帳號", "✅ 已删除自定义提供商「{name}」{accounts}{keys}": "✅ 已刪除自定義提供商「{name}」{accounts}{keys}", "✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)": "✅ 已更新已有帳號{name}(同一把 API Key 只保留一條,重複新增會合並)", "✅ 登录成功,{edition}账号已加入列表": "✅ 登入成功,{edition}帳號已加入列表", "✅ 领取成功:{planId}{period}": "✅ 領取成功:{planId}{period}", " 同一家可以放多把 key,按优先级轮换。": " 同一家可以放多把 key,按優先順序輪換。", "「{name}」的账号添加功能还在开发中,敬请期待。": "「{name}」的帳號新增功能還在開發中,敬請期待。", "一个 Key 用遍多家模型,模型名用「厂商/模型」全称(如 deepseek/deepseek-chat)": "一個 Key 用遍多家模型,模型名用「廠商/模型」全稱(如 deepseek/deepseek-chat)", "上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)": "上游不要鑑權時留空,並勾選下面一項(留空又不勾會被當成未配置憑證)", "上游信息": "上游資訊", "不可领({status})": "不可領({status})", "不支持导入": "不支援匯入", "不是有效的凭证文件:内容要是一个 JSON 对象": "不是有效的憑證檔案:內容要是一個 JSON 物件", "不是有效的凭证文件:需要包含 accessToken 与 uid": "不是有效的憑證檔案:需要包含 accessToken 與 uid", "不是自定义提供商": "不是自定義提供商", "不需要 Key:转发与拉取模型都不发送鉴权头": "不需要 Key:轉發與拉取模型都不傳送鑑權頭", "不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。": "不需要登入:點下面的按鈕,閘道器會直接在智譜清言換髮一份訪客憑證並加入帳號列表(也可以先填個備註名)。訪客憑證可以直接用來對話,免費額度由上游按裝置發放。

    注意:訪客帳號沒有積分體系 —— 它與「會員積分」「每日登入積分」「活動領取」相關的介面一律需要登入,因此那些能力對訪客會如實跳過(帳號頁的積分、簽到中心都不顯示讀數)。想要積分就用「填寫憑證」粘一個已登入帳號的權杖,或「匯入桌面版登入態」。", "两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。": "兩版帳號可同時儲存,各自一份模型清單(國內版與國際版是兩家提供商,可分別啟用與對映)。", "中国版": "中國版", "今天没有需要领的活动(都已到账)": "今天沒有需要領的活動(都已到賬)", "今天(北京时间 {day})已试 {attempts} 次,还能试 {left} 次{next}
    ": "今天(北京時間 {day})已試 {attempts} 次,還能試 {left} 次{next}
    ", "从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。": "從別的機器(或 OfficeAce 桌面版 models.json)取三項貼進來:模型閘道器基址(baseUrl,形如 https://modelgw-…/v2)與 modelAppKey / modelAppSecret。這三項就能轉發(閘道器憑據不過期);控制面臨時憑據(accessKeyId 等)可選,留空則額度/自動續期不可用,但不影響轉發。", "从本机导入桌面端登录态": "從本機匯入桌面版登入態", "任务镜像 id": "任務映象 id", "余额查询": "餘額查詢", "使用 Google 账号登录": "使用 Google 帳號登入", "使用 Zai 账号登录": "使用 Zai 帳號登入", "使用个人访问令牌(PAT)": "使用個人存取權杖(PAT)", "免费模型不用填 Key(默认勾上「该上游无需鉴权」,网关自动用匿名凭证);付费模型则填 Zen 的 API Key。免费档上游只认官方客户端形态,已默认开启「伪装 OpenCode 官方客户端」": "免費模型不用填 Key(預設勾上「該上游無需鑑權」,閘道器自動用匿名憑證);付費模型則填 Zen 的 API Key。免費檔上游只認官方客戶端形態,已預設開啟「偽裝 OpenCode 官方客戶端」", "内嵌窗口": "內嵌視窗", "内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)": "內嵌視窗開啟;關窗即取消等待(Google 帳號被拒時改用系統瀏覽器)", "内嵌窗口打开;完成后自动加入列表,关窗即取消等待": "內嵌視窗開啟;完成後自動加入列表,關窗即取消等待", "内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待": "內嵌視窗開啟;掃碼完成後自動加入列表,關窗即取消等待", "内嵌窗口用全新环境,多账号互不影响;关窗即取消等待": "內嵌視窗用全新環境,多帳號互不影響;關窗即取消等待", "内嵌窗口(推荐)": "內嵌視窗(推薦)", "准备验证…": "準備驗證…", "凭据 JSON": "憑據 JSON", "凭证文件在哪?": "憑證檔案在哪?", "创建并添加账号": "建立並新增帳號", "创建这个提供商,并同时建立它的第一个账号。": "建立這個提供商,並同時建立它的第一個帳號。", "删除功能不可用(脚本未就绪)": "刪除功能不可用(指令碼未就緒)", "删除失败:{reason}": "刪除失敗:{reason}", "删除此提供商": "刪除此提供商", "及 {n} 个账号": "及 {n} 個帳號", "发送中…": "傳送中…", "发送失败:{message}": "傳送失敗:{message}", "发送未确认:登录窗口已弹出,请在弹出的窗口中手动完成登录": "傳送未確認:登入視窗已彈出,請在彈出的視窗中手動完成登入", "取消失败:{message}": "取消失敗:{message}", "取消等待": "取消等待", "只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页": "只有「內嵌視窗」能恢復第三方入口:系統瀏覽器裡我們無法改動登入頁", "可选": "可選", "可选(cloudaicompanionProject):留空由网关自动发现": "可選(cloudaicompanionProject):留空由閘道器自動發現", "可选,展示用": "可選,展示用", "可选,没有则无法自动续期": "可選,沒有則無法自動續期", "可选,留空使用凭据里的 user_name": "可選,留空使用憑據裡的 user_name", "可选,留空使用账号姓名、邮箱或令牌指纹": "可選,留空使用帳號姓名、郵箱或權杖指紋", "可选,留空使用账号昵称或邮箱": "可選,留空使用帳號暱稱或郵箱", "可选,留空则用 key 尾号": "可選,留空則用 key 尾號", "可选,留空则用 userId": "可選,留空則用 userId", "可选,留空则用上游账号昵称": "可選,留空則用上游帳號暱稱", "可选,留空则用上游返回的账号名或账号 id": "可選,留空則用上游返回的帳號名或帳號 id", "可选,留空则用凭证里的账号名": "可選,留空則用憑證裡的帳號名", "可选,留空则用文件里的昵称": "可選,留空則用檔案裡的暱稱", "可选,留空则用登录名或 uid": "可選,留空則用登入名或 uid", "可选,留空则用脱敏手机号": "可選,留空則用脫敏手機號", "可选,留空则用脱敏手机号或 userId": "可選,留空則用脫敏手機號或 userId", "可选,留空则用账号 uk": "可選,留空則用帳號 uk", "可选,留空则用账号昵称": "可選,留空則用帳號暱稱", "可选,留空则用账号昵称或 userId": "可選,留空則用帳號暱稱或 userId", "可选,留空则用邮箱或令牌尾号": "可選,留空則用郵箱或權杖尾號", "可选,留空用「OfficeAce 果办」": "可選,留空用「OfficeAce 果辦」", "可选,留空自动生成": "可選,留空自動生成", "可选,留空自动用昵称": "可選,留空自動用暱稱", "可选,给这个访客账号起个备注名": "可選,給這個訪客帳號起個備註名", "可选,续期时带上": "可選,續期時帶上", "可选,讯飞侧 userid": "可選,訊飛側 userid", "可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补": "可選:發起對話必需,留空則由閘道器從該帳號已有任務裡自動發現,發現不到時之後手動補", "可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)": "可選:帳號郵箱,用於展示與身份識別(換新權杖也能認回同一帳號)", "可选;UUID 形态,与凭据同生共死": "可選;UUID 形態,與憑據同生共死", "可选;填了才能到期自动续期": "可選;填了才能到期自動續期", "可选;用于去重与展示名(留空时网关会问一次上游)": "可選;用於去重與展示名(留空時閘道器會問一次上游)", "可选;用于生成账号 id 与展示名": "可選;用於生成帳號 id 與展示名", "可选;纯数字串(上游只收 8–24 位数字)": "可選;純數字串(上游只收 8–24 位數字)", "可领取": "可領取", "同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)": "同一家可以混著放:有 Key 的帳號與無鑑權帳號各按各的規則走;無需鑑權的帳號也能並存多條(各自可配不同的出網代理)", "同地址换 anthropic 协议即走它的 Claude 兼容端点。转发必须填 OpenCode Go 的 API Key(订阅制;获取模型清单不需要 Key,但发请求上游会回 401「Missing API key」)": "同地址換 anthropic 協議即走它的 Claude 相容端點。轉發必須填 OpenCode Go 的 API Key(訂閱制;獲取模型清單不需要 Key,但發請求上游會回 401「Missing API key」)", "响应为空": "響應為空", "商汤日日新的 OpenAI 兼容端点;余额查询走控制台账号密码(见下方「余额查询」一段)": "商湯日日新的 OpenAI 相容端點;餘額查詢走控制台帳號密碼(見下方「餘額查詢」一段)", "国内版": "國內版", "国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。": "國內版與**國際版是兩套獨立的帳號與套餐**,憑證與領取的套餐都不通用。", "国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)": "國內版登入頁沒有 Google / GitHub 入口(它用微信 / 手機號 / 郵箱登入)", "国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。": "國內版的登入站點是 www.accio-ai.com,與國際版不是同一站。", "国内版(WorkBuddy)": "國內版(WorkBuddy)", "国内站为 https://api.siliconflow.cn/v1": "國內站為 https://api.siliconflow.cn/v1", "国内站(minimaxi.com);OpenAI 兼容地址为 https://api.minimaxi.com/v1": "國內站(minimaxi.com);OpenAI 相容地址為 https://api.minimaxi.com/v1", "国际版": "國際版", "国际版 z.ai 的 Coding 套餐;OpenAI 兼容地址为 https://api.z.ai/api/coding/paas/v4": "國際版 z.ai 的 Coding 套餐;OpenAI 相容地址為 https://api.z.ai/api/coding/paas/v4", "国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。": "國際版與國內版是**兩套獨立的帳號**(同一帳號體系的兩個站點),憑證不通用。", "国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。": "國際版與國內版帳號體系獨立,請填國際版的憑證。未填 refreshToken 無法自動續期。", "国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口": "國際版登入頁預設只顯示郵箱登入,勾選後恢復 Google / GitHub / X 入口", "国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。": "國際版的推理站點是 api.z.ai,與國內版不是同一站;套餐也各自獨立。", "国际版(WorkBuddy AI)": "國際版(WorkBuddy AI)", "国际站 Coding 套餐;OpenAI 兼容地址为 https://api.minimax.io/v1": "國際站 Coding 套餐;OpenAI 相容地址為 https://api.minimax.io/v1", "在 cc-switch 里找到": "在 cc-switch 裡找到", "在内嵌窗口里完成官方登录,成功后自动加入账号列表。": "在內嵌視窗裡完成官方登入,成功後自動加入帳號列表。", "在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。": "在{label}的 Qoder 帳號設定 → Integrations 生成 PAT(別填 Google / GitHub 的權杖)。兩個地區的帳號與憑證不通用。", "在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。": "在開啟的官方授權頁裡用微信掃碼登入(頁面會直接顯示二維碼)。掃碼成功後自動加入帳號列表。", "在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。": "在開啟的窗口裡用百度帳號登入 KukuAI 主站(手機驗證碼 / 掃碼均可),登入成功後自動加入帳號列表。閘道器會向百度換髮 KukuAI 業務會話權杖(依賴本機已安裝庫庫AI 客戶端)。", "在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。": "在開啟的窗口裡登入 Google 帳號(Antigravity 的授權頁),授權完成後自動加入帳號列表。", "在浏览器中打开登录页": "在瀏覽器中開啟登入頁", "地区": "地區", "填写凭证": "填寫憑證", "填写凭证添加": "填寫憑證新增", "备注名": "備註名", "套餐": "套餐", "如:智谱 GLM": "如:智譜 GLM", "完成登录后自动加入账号列表,昵称取自上游。": "完成登入後自動加入帳號列表,暱稱取自上游。", "官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth": "官方客戶端憑證目錄:Windows 是 C:\\Users\\<你的使用者名稱>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth", "官方已确认到账": "官方已確認到賬", "导入": "匯入", "导入中…": "匯入中…", "导入凭证文件": "匯入憑證檔案", "导入失败": "匯入失敗", "导入失败:{reason}": "匯入失敗:{reason}", "导入所选": "匯入所選", "导入所选({n})": "匯入所選({n})", "导入桌面端登录态": "匯入桌面版登入態", "将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下": "將開啟內嵌視窗;授權完成後自動加入帳號列表。關掉視窗即取消等待。授權頁最後可能提示無法開啟 zcode:// 連結,這是正常的 —— 結果已由服務端記下", "将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)": "將開啟內嵌視窗;授權完成後自動加入帳號列表。遠端面板可貼上回撥地址。關掉視窗即取消等待。連結 5 分鐘內有效,超時或未點就會作廢(可重新發起)", "将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待": "將開啟內嵌視窗;登入完成後自動加入帳號列表。關掉視窗即取消等待", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。": "將用系統預設瀏覽器開啟授權頁(會複用瀏覽器裡已登入的 Trae 帳號);同機完成後自動加入,Docker / 遠端面板按提示貼上位址列回撥地址。", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象": "將用系統預設瀏覽器開啟授權頁(會複用瀏覽器裡已登入的 ZCode 帳號);授權完成後自動加入帳號列表。頁面最後可能提示無法開啟 zcode:// 連結,屬正常現象", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表": "將用系統預設瀏覽器開啟授權頁(會複用瀏覽器裡已登入的華為雲帳號);授權碼由閘道器輪詢雲端取回,與瀏覽器跑在哪臺機器無關,完成後自動加入帳號列表", "将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板": "將用系統預設瀏覽器開啟授權頁(會複用瀏覽器裡已登入的華為雲帳號);瀏覽器與閘道器不在同一臺機器時,按上方說明把最終回撥地址貼上回面板", "将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待": "將用系統預設瀏覽器開啟登入頁(會複用瀏覽器裡已登入的 Accio 帳號);完成登入後自動加入帳號列表,關掉彈窗即取消等待", "小米 MiMo Token Plan 套餐(新加坡站)": "小米 MiMo Token Plan 套餐(新加坡站)", "已到账": "已到賬", "已取消登录等待": "已取消登入等待", "已取消领取": "已取消領取", "已取消验证码": "已取消驗證碼", "已填写手机号,正在发送验证码…": "已填寫手機號,正在傳送驗證碼…", "已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头": "已宣告無需鑑權:帳號會被正常選路,出網時不帶任何鑑權頭", "已导入 {ok} 个,失败 {fail} 个(失败项已标注在列表里)": "已匯入 {ok} 個,失敗 {fail} 個(失敗項已標註在列表裡)", "已建过 · {n} 个账号,点击继续添加": "已建過 · {n} 個帳號,點擊繼續新增", "已建过,点击继续添加账号": "已建過,點擊繼續新增帳號", "已打开官方登录页,请在窗口中完成登录…": "已開啟官方登入頁,請在視窗中完成登入…", "已点发送,等待短信…": "已點發送,等待簡訊…", "已用系统默认浏览器打开登录页,请在浏览器中完成登录…": "已用系統預設瀏覽器開啟登入頁,請在瀏覽器中完成登入…", "已领取,等官方确认": "已領取,等官方確認", "当前壳版本不支持 AutoClaw 网页登录,请更新应用": "當前殼版本不支援 AutoClaw 網頁登入,請更新應用", "当前没有可领取的套餐(活动尚未开始)": "當前沒有可領取的套餐(活動尚未開始)", "当前环境不支持领取(桥接方法缺失)": "當前環境不支援領取(橋接方法缺失)", "必填,CatPaw 账号标识": "必填,CatPaw 帳號標識", "恢复 Google / GitHub 入口": "恢復 Google / GitHub 入口", "手机号": "手機號", "手机验证码登录": "手機驗證碼登入", "打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。": "開啟 Trae SOLO 的官方授權頁(trae.cn)並用你的 Trae 帳號登入:授權完成後官方頁面會跳回本機的一個臨時連接埠;同機部署自動接收,Docker / 遠端面板請按提示覆制位址列回撥地址。", "打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。": "開啟 Accio {label}的官方登入頁({site})並用你的 Accio 帳號登入:登入成功後官方頁面會跳回本機;同機自動完成,Docker / 遠端面板按提示貼上回撥地址即可(授權碼只在本機傳給閘道器,介面不顯示明文 token)。", "打开 Accio {label}登录页": "開啟 Accio {label}登入頁", "打开 Antigravity 网页登录": "開啟 Antigravity 網頁登入", "打开 CatPaw 网页登录": "開啟 CatPaw 網頁登入", "打开 Cline 授权页": "開啟 Cline 授權頁", "打开 CodeArts 授权页": "開啟 CodeArts 授權頁", "打开 Qoder 网页登录": "開啟 Qoder 網頁登入", "打开 Trae 授权页": "開啟 Trae 授權頁", "打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。": "開啟 ZCode {label}的官方授權頁並用你的帳號登入。授權結果由 ZCode 服務端記錄,閘道器在後臺自動取回憑證並加入帳號列表。", "打开 ZCode {label}授权页": "開啟 ZCode {label}授權頁", "打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。": "開啟華為雲 CodeArts 的官方授權頁登入:登入完成後官方頁面會把瀏覽器帶回閘道器自己的 /oauth/callback,閘道器用一次性授權碼換取臨時憑據並加入帳號列表。
    閘道器跑在另一臺機器上時,網頁端會提示把位址列中的最終回撥地址直接貼上回面板。", "打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。": "開啟華為雲授權頁登入:登入完成後閘道器會自動輪詢雲端取回授權碼並加入帳號列表(不需要裝 OfficeAce 桌面版,也無需手工回填回撥地址)。", "打开官方授权页完成设备码授权,登录的是{label}({site})的账号。": "開啟官方授權頁完成裝置碼授權,登入的是{label}({site})的帳號。", "打开授权页": "開啟授權頁", "打开授权页完成确认,账号自动加入 {label}{note}": "開啟授權頁完成確認,帳號自動加入 {label}{note}", "打开方式": "開啟方式", "打开网页登录": "開啟網頁登入", "探测失败:{message}": "探測失敗:{message}", "接入一个兼容上游": "接入一個相容上游", "提交中…": "提交中…", "搜索提供商": "搜尋提供商", "搜索提供商…": "搜尋提供商…", "整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {\"codearts_provider_credential\":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。": "整份貼上官方外掛 / CLIProxyAPI 落盤的憑據 JSON(形如 {\"codearts_provider_credential\":{…}},鋪平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自動續期,必須連 refresh_token 與 oauth_context 一起粘 —— 臨時憑據約一小時到期,缺這半塊就續不回來,只能重新登入。", "文件是{edition}凭证,已按该版本导入": "檔案是{edition}憑證,已按該版本匯入", "新建自定义提供商": "新建自定義提供商", "方案:{label}": "方案:{label}", "明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)": "明文 JWT 或 auth.json 裡的 enc: 加密值(自動解密)", "明文 JWT(国际版账号的 access token)": "明文 JWT(國際版帳號的 access token)", "智谱 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys": "智譜 bigmodel.cn 的 Coding 套餐,Key 在 open.bigmodel.cn/usercenter/apikeys", "未知错误": "未知錯誤", "未能获取授权地址,请重试": "未能獲取授權地址,請重試", "未能读取 cc-switch 数据": "未能讀取 cc-switch 資料", "未领取成功": "未領取成功", "本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用": "本地 Ollama、OpenCode Zen 免費檔這類上游要勾上,否則帳號不可用", "本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)": "本家有兩個**互不替代**的憑證,按你要用的功能填,至少填一個:編碼套餐 API Key 用於轉發推理(打 {site})與查詢視窗限額(每 N 小時 / 每週的剩餘比例);jwt 用於領取套餐與查詢餘額(打 zcode.z.ai 的 billing 閘道器,官方叫 Coding Plan JWT,是一串三段點分的字串)。餘額兩把都能查、但讀到的東西不同:jwt 讀到餘額桶與套餐到期,API Key 讀到視窗限額;而領取只認 jwt、轉發只認 API Key。請填寫 {label}帳號的憑證 —— {plan}(最容易拿到的辦法:直接用上方的「網頁登入」—— 它會替你把這個 API Key 換好,兩個憑證一起拿到。)", "本机 Ollama 的 OpenAI 兼容端点,无需 API Key(默认已勾上「该上游无需鉴权」,鉴权头一个都不发)": "本機 Ollama 的 OpenAI 相容端點,無需 API Key(預設已勾上「該上游無需鑑權」,鑑權頭一個都不發)", "本次未确认到账": "本次未確認到賬", "条可导入": "條可匯入", "条配置,其中": "條配置,其中", "桌面运行时不可用(Tauri 未初始化)": "桌面執行時不可用(Tauri 未初始化)", "模型网关基址": "模型閘道器基址", "正在打开百度登录页…": "正在開啟百度登入頁…", "正在扫描本机 cc-switch…": "正在掃描本機 cc-switch…", "正在换发访客凭证…": "正在換髮訪客憑證…", "正在添加…": "正在新增…", "正在等待{name}登录完成;完成或取消后才能发起新的登录": "正在等待{name}登入完成;完成或取消後才能發起新的登入", "每周": "每週", "每日": "每日", "每月": "每月", "没有则无法自动续期": "沒有則無法自動續期", "没有匹配「{keyword}」的提供商": "沒有匹配「{keyword}」的提供商", "添加 {name} 账号": "新增 {name} 帳號", "添加中…": "新增中…", "添加到 ": "新增到 ", "添加失败:{reason}": "新增失敗:{reason}", "添加小浣熊账号": "新增小浣熊帳號", "添加方式": "新增方式", "添加访客账号": "新增訪客帳號", "添加账号": "新增帳號", "火山引擎 Coding 套餐;通用推理接入点为 https://ark.cn-beijing.volces.com/api/v3": "火山引擎 Coding 套餐;通用推理接入點為 https://ark.cn-beijing.volces.com/api/v3", "点击添加账号": "點擊新增帳號", "点开即预填,填 Key 接入": "點開即預填,填 Key 接入", "点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。": "點按鈕後先過一次滑塊驗證(官方風控),隨後開啟登入頁,登入完成即自動新增帳號。
    這是國際版官方唯一的登入方式;已在客戶端登入過的,用「匯入桌面版登入態」更快。", "用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。": "用 AutoClaw 帳號繫結的手機號登入:點擊「獲取驗證碼」,收到簡訊後填入下方並登入。驗證碼由本機直接提交給官方介面,介面不顯示 token。", "用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。": "用 CatPaw 帳號完成登入(美團 passport),成功後自動加入帳號列表。", "用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。": "用 Loomy 帳號繫結的手機號登入:點「獲取驗證碼」後填入即可。這是本家最省事的入口。", "用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)": "用於轉發;形如 apiKey.secret 兩段點分(不填則這個帳號不能轉發)", "用于领取套餐与查询余额;不填则这个账号不能领取与查余额": "用於領取套餐與查詢餘額;不填則這個帳號不能領取與查餘額", "用户 ID": "使用者 ID", "用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。": "用繫結的手機號登入:點「獲取驗證碼」後填入即可。這是國內版官方唯一的登入方式。", "留空则用提供商名称": "留空則用提供商名稱", "登录 / 添加 {name} 账号": "登入 / 新增 {name} 帳號", "登录 session(一长串)": "登入 session(一長串)", "登录中…": "登入中…", "登录失败:{message}": "登入失敗:{message}", "登录已结束": "登入已結束", "登录并添加": "登入並新增", "登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)": "登入態檔案路徑:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的使用者名稱>\\.box-agent\\config\\auth.json)", "确定删除自定义提供商「{name}」?将同时删除该提供商下 {count} 个账号,删除后无法恢复。": "確定刪除自定義提供商「{name}」?將同時刪除該提供商下 {count} 個帳號,刪除後無法恢復。", "等待 Accio {label}登录完成…": "等待 Accio {label}登入完成…", "等待 CatPaw 登录完成…": "等待 CatPaw 登入完成…", "等待 Cline 授权确认…": "等待 Cline 授權確認…", "等待 CodeArts 登录完成…": "等待 CodeArts 登入完成…", "等待 Google 授权完成…": "等待 Google 授權完成…", "等待 KukuAI 登录完成…": "等待 KukuAI 登入完成…", "等待 OfficeAce 登录完成…": "等待 OfficeAce 登入完成…", "等待 OrcaTerm 登录完成…": "等待 OrcaTerm 登入完成…", "等待 Qoder 授权完成…": "等待 Qoder 授權完成…", "等待 Trae 授权完成…": "等待 Trae 授權完成…", "等待 ZCode {label}授权完成…": "等待 ZCode {label}授權完成…", "等待小浣熊登录完成…": "等待小浣熊登入完成…", "等待登录完成…": "等待登入完成…", "等待网页登录…": "等待網頁登入…", "粘贴 API Key": "貼上 API Key", "粘贴 API 令牌": "貼上 API 權杖", "粘贴 Accio 的 accessToken": "貼上 Accio 的 accessToken", "粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。": "貼上 Antigravity 的 Google refresh token(以 1// 開頭;直接貼上含 refresh_token= 的整行也行)。
    這是網頁登入之外的手工入口(例如從已登入的官方 IDE 裡匯出)。refresh token 不會過期,access token 到期由閘道器自動續期;權杖丟了只能重新走 Google 授權,請妥善儲存。", "粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。": "貼上 Command Code 的 API Key(user_ 開頭;從官方 CLI 的 ~/.commandcode/auth.json 或網頁 studio 獲取)。整行 / 帶引號 / 帶 Bearer 字首地粘都行,閘道器會自己剝成裸 key。key 不過期、也沒有續期介面,失效後重新獲取即可;新增時閘道器會做一次輕量探活,失敗不影響新增。", "粘贴 Cookie": "貼上 Cookie", "粘贴 Google refresh token": "貼上 Google refresh token", "粘贴 ModelScope 的 API 令牌(ms- 开头,在 {site} 的「访问令牌」页获取)。
    {siteNote}
    这枚令牌两用:网关既用它调推理,也用它读账号身份、魔粒余额与每日签到。令牌长期有效、没有续期接口,失效后重新获取再粘一次即可。": "貼上 ModelScope 的 API 權杖(ms- 開頭,在 {site} 的「存取權杖」頁獲取)。
    {siteNote}
    這枚權杖兩用:閘道器既用它調推理,也用它讀帳號身份、魔粒餘額與每日簽到。權杖長期有效、沒有續期介面,失效後重新獲取再粘一次即可。", "粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。": "貼上 OrcaTerm 的 OAuth accessToken(JWT,三段點分;從桌面客戶端 data.bin 或 Web 版 Cookie ot_session 獲取)。直接貼上含 Bearer / ot_session= 的整行也行,閘道器會自己剝成裸 token。新增後由閘道器自動續期(上游有續期介面),無需跟隨 2 小時時效手動更換。", "粘贴 Qoder 个人访问令牌(pt-…)": "貼上 Qoder 個人存取權杖(pt-…)", "粘贴 accessToken": "貼上 accessToken", "粘贴 access_token(一长串 JWT)": "貼上 access_token(一長串 JWT)", "粘贴 session cookie": "貼上 session cookie", "粘贴 token / refreshToken": "貼上 token / refreshToken", "粘贴 workos:… 开头的令牌(不带前缀也会自动补上)": "貼上 workos:… 開頭的權杖(不帶字首也會自動補上)", "粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。": "貼上智譜清言的存取權杖(JWT,三段點分)。獲取方式:瀏覽器開啟 chatglm.cn 並登入後,在開發者工具的 Application → Cookies 裡複製 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘貼後會先向上游校驗一次,校驗通過才落帳號;登入帳號的積分、簽到能力都能用,之後由閘道器自動續期(上游有續期介面)。", "粘贴登录凭据": "貼上登入憑據", "粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。": "貼上的是登入 session(同時是模型閘道器的 token)。Loomy 沒有續期介面,session 有效期約 14 天,過期後重新登入即可。", "粘贴网关凭据": "貼上閘道器憑據", "粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。": "貼上網頁登入態 cookie monkeycode_ai_session 的值(在瀏覽器裡複製整段 Cookie 直接貼上也行,閘道器會自己剝出值)。
    {siteNote}
    MonkeyCode 沒有續期介面:session 有效期約 30 天(硬限制),過期後重新登入網頁、再貼上一次即可。", "粘贴访问令牌": "貼上存取權杖", "系统浏览器": "系統瀏覽器", "系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。": "系統瀏覽器可複用已有登入態(國際版推薦);內嵌視窗更乾淨。", "系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入的 Cline 帳號);完成後自動加入列表", "系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入的 Google 帳號);完成後自動加入列表", "系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入的 Zai / Google 帳號);完成後自動加入列表", "系统浏览器打开(复用已登录的美团账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入的美團帳號);完成後自動加入列表", "系统浏览器打开(复用已登录账号);完成后自动加入列表": "系統瀏覽器開啟(複用已登入帳號);完成後自動加入列表", "系统默认浏览器": "系統預設瀏覽器", "编码套餐 API Key": "編碼套餐 API Key", "网关 Secret": "閘道器 Secret", "网页登录": "網頁登入", "网页登录的打开方式": "網頁登入的開啟方式", "网页登录(Zai / Google)": "網頁登入(Zai / Google)", "自定义": "自定義", "自建聚合面板:填你自己的站点地址。余额查询用该账号的 API Key 打 {base}/v1/usage,不需要额外配置": "自建聚合面板:填你自己的站點地址。餘額查詢用該帳號的 API Key 打 {base}/v1/usage,不需要額外配置", "自建聚合面板:填你自己的站点地址;余额查询要另填 NewAPI 的个人访问令牌(见下方「余额查询」一段)": "自建聚合面板:填你自己的站點地址;餘額查詢要另填 NewAPI 的個人存取權杖(見下方「餘額查詢」一段)", "获取风控配置失败,将直接尝试领取:{message}": "獲取風控配置失敗,將直接嘗試領取:{message}", "获取验证码": "獲取驗證碼", "访客模式": "訪客模式", "访客模式(免登录)": "訪客模式(免登入)", "该上游无需鉴权(不发送鉴权头)": "該上游無需鑑權(不傳送鑑權頭)", "该提供商": "該提供商", "该提供商账号添加功能即将上线": "該提供商帳號新增功能即將上線", "该自定义提供商已不存在(可能已被删除),请刷新后重试": "該自定義提供商已不存在(可能已被刪除),請重新整理後重試", "请先选择一个自定义提供商": "請先選擇一個自定義提供商", "请在弹出的滑块中完成验证(官方要求的风控步骤)": "請在彈出的滑塊中完成驗證(官方要求的風控步驟)", "请填写 11 位大陆手机号": "請填寫 11 位大陸手機號", "请填写 6 位数字验证码": "請填寫 6 位數字驗證碼", "请填写 Base URL": "請填寫 Base URL", "请填写 {label}": "請填寫 {label}", "请填写名称": "請填寫名稱", "请完成验证…": "請完成驗證…", "读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows": "讀取 %APPDATA%/AutoClaw/auth.json 並解密,僅 Windows", "读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录": "讀取 ~/.cline/data/settings/providers.json,需已在 Cline 客戶端登入", "读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录": "讀取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客戶端登入", "读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录": "讀取本機 KukuAI 客戶端登入態(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客戶端登入", "读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录": "讀取本機 OrcaTerm 客戶端登入態(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客戶端登入", "读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录": "讀取本機智譜清言客戶端登入態(%APPDATA%\\chatglm\\Network\\Cookies),需已在客戶端登入", "读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。": "讀本機官方客戶端(Tencent WorkBuddy / WorkBuddy AI)當前登入的帳號:自動定位其憑證目錄裡最新的登入態檔案(需已在本機官方客戶端登入)。匯入後由閘道器自動續期,無需跟隨 2 小時時效手動換權杖。", "读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。": "讀本機客戶端當前登入態(明文 Cookie,無需解密)。客戶端執行時 Cookies 檔案被獨佔佔用,匯入前請先關閉 KukuAI 客戶端。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。客戶端重新登入後點「重新整理 Token」同步。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。客戶端重新登入後重新匯入即可。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。用 Zai / Google 登入客戶端的使用者走這一條。", "读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。": "讀本機客戶端當前登入態,每次即時讀取(刪掉這條記錄不影響客戶端登入態)。這一條歸入 {label}。", "读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。": "讀本機客戶端當前登入的 OAuth 權杖(明文 JSON,無需解密)。匯入後由閘道器自動續期,無需跟隨客戶端的 2 小時時效手動換權杖。", "读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。": "讀本機客戶端當前的登入態。客戶端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此僅 Windows 可用;客戶端正在執行時可能讀不到該檔案,先退出客戶端再試即可(也可改用「填寫憑證」貼上權杖)。", "账号信息": "帳號資訊", "账号信息不完整,请刷新后重试": "帳號資訊不完整,請重新整理後重試", "账号已添加,但请留意:{warning}": "帳號已新增,但請留意:{warning}", "账号版本": "帳號版本", "账号类型": "帳號型別", "账号:{name}
    ": "帳號:{name}
    ", "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 创建": "走 Inference Providers 路由,Key 在 hf.co/settings/tokens 建立", "还没有账号": "還沒有帳號", "这一家当前不支持网页登录,请改用填写凭证": "這一家當前不支援網頁登入,請改用填寫憑證", "这个账号当前没有可自动领的活动(只自动领每日登录赠送积分)": "這個帳號當前沒有可自動領的活動(只自動領每日登入贈送積分)", "这份额度走「活动套餐」通道:若转发时提示编码套餐已到期,": "這份額度走「活動套餐」通道:若轉發時提示編碼套餐已到期,", "这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。": "這裡填國內站(modelscope.cn)的帳號:請貼上國內站的權杖。國際站(modelscope.ai)是另一家 provider、另一套帳號,兩邊的權杖不通用。", "这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。": "這裡填國內站(monkeycode-ai.com)的帳號:請貼上國內站的 session。國際站(monkeycode-ai.net)是另一家 provider、另一套帳號,兩邊的憑證不通用。", "这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。": "這裡填國際站(modelscope.ai)的帳號:請貼上國際站的權杖。國內站(modelscope.cn)是另一家 provider、另一套帳號,兩邊的權杖不通用。", "这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。": "這裡填國際站(monkeycode-ai.net)的帳號:請貼上國際站的 session。國內站(monkeycode-ai.com)是另一家 provider、另一套帳號,兩邊的憑證不通用。", "选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "選擇 CatPaw 客戶端的登入態檔案 auth.json(Windows:C:\\Users\\<你的使用者名稱>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。匯入後憑證直接落在閘道器、可獨立轉發,不再依賴本機客戶端。", "选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。": "選擇 Cline 客戶端的登入態檔案 providers.json(Windows:C:\\Users\\<你的使用者名稱>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。匯入後憑證直接落在閘道器、可獨立轉發,不再依賴本機客戶端;這一條歸入 {label}。", "选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。": "選擇 KukuAI 客戶端的 Cookies 檔案(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二進位制** SQLite 資料庫(無副檔名,不是 JSON)。匯入時讀的是你選中檔案的副本、不和執行中的客戶端搶佔用,因此**無需先關閉客戶端**。匯入後憑證直接落在閘道器、可獨立轉發。", "选择凭证文件导入": "選擇憑證檔案匯入", "选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。": "選擇官方客戶端的登入態憑證檔案(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 匯出的帳號 JSON(巢狀 / 扁平形均可)。", "选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。": "選擇小浣熊客戶端的登入態檔案 auth.json(Windows:C:\\Users\\<你的使用者名稱>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。匯入後憑證直接落在閘道器、可獨立轉發,不再依賴本機客戶端。", "选择提供商": "選擇提供商", "选择的文件不是合法 JSON": "選擇的檔案不是合法 JSON", "选择要添加账号的提供商": "選擇要新增帳號的提供商", "重新扫描": "重新掃描", "鉴权": "鑑權", "阿里云 Token Plan 套餐(国际站)": "阿里雲 Token Plan 套餐(國際站)", "阿里云百炼 Coding 套餐(国内站)": "阿里雲百鍊 Coding 套餐(國內站)", "阿里云百炼 Coding 套餐(国际站)": "阿里雲百鍊 Coding 套餐(國際站)", "阿里云百炼模型服务(国际站,OpenAI 兼容模式)": "阿里雲百鍊模型服務(國際站,OpenAI 相容模式)", "需要图形验证码:登录窗口已弹出,请填写后继续": "需要圖形驗證碼:登入視窗已彈出,請填寫後繼續", "预置 API": "預置 API", "领取 CodeArts 每日福利": "領取 CodeArts 每日福利", "领取失败:{message}": "領取失敗:{message}", "领取并让官方确认": "領取並讓官方確認", "风控验证配置不完整,请稍后重试": "風控驗證配置不完整,請稍後重試", "验证码": "驗證碼", "验证码已发送。收到后填入下方并点「登录并添加」": "驗證碼已傳送。收到後填入下方並點「登入並新增」", "验证码已发送,请查看手机短信": "驗證碼已傳送,請檢視手機簡訊", "验证码已发送,请查看手机短信。填入下方并点「登录并添加」即完成登录": "驗證碼已傳送,請檢視手機簡訊。填入下方並點「登入並新增」即完成登入", "验证码已发送,请查看短信": "驗證碼已傳送,請檢視簡訊", "验证码校验失败,请重试": "驗證碼校驗失敗,請重試", "验证码校验超时,请重试": "驗證碼校驗超時,請重試", "验证码组件不可用,请重试": "驗證碼元件不可用,請重試", "验证码组件初始化超时,请重试": "驗證碼元件初始化超時,請重試", "验证码组件加载失败,请检查网络后重试": "驗證碼元件載入失敗,請檢查網路後重試", "验证码组件加载异常,请重试": "驗證碼元件載入異常,請重試", "验证码组件加载超时,请检查网络后重试": "驗證碼元件載入超時,請檢查網路後重試", "验证码组件未加载,请重启应用后重试": "驗證碼元件未載入,請重啟應用後重試", "(免费额度池,模型名带 cline-free/ 前缀)。": "(免費額度池,模型名帶 cline-free/ 字首)。", "(其中 {n} 把恢复为不限制)": "(其中 {n} 把恢復為不限制)", "(必填)": "(必填)", "(有效期 {window})": "(有效期 {window})", "(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。": "(訂閱池,模型名帶 cline-pass/ 字首,需要帳號有對應訂閱)。", ",下一次最快 {minutes} 分钟后": ",下一次最快 {minutes} 分鐘後", ",并从 {n} 把 Key 的可用提供商里移除": ",並從 {n} 把 Key 的可用提供商裡移除" }); diff --git a/desktop-tauri/ui/i18n/zh-Hant/checkin.js b/desktop-tauri/ui/i18n/zh-Hant/checkin.js index da5289f0..7318c0ab 100644 --- a/desktop-tauri/ui/i18n/zh-Hant/checkin.js +++ b/desktop-tauri/ui/i18n/zh-Hant/checkin.js @@ -1,2 +1,2 @@ /* Agent2API 词典构建产物:zh-Hant/checkin —— 由 desktop-tauri/i18n/build.mjs 生成,请勿手改;源头是 i18n-src/*.json */ -window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "SOLO 的 checkin_credits 領取 · 按自然日 0 點重新整理", "UMID 组件安装失败:{error}": "UMID 元件安裝失敗:{error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy 國內版 · 查詢任務樹後一鍵點亮/領獎 · 含開學季與貓貓旅行 · 點擊行展開明細", "WorkBuddy 国际版保活模型,按顺序回退": "WorkBuddy 國際版保活模型,按順序回退", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "WorkBuddy 國際版日活任務的免費模型 · 全域一份,與條目無關", "{date}(每天 {time})": "{date}(每天 {time})", "{label} ×{count}({reason})": "{label} ×{count}({reason})", "{n} 项可完成": "{n} 項可完成", "{n} 项待领": "{n} 項待領", "{total} 账号 · {done} 已签": "{total} 帳號 · {done} 已籤", "{total} 项任务 · {pending} 项可完成": "{total} 項任務 · {pending} 項可完成", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ UMID 元件已安裝,下輪簽到即可領取國際版積分", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ 定時簽到已開啟", "✅ 开学季任务执行完成": "✅ 開學季任務執行完成", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ 成長任務執行完成:積分 +{credit} 能量 +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ 新手福利領取完成,累計 {n} 積分", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ 簽到完成:{succeeded}/{total} 個帳號成功領取{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "「保活模型鏈」是 WorkBuddy 國際版領日活時用來保活的免費模型,按順序逐個嘗試、 第一個成功即止;清空提交恢復預設({defaults})。 當天去重 + 冪等領取:重複執行只會拿到「已領取」,不會重複加分。", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "「保活模型鏈」是 WorkBuddy 國際版領日活時用來保活的免費模型,按順序逐個嘗試、 第一個成功即止;清空清單並儲存 = 恢復預設鏈(當前預設:{defaults})。 當天去重 + 冪等領取:重複執行只會拿到「已領取」,不會重複加分。", "「免费领积分」的每日任务 · 逐个领取": "「免費領積分」的每日任務 · 逐個領取", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "一次性福利 · 簽到後自動查詢並領取,領完記在本機不再查上游 · 點擊行展開任務清單", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "一次領當天全部獎勵(每日簽到 + 新人禮) · 冪等由上游保證", "一键安装组件": "一鍵安裝元件", "一键完成": "一鍵完成", "一键领取({n})": "一鍵領取({n})", "上次执行:{line}": "上次執行:{line}", "上次签到时间": "上次簽到時間", "上次领取 {time} · 领取需通过滑块验证码": "上次領取 {time} · 領取需通過滑塊驗證碼", "下次 {date}": "下次 {date}", "下次 {date} · 点此管理条目": "下次 {date} · 點此管理條目", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "不參與每日簽到:{list}。CodeArts 的一次性獎勵在下方「新手福利」,它與 ZCode 的每日/套餐福利領取見「活動福利」。", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "不參與每日簽到:{list}。CodeArts 的一次性獎勵在下方「新手福利」,它的每日福利就在上方「每日簽到」裡;ZCode 的套餐領取見「活動福利」。", "与国内版同一套任务接口 · 站点不同": "與國內版同一套任務介面 · 站點不同", "今天已领 {n} 份": "今天已領 {n} 份", "今天未领": "今天未領", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "今天(北京時間 {day})已領取 · 官方確認到賬 {n} 項 · 明天可再領", "今日已执行": "今日已執行", "今日已派出": "今日已派出", "今日已领取": "今日已領取", "今日签到": "今日簽到", "今日签到进度": "今日簽到進度", "从清单里移除": "從清單裡移除", "保活": "保活", "保活 {n}": "保活 {n}", "保活+领取": "保活+領取", "保活中…": "保活中…", "保活模型链": "保活模型鏈", "全选": "全選", "全部 {n} 家": "全部 {n} 家", "全部完成": "全部完成", "全部查询": "全部查詢", "全部结果": "全部結果", "全部账号均可签到": "全部帳號均可簽到", "全部领取": "全部領取", "关着:所有条目都不执行": "關著:所有條目都不執行", "删除失败:{error}": "刪除失敗:{error}", "删除定时条目": "刪除定時條目", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "到點後自動簽到勾選提供商的可用帳號(WorkBuddy 國內版走每日簽到介面,國際版走每日活躍任務:探測活動、領日活獎勵、再用免費模型保活並在網頁通道建會話點亮日活;小浣熊走桌面版每日積分鏈路;AutoClaw 走官方客戶端的每日簽到任務;Qoder 中國版走活動領取,沒被下發活動的帳號會得到中性提示;Qoder 國際版要先帶裝置風控身份(本機 Qoder 客戶端 / qodercli 的 UMID 元件生成)才能看到「每日 100 Credits」活動,缺元件時會得到明確的說明而不是報錯;Trae 領 SOLO 的每日簽到積分(按自然日 0 點重置),上游沒對該帳號開活動、或憑據裡沒有裝置號時得到的是「未領取 + 具體原因」而不是報錯;Loomy 每天替帳號打一次首次登入積分;KukuAI 領「免費領積分」的每日任務;CodeArts 領當日的運營福利(領取 → 確認 → 回讀核實,自動執行受每天 6 次 / 間隔 10 分鐘的寫請求限流);OfficeAce 果辦一次領當天全部獎勵(每日簽到 + 新人禮))。錯過時點開機後會自動補籤,不會因為當時沒開機而漏掉。各家簽到介面都是冪等的,重複執行不會重複領取。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "到點後自動簽到勾選提供商的可用帳號(WorkBuddy 國內版走每日簽到介面,國際版走每日活躍任務:探測活動、領日活獎勵、再用免費模型保活;小浣熊走桌面版每日積分鏈路;AutoClaw 走官方客戶端的每日簽到任務;Qoder 中國版走活動領取,沒被下發活動的帳號會得到中性提示;Qoder 國際版要先帶裝置風控身份(本機 Qoder 客戶端 / qodercli 的 UMID 元件生成)才能看到「每日 100 Credits」活動,缺元件時會得到明確的說明而不是報錯;Trae 領 SOLO 的每日簽到積分(按自然日 0 點重置),上游沒對該帳號開活動、或憑據裡沒有裝置號時得到的是「未領取 + 具體原因」而不是報錯;Loomy 每天替帳號打一次首次登入積分;KukuAI 領「免費領積分」的每日任務;CodeArts 領當日的運營福利(領取 → 確認 → 回讀核實,自動執行受每天 6 次 / 間隔 10 分鐘的寫請求限流);OfficeAce 果辦一次領當天全部獎勵(每日簽到 + 新人禮))。錯過時點開機後會自動補籤,不會因為當時沒開機而漏掉。各家簽到介面都是冪等的,重複執行不會重複領取。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "到點後自動簽到勾選提供商的可用帳號(WorkBuddy 國內版走每日簽到介面,國際版走每日活躍任務:探測活動、領日活獎勵、再用免費模型保活;小浣熊走桌面版每日積分鏈路;AutoClaw 走官方客戶端的每日簽到任務;Qoder 中國版走活動領取,沒被下發活動的帳號會得到中性提示;Qoder 國際版要先帶裝置風控身份(本機 Qoder 客戶端 / qodercli 的 UMID 元件生成)才能看到「每日 100 Credits」活動,缺元件時會得到明確的說明而不是報錯;Trae 領 SOLO 的每日簽到積分(按自然日 0 點重置),上游沒對該帳號開活動、或憑據裡沒有裝置號時得到的是「未領取 + 具體原因」而不是報錯;Loomy 每天替帳號打一次首次登入積分;KukuAI 領「免費領積分」的每日任務;OfficeAce 果辦一次領當天全部獎勵(每日簽到 + 新人禮))。錯過時點開機後會自動補籤,不會因為當時沒開機而漏掉。各家簽到介面都是冪等的,重複執行不會重複領取。", "到点时逐个签到,已勾 {n} / {total} 家": "到點時逐個簽到,已勾 {n} / {total} 家", "北京时间 · 错过时点开机后会自动补签": "北京時間 · 錯過時點開機後會自動補籤", "去领取": "去領取", "另有 {n} 个账号不参与每日签到": "另有 {n} 個帳號不參與每日簽到", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "只領取已完成任務的獎勵(冪等,重複點不會重複入帳)", "可完成": "可完成", "可派出": "可派出", "可选 · 缺省显示时刻": "可選 · 預設顯示時刻", "可领奖": "可領獎", "后端未返回定时签到数据": "後端未返回定時簽到資料", "后端未返回签到中心数据": "後端未返回簽到中心資料", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "國際版簽到需要 UMID 元件生成裝置風控身份(本機未檢測到)。", "在途": "在途", "填入缺省链": "填入預設鏈", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "填好時刻與簽到範圍後點「儲存」;名稱可以留空(介面顯示時刻)", "失败 {n}": "失敗 {n}", "套餐明细": "套餐明細", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "安裝 Qoder 客戶端或 qodercli 後即可(無需重啟閘道器)。", "安装中…": "安裝中…", "官方客户端的每日签到任务": "官方客戶端的每日簽到任務", "定时签到": "定時簽到", "定时签到已关闭": "定時簽到已關閉", "尚未查询": "尚未查詢", "尚未查询任务状态": "尚未查詢任務狀態", "巡检一次": "巡檢一次", "已保存:{label}": "已儲存:{label}", "已保存:保活模型链": "已儲存:保活模型鏈", "已保存:定时条目": "已儲存:定時條目", "已删除定时条目": "已刪除定時條目", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "已完成活躍上報(連登已點亮),但活動未開啟(本次沒有可領的獎勵)", "已抽 {n} 次": "已抽 {n} 次", "已有结果 {checked} / 共 {total} 个账号": "已有結果 {checked} / 共 {total} 個帳號", "已签": "已籤", "已领 {claimed}/{total} · 累计 {earned} 积分": "已領 {claimed}/{total} · 累計 {earned} 積分", "已领养": "已領養", "已领取": "已領取", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "帶裝置風控身份領取「每日 100 Credits」 · 需要 UMID 元件", "开学季执行失败:{error}": "開學季執行失敗:{error}", "开学季执行完成:{message}": "開學季執行完成:{message}", "开学季活动": "開學季活動", "开着:启用的条目按各自时刻执行": "開著:啟用的條目按各自時刻執行", "待签": "待籤", "待领新手福利": "待領新手福利", "总开关": "總開關", "总开关已关闭 · 在「定时签到」页打开": "總開關已關閉 · 在「定時簽到」頁開啟", "成功 {n}": "成功 {n}", "成长任务": "成長任務", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "成長任務完成({done} 項成功、{failed} 項失敗),積分 +{credit} 能量 +{energy}", "成长任务执行失败:{error}": "成長任務執行失敗:{error}", "执行失败:{error}": "執行失敗:{error}", "执行并抽奖": "執行並抽獎", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "執行開學季任務並抽空抽獎機會(分享/對話/專家事件)", "把缺省链填进清单,再点「保存」生效": "把預設鏈填進清單,再點「儲存」生效", "抽奖机会 {n} 次": "抽獎機會 {n} 次", "按住拖动调整顺序": "按住拖動調整順序", "按住拖动,调整这个模型在链里的顺序": "按住拖動,調整這個模型在鏈裡的順序", "按序逐个尝试,共 {n} 个": "按序逐個嘗試,共 {n} 個", "按结果筛选": "按結果篩選", "探测 + 领取 + 保活 · 与定时签到同一套组合": "探測 + 領取 + 保活 · 與定時簽到同一套組合", "探测活动并领取日活奖励 · 不做保活": "探測活動並領取日活獎勵 · 不做保活", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "接單+點亮+領獎(只處理已實測沉澱的任務)", "搜账号 / 收益 / 错误 / 触发原因": "搜帳號 / 收益 / 錯誤 / 觸發原因", "收起新建": "收起新建", "新建定时条目": "新建定時條目", "新手福利": "新手福利", "新手福利有 {n} 项领取失败,可重试": "新手福利有 {n} 項領取失敗,可重試", "无": "無", "无独立签到接口 · 每天替账号打一次首次登录积分": "無獨立簽到介面 · 每天替帳號打一次首次登入積分", "无账号": "無帳號", "暂不可领": "暫不可領", "暂不支持": "暫不支援", "暂无启用的条目 · 点此添加": "暫無啟用的條目 · 點此新增", "有未保存的改动": "有未儲存的改動", "未勾选提供商": "未勾選提供商", "未开启": "未開啟", "未解锁": "未解鎖", "未领养(领养需先完成当日对话量)": "未領養(領養需先完成當日對話量)", "未领取": "未領取", "本地台账里今天还没领过;活动期内每天发一份新套餐": "本地臺賬裡今天還沒領過;活動期內每天發一份新套餐", "本地台账里今天(北京时间)领过的套餐:{plans}": "本地臺賬裡今天(北京時間)領過的套餐:{plans}", "条启用": "條啟用", "查询于 {time}": "查詢於 {time}", "查询任务": "查詢任務", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "查詢任務樹並一鍵點亮/領獎(含開學季與貓貓旅行)", "查询失败:{error}": "查詢失敗:{error}", "桌面端每日积分链路": "桌面版每日積分鏈路", "正在读取定时签到数据…": "正在讀取定時簽到資料…", "正在读取签到数据…": "正在讀取簽到資料…", "每天 {time}": "每天 {time}", "每天 {time} · {scope}": "每天 {time} · {scope}", "每天时刻": "每天時刻", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "每執行一次簽到 · 每個帳號一條明細 · 結果與收益以後端落賬為準", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "每日活躍任務 · 網頁會話保活點亮日活,領取才加積分 · 兩者可分開執行", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "每日登入積分 · 順帶領取會員活動 · 訪客帳號無積分體系(跳過)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "每日福利 · 領取 → 確認 → 回讀核實 · 按北京時間自然日重置", "每日签到": "每日簽到", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "每條條目各有時刻與範圍 · 各自當天去重 · 錯過時點開機自動補籤", "每账号一条明细 · 点此查看「签到记录」": "每帳號一條明細 · 點此檢視「簽到記錄」", "没有可领套餐的账号(ZCode 未添加)。": "沒有可領套餐的帳號(ZCode 未新增)。", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "沒有可領福利的帳號(CodeArts / ZCode 未新增)。", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "沒有支援成長任務的帳號(需要 WorkBuddy 國內版)。", "没有支持新手福利的账号": "沒有支援新手福利的帳號", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "沒有支援新手福利的帳號 —— 目前有 Loomy、小浣熊、CodeArts 三家。", "没有符合筛选条件的签到记录": "沒有符合篩選條件的簽到記錄", "没有需要执行的任务": "沒有需要執行的任務", "活动福利": "活動福利", "活动(campaign)领取 · 每天 10:00 刷新": "活動(campaign)領取 · 每天 10:00 重新整理", "活跃上报与保活均未成功,且活动未开启": "活躍上報與保活均未成功,且活動未開啟", "活跃上报完成,但保活未成功且活动未开启": "活躍上報完成,但保活未成功且活動未開啟", "活跃上报完成,但活动未开启": "活躍上報完成,但活動未開啟", "活跃上报成功": "活躍上報成功", "活跃保活失败": "活躍保活失敗", "活跃保活完成": "活躍保活完成", "活跃保活完成,但活动未开启": "活躍保活完成,但活動未開啟", "活跃保活完成,但活跃上报失败且活动未开启": "活躍保活完成,但活躍上報失敗且活動未開啟", "添加条目": "新增條目", "添加模型": "新增模型", "清单为空 —— 保存后恢复缺省链": "清單為空 —— 儲存後恢復預設鏈", "清单里已经有「{name}」": "清單裡已經有「{name}」", "清空失败:{error}": "清空失敗:{error}", "清空签到记录": "清空簽到記錄", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "點「套餐明細」看領到了哪幾份、什麼時候生效;活動期內每天可再領", "点击行展开账号明细 · 单账号签到不受范围限制": "點擊行展開帳號明細 · 單帳號簽到不受範圍限制", "独立链路 · 只提供手动入口 · 不进自动签到": "獨立鏈路 · 只提供手動入口 · 不進自動簽到", "猫猫旅行": "貓貓旅行", "猫猫旅行失败:{error}": "貓貓旅行失敗:{error}", "猫猫旅行失败:{message}": "貓貓旅行失敗:{message}", "猫猫旅行:{message}": "貓貓旅行:{message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "用免費模型與網頁會話維持帳號活躍 · 不領取獎勵", "确定删除「{name}」?删除后到点不再执行。": "確定刪除「{name}」?刪除後到點不再執行。", "确定清空全部签到记录?清空后无法恢复。": "確定清空全部簽到記錄?清空後無法恢復。", "确定清空当前筛选出的签到记录?清空后无法恢复。": "確定清空當前篩選出的簽到記錄?清空後無法恢復。", "移除 {name}": "移除 {name}", "立即全部签到": "立即全部簽到", "签到": "簽到", "签到中…": "簽到中…", "签到中心分区": "簽到中心分割槽", "签到失败:{error}": "簽到失敗:{error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "簽到完成:{succeeded}/{total} 成功{active},{failed} 個失敗", "签到成功": "簽到成功", "签到提供商": "簽到提供商", "签到范围": "簽到範圍", "签到触发时刻": "簽到觸發時刻", "签到记录": "簽到記錄", "签到记录时间范围": "簽到記錄時間範圍", "签到记录表": "簽到記錄表", "累计签到记录": "累計簽到記錄", "结算于 {time}": "結算於 {time}", "能量 {n}": "能量 {n}", "腾讯每日签到接口 · 仅国内版": "騰訊每日簽到介面 · 僅國內版", "至少勾一家才能保存(不勾等于这条条目不签到)": "至少勾一家才能儲存(不勾等於這條條目不簽到)", "读取定时签到数据失败:{error}": "讀取定時簽到資料失敗:{error}", "读取签到数据失败:{error}": "讀取簽到資料失敗:{error}", "读取签到记录失败:{error}": "讀取簽到記錄失敗:{error}", "跳过 {n}": "跳過 {n}", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "運營活動交付(領取 → 確認 → 回讀核實)· 領的是套餐贈送積分", "还没执行过": "還沒執行過", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "還沒有定時條目 —— 點「新增條目」建一條,或到「簽到中心」手動簽到。", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "還沒有簽到記錄 —— 手動簽到或等定時條目執行後,明細會出現在這裡。", "连登 {n} 天": "連登 {n} 天", "部分": "部分", "重签": "重籤", "重试": "重試", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "限時體驗套餐 · 領取需滑塊驗證碼 · 逐份檢視與領取", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "限時體驗套餐(start-plan),活動期內每天一份 · 領取需滑塊驗證碼", "需真实操作": "需真實操作", "非活动期": "非活動期", "项": "項", "领取": "領取", "领取中": "領取中", "领取中…": "領取中…", "领取失败": "領取失敗", "领取失败:{error}": "領取失敗:{error}", "(共 {n} 个账号)": "(共 {n} 個帳號)", "(能量 / 连登读数本次未取到)": "(能量/連登讀數本次未取到)", ",日活保活 {n} 个": ",日活保活 {n} 個" }); +window.wbI18nDict = window.wbI18nDict || {}; Object.assign(window.wbI18nDict, { " · ": " · ", "SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新": "SOLO 的 checkin_credits 領取 · 按自然日 0 點重新整理", "UMID 组件安装失败:{error}": "UMID 元件安裝失敗:{error}", "WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细": "WorkBuddy 國內版 · 查詢任務樹後一鍵點亮/領獎 · 含開學季與貓貓旅行 · 點擊行展開明細", "WorkBuddy 国际版保活模型,按顺序回退": "WorkBuddy 國際版保活模型,按順序回退", "WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关": "WorkBuddy 國際版日活任務的免費模型 · 全域一份,與條目無關", "{date}(每天 {time})": "{date}(每天 {time})", "{label} ×{count}({reason})": "{label} ×{count}({reason})", "{n} 项可完成": "{n} 項可完成", "{n} 项待领": "{n} 項待領", "{total} 账号 · {done} 已签": "{total} 帳號 · {done} 已籤", "{total} 项任务 · {pending} 项可完成": "{total} 項任務 · {pending} 項可完成", "✅ UMID 组件已安装,下轮签到即可领取国际版积分": "✅ UMID 元件已安裝,下輪簽到即可領取國際版積分", "✅ {message}": "✅ {message}", "✅ 定时签到已开启": "✅ 定時簽到已開啟", "✅ 开学季任务执行完成": "✅ 開學季任務執行完成", "✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}": "✅ 成長任務執行完成:積分 +{credit} 能量 +{energy}", "✅ 新手福利领取完成,累计 {n} 积分": "✅ 新手福利領取完成,累計 {n} 積分", "✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}": "✅ 簽到完成:{succeeded}/{total} 個帳號成功領取{active}", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空提交恢复缺省({defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "「保活模型鏈」是 WorkBuddy 國際版領日活時用來保活的免費模型,按順序逐個嘗試、 第一個成功即止;清空提交恢復預設({defaults})。 當天去重 + 冪等領取:重複執行只會拿到「已領取」,不會重複加分。", "「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。": "「保活模型鏈」是 WorkBuddy 國際版領日活時用來保活的免費模型,按順序逐個嘗試、 第一個成功即止;清空清單並儲存 = 恢復預設鏈(當前預設:{defaults})。 當天去重 + 冪等領取:重複執行只會拿到「已領取」,不會重複加分。", "「免费领积分」的每日任务 · 逐个领取": "「免費領積分」的每日任務 · 逐個領取", "一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单": "一次性福利 · 簽到後自動查詢並領取,領完記在本機不再查上游 · 點擊行展開任務清單", "一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证": "一次領當天全部獎勵(每日簽到 + 新人禮) · 冪等由上游保證", "一键安装组件": "一鍵安裝元件", "一键完成": "一鍵完成", "一键领取({n})": "一鍵領取({n})", "上次执行:{line}": "上次執行:{line}", "上次签到时间": "上次簽到時間", "上次领取 {time} · 领取需通过滑块验证码": "上次領取 {time} · 領取需通過滑塊驗證碼", "下次 {date}": "下次 {date}", "下次 {date} · 点此管理条目": "下次 {date} · 點此管理條目", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它与 ZCode 的每日/套餐福利领取见「活动福利」。": "不參與每日簽到:{list}。CodeArts 的一次性獎勵在下方「新手福利」,它與 ZCode 的每日/套餐福利領取見「活動福利」。", "不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。": "不參與每日簽到:{list}。CodeArts 的一次性獎勵在下方「新手福利」,它的每日福利就在上方「每日簽到」裡;ZCode 的套餐領取見「活動福利」。", "与国内版同一套任务接口 · 站点不同": "與國內版同一套任務介面 · 站點不同", "与国内版同一套链路 · 站点不同、令牌不通用": "與國內版同一套鏈路 · 站點不同、權杖不通用", "今天已领 {n} 份": "今天已領 {n} 份", "今天未领": "今天未領", "今天(北京时间 {day})已领取 · 官方确认到账 {n} 项 · 明天可再领": "今天(北京時間 {day})已領取 · 官方確認到賬 {n} 項 · 明天可再領", "今日已执行": "今日已執行", "今日已派出": "今日已派出", "今日已领取": "今日已領取", "今日签到": "今日簽到", "今日签到进度": "今日簽到進度", "从清单里移除": "從清單裡移除", "保活": "保活", "保活 {n}": "保活 {n}", "保活+领取": "保活+領取", "保活中…": "保活中…", "保活模型链": "保活模型鏈", "全选": "全選", "全部 {n} 家": "全部 {n} 家", "全部完成": "全部完成", "全部查询": "全部查詢", "全部结果": "全部結果", "全部账号均可签到": "全部帳號均可簽到", "全部领取": "全部領取", "关着:开机后等到窗口起点再签,随机窗口当天生效": "關著:開機後等到視窗起點再籤,隨機視窗當天生效", "关着:所有条目都不执行": "關著:所有條目都不執行", "分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行": "分鐘 · 視窗內逐個帳號隨機執行,0 = 到點立即執行", "删除失败:{error}": "刪除失敗:{error}", "删除定时条目": "刪除定時條目", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。": "到點後自動簽到勾選提供商的可用帳號(WorkBuddy 國內版走每日簽到介面,國際版走每日活躍任務:探測活動、領日活獎勵、再用免費模型保活並在網頁通道建會話點亮日活;小浣熊走桌面版每日積分鏈路;AutoClaw 走官方客戶端的每日簽到任務;Qoder 中國版走活動領取,沒被下發活動的帳號會得到中性提示;Qoder 國際版要先帶裝置風控身份(本機 Qoder 客戶端 / qodercli 的 UMID 元件生成)才能看到「每日 100 Credits」活動,缺元件時會得到明確的說明而不是報錯;Trae 領 SOLO 的每日簽到積分(按自然日 0 點重置),上游沒對該帳號開活動、或憑據裡沒有裝置號時得到的是「未領取 + 具體原因」而不是報錯;Loomy 每天替帳號打一次首次登入積分;KukuAI 領「免費領積分」的每日任務;CodeArts 領當日的運營福利(領取 → 確認 → 回讀核實,自動執行受每天 6 次 / 間隔 10 分鐘的寫請求限流);OfficeAce 果辦一次領當天全部獎勵(每日簽到 + 新人禮))。設了「隨機前後 N 分鐘」時,本輪帳號在各自視窗內分散執行(視窗夾在當天 0 點到 23:59 之間),不再全部擠在同一分鐘;視窗已過則立即全部執行。錯過時點開機後會自動補籤,不會因為當時沒開機而漏掉(可在「啟動補籤」關掉,改為等到視窗起點)。各家簽到介面都是冪等的,重複執行不會重複領取。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "到點後自動簽到勾選提供商的可用帳號(WorkBuddy 國內版走每日簽到介面,國際版走每日活躍任務:探測活動、領日活獎勵、再用免費模型保活;小浣熊走桌面版每日積分鏈路;AutoClaw 走官方客戶端的每日簽到任務;Qoder 中國版走活動領取,沒被下發活動的帳號會得到中性提示;Qoder 國際版要先帶裝置風控身份(本機 Qoder 客戶端 / qodercli 的 UMID 元件生成)才能看到「每日 100 Credits」活動,缺元件時會得到明確的說明而不是報錯;Trae 領 SOLO 的每日簽到積分(按自然日 0 點重置),上游沒對該帳號開活動、或憑據裡沒有裝置號時得到的是「未領取 + 具體原因」而不是報錯;Loomy 每天替帳號打一次首次登入積分;KukuAI 領「免費領積分」的每日任務;CodeArts 領當日的運營福利(領取 → 確認 → 回讀核實,自動執行受每天 6 次 / 間隔 10 分鐘的寫請求限流);OfficeAce 果辦一次領當天全部獎勵(每日簽到 + 新人禮))。錯過時點開機後會自動補籤,不會因為當時沒開機而漏掉。各家簽到介面都是冪等的,重複執行不會重複領取。", "到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。": "到點後自動簽到勾選提供商的可用帳號(WorkBuddy 國內版走每日簽到介面,國際版走每日活躍任務:探測活動、領日活獎勵、再用免費模型保活;小浣熊走桌面版每日積分鏈路;AutoClaw 走官方客戶端的每日簽到任務;Qoder 中國版走活動領取,沒被下發活動的帳號會得到中性提示;Qoder 國際版要先帶裝置風控身份(本機 Qoder 客戶端 / qodercli 的 UMID 元件生成)才能看到「每日 100 Credits」活動,缺元件時會得到明確的說明而不是報錯;Trae 領 SOLO 的每日簽到積分(按自然日 0 點重置),上游沒對該帳號開活動、或憑據裡沒有裝置號時得到的是「未領取 + 具體原因」而不是報錯;Loomy 每天替帳號打一次首次登入積分;KukuAI 領「免費領積分」的每日任務;OfficeAce 果辦一次領當天全部獎勵(每日簽到 + 新人禮))。錯過時點開機後會自動補籤,不會因為當時沒開機而漏掉。各家簽到介面都是冪等的,重複執行不會重複領取。", "到点时逐个签到,已勾 {n} / {total} 家": "到點時逐個簽到,已勾 {n} / {total} 家", "北京时间 · 错过时点开机后会自动补签": "北京時間 · 錯過時點開機後會自動補籤", "去领取": "去領取", "另有 {n} 个账号不参与每日签到": "另有 {n} 個帳號不參與每日簽到", "只领取已完成任务的奖励(幂等,重复点不会重复入账)": "只領取已完成任務的獎勵(冪等,重複點不會重複入帳)", "可完成": "可完成", "可派出": "可派出", "可选 · 缺省显示时刻": "可選 · 預設顯示時刻", "可领奖": "可領獎", "后端未返回定时签到数据": "後端未返回定時簽到資料", "后端未返回签到中心数据": "後端未返回簽到中心資料", "启动补签": "啟動補籤", "启动补签已关闭": "啟動補籤已關閉", "启动补签已开启": "啟動補籤已開啟", "国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。": "國際版簽到需要 UMID 元件生成裝置風控身份(本機未檢測到)。", "在途": "在途", "填入缺省链": "填入預設鏈", "填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)": "填好時刻與簽到範圍後點「儲存」;名稱可以留空(介面顯示時刻)", "失败 {n}": "失敗 {n}", "套餐明细": "套餐明細", "安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。": "安裝 Qoder 客戶端或 qodercli 後即可(無需重啟閘道器)。", "安装中…": "安裝中…", "官方客户端的每日签到任务": "官方客戶端的每日簽到任務", "定时签到": "定時簽到", "定时签到已关闭": "定時簽到已關閉", "尚未查询": "尚未查詢", "尚未查询任务状态": "尚未查詢任務狀態", "巡检一次": "巡檢一次", "已保存:{label}": "已儲存:{label}", "已保存:保活模型链": "已儲存:保活模型鏈", "已保存:定时条目": "已儲存:定時條目", "已删除定时条目": "已刪除定時條目", "已完成活跃上报(连登已点亮),但活动未开启(本次没有可领的奖励)": "已完成活躍上報(連登已點亮),但活動未開啟(本次沒有可領的獎勵)", "已抽 {n} 次": "已抽 {n} 次", "已有结果 {checked} / 共 {total} 个账号": "已有結果 {checked} / 共 {total} 個帳號", "已签": "已籤", "已领 {claimed}/{total} · 累计 {earned} 积分": "已領 {claimed}/{total} · 累計 {earned} 積分", "已领养": "已領養", "已领取": "已領取", "带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件": "帶裝置風控身份領取「每日 100 Credits」 · 需要 UMID 元件", "开学季执行失败:{error}": "開學季執行失敗:{error}", "开学季执行完成:{message}": "開學季執行完成:{message}", "开学季活动": "開學季活動", "开着:启用的条目按各自时刻执行": "開著:啟用的條目按各自時刻執行", "开着:开机后今天没签过的条目立刻补签,不看随机窗口": "開著:開機後今天沒簽過的條目立刻補籤,不看隨機視窗", "待签": "待籤", "待领新手福利": "待領新手福利", "总开关": "總開關", "总开关已关闭 · 在「定时签到」页打开": "總開關已關閉 · 在「定時簽到」頁開啟", "成功 {n}": "成功 {n}", "成长任务": "成長任務", "成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}": "成長任務完成({done} 項成功、{failed} 項失敗),積分 +{credit} 能量 +{energy}", "成长任务执行失败:{error}": "成長任務執行失敗:{error}", "执行失败:{error}": "執行失敗:{error}", "执行并抽奖": "執行並抽獎", "执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)": "執行開學季任務並抽空抽獎機會(分享/對話/專家事件)", "把缺省链填进清单,再点「保存」生效": "把預設鏈填進清單,再點「儲存」生效", "抽奖机会 {n} 次": "抽獎機會 {n} 次", "按住拖动调整顺序": "按住拖動調整順序", "按住拖动,调整这个模型在链里的顺序": "按住拖動,調整這個模型在鏈裡的順序", "按序逐个尝试,共 {n} 个": "按序逐個嘗試,共 {n} 個", "按结果筛选": "按結果篩選", "探测 + 领取 + 保活 · 与定时签到同一套组合": "探測 + 領取 + 保活 · 與定時簽到同一套組合", "探测活动并领取日活奖励 · 不做保活": "探測活動並領取日活獎勵 · 不做保活", "接单 + 点亮 + 领奖(只处理已实测沉淀的任务)": "接單+點亮+領獎(只處理已實測沉澱的任務)", "搜账号 / 收益 / 错误 / 触发原因": "搜帳號 / 收益 / 錯誤 / 觸發原因", "收起新建": "收起新建", "新建定时条目": "新建定時條目", "新手福利": "新手福利", "新手福利有 {n} 项领取失败,可重试": "新手福利有 {n} 項領取失敗,可重試", "无": "無", "无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)": "無獨立簽到介面 · 每天替帳號打一次登入資訊(即當日魔粒)", "无独立签到接口 · 每天替账号打一次首次登录积分": "無獨立簽到介面 · 每天替帳號打一次首次登入積分", "无账号": "無帳號", "暂不可领": "暫不可領", "暂不支持": "暫不支援", "暂无启用的条目 · 点此添加": "暫無啟用的條目 · 點此新增", "有未保存的改动": "有未儲存的改動", "未勾选提供商": "未勾選提供商", "未开启": "未開啟", "未解锁": "未解鎖", "未领养(领养需先完成当日对话量)": "未領養(領養需先完成當日對話量)", "未领取": "未領取", "本地台账里今天还没领过;活动期内每天发一份新套餐": "本地臺賬裡今天還沒領過;活動期內每天發一份新套餐", "本地台账里今天(北京时间)领过的套餐:{plans}": "本地臺賬裡今天(北京時間)領過的套餐:{plans}", "条启用": "條啟用", "查询于 {time}": "查詢於 {time}", "查询任务": "查詢任務", "查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)": "查詢任務樹並一鍵點亮/領獎(含開學季與貓貓旅行)", "查询失败:{error}": "查詢失敗:{error}", "桌面端每日积分链路": "桌面版每日積分鏈路", "正在读取定时签到数据…": "正在讀取定時簽到資料…", "正在读取签到数据…": "正在讀取簽到資料…", "每天 {time}": "每天 {time}", "每天 {time} · {scope}": "每天 {time} · {scope}", "每天 {time} · 随机前后 {n} 分钟 · {scope}": "每天 {time} · 隨機前後 {n} 分鐘 · {scope}", "每天时刻": "每天時刻", "每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准": "每執行一次簽到 · 每個帳號一條明細 · 結果與收益以後端落賬為準", "每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行": "每日活躍任務 · 網頁會話保活點亮日活,領取才加積分 · 兩者可分開執行", "每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)": "每日登入積分 · 順帶領取會員活動 · 訪客帳號無積分體系(跳過)", "每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置": "每日福利 · 領取 → 確認 → 回讀核實 · 按北京時間自然日重置", "每日签到": "每日簽到", "每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签": "每條條目各有時刻與範圍 · 各自當天去重 · 錯過時點開機自動補籤", "每账号一条明细 · 点此查看「签到记录」": "每帳號一條明細 · 點此檢視「簽到記錄」", "没有可领套餐的账号(ZCode 未添加)。": "沒有可領套餐的帳號(ZCode 未新增)。", "没有可领福利的账号(CodeArts / ZCode 未添加)。": "沒有可領福利的帳號(CodeArts / ZCode 未新增)。", "没有支持成长任务的账号(需要 WorkBuddy 国内版)。": "沒有支援成長任務的帳號(需要 WorkBuddy 國內版)。", "没有支持新手福利的账号": "沒有支援新手福利的帳號", "没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。": "沒有支援新手福利的帳號 —— 目前有 Loomy、小浣熊、CodeArts 三家。", "没有符合筛选条件的签到记录": "沒有符合篩選條件的簽到記錄", "没有需要执行的任务": "沒有需要執行的任務", "活动福利": "活動福利", "活动(campaign)领取 · 每天 10:00 刷新": "活動(campaign)領取 · 每天 10:00 重新整理", "活跃上报与保活均未成功,且活动未开启": "活躍上報與保活均未成功,且活動未開啟", "活跃上报完成,但保活未成功且活动未开启": "活躍上報完成,但保活未成功且活動未開啟", "活跃上报完成,但活动未开启": "活躍上報完成,但活動未開啟", "活跃上报成功": "活躍上報成功", "活跃保活失败": "活躍保活失敗", "活跃保活完成": "活躍保活完成", "活跃保活完成,但活动未开启": "活躍保活完成,但活動未開啟", "活跃保活完成,但活跃上报失败且活动未开启": "活躍保活完成,但活躍上報失敗且活動未開啟", "添加条目": "新增條目", "添加模型": "新增模型", "清单为空 —— 保存后恢复缺省链": "清單為空 —— 儲存後恢復預設鏈", "清单里已经有「{name}」": "清單裡已經有「{name}」", "清空失败:{error}": "清空失敗:{error}", "清空签到记录": "清空簽到記錄", "点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领": "點「套餐明細」看領到了哪幾份、什麼時候生效;活動期內每天可再領", "点击行展开账号明细 · 单账号签到不受范围限制": "點擊行展開帳號明細 · 單帳號簽到不受範圍限制", "独立链路 · 只提供手动入口 · 不进自动签到": "獨立鏈路 · 只提供手動入口 · 不進自動簽到", "猫猫旅行": "貓貓旅行", "猫猫旅行失败:{error}": "貓貓旅行失敗:{error}", "猫猫旅行失败:{message}": "貓貓旅行失敗:{message}", "猫猫旅行:{message}": "貓貓旅行:{message}", "用免费模型与网页会话维持账号活跃 · 不领取奖励": "用免費模型與網頁會話維持帳號活躍 · 不領取獎勵", "确定删除「{name}」?删除后到点不再执行。": "確定刪除「{name}」?刪除後到點不再執行。", "确定清空全部签到记录?清空后无法恢复。": "確定清空全部簽到記錄?清空後無法恢復。", "确定清空当前筛选出的签到记录?清空后无法恢复。": "確定清空當前篩選出的簽到記錄?清空後無法恢復。", "移除 {name}": "移除 {name}", "立即全部签到": "立即全部簽到", "签到": "簽到", "签到中…": "簽到中…", "签到中心分区": "簽到中心分割槽", "签到失败:{error}": "簽到失敗:{error}", "签到完成:{succeeded}/{total} 成功{active},{failed} 个失败": "簽到完成:{succeeded}/{total} 成功{active},{failed} 個失敗", "签到成功": "簽到成功", "签到提供商": "簽到提供商", "签到范围": "簽到範圍", "签到触发时刻": "簽到觸發時刻", "签到记录": "簽到記錄", "签到记录时间范围": "簽到記錄時間範圍", "签到记录表": "簽到記錄表", "累计签到记录": "累計簽到記錄", "结算于 {time}": "結算於 {time}", "能量 {n}": "能量 {n}", "腾讯每日签到接口 · 仅国内版": "騰訊每日簽到介面 · 僅國內版", "至少勾一家才能保存(不勾等于这条条目不签到)": "至少勾一家才能儲存(不勾等於這條條目不簽到)", "读取定时签到数据失败:{error}": "讀取定時簽到資料失敗:{error}", "读取签到数据失败:{error}": "讀取簽到資料失敗:{error}", "读取签到记录失败:{error}": "讀取簽到記錄失敗:{error}", "跳过 {n}": "跳過 {n}", "运营活动交付(领取 → 确认 → 回读核实)· 领的是套餐赠送积分": "運營活動交付(領取 → 確認 → 回讀核實)· 領的是套餐贈送積分", "还没执行过": "還沒執行過", "还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。": "還沒有定時條目 —— 點「新增條目」建一條,或到「簽到中心」手動簽到。", "还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。": "還沒有簽到記錄 —— 手動簽到或等定時條目執行後,明細會出現在這裡。", "连登 {n} 天": "連登 {n} 天", "部分": "部分", "重签": "重籤", "重试": "重試", "限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取": "限時體驗套餐 · 領取需滑塊驗證碼 · 逐份檢視與領取", "限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码": "限時體驗套餐(start-plan),活動期內每天一份 · 領取需滑塊驗證碼", "随机前后": "隨機前後", "需真实操作": "需真實操作", "非活动期": "非活動期", "项": "項", "领取": "領取", "领取中": "領取中", "领取中…": "領取中…", "领取失败": "領取失敗", "领取失败:{error}": "領取失敗:{error}", "(共 {n} 个账号)": "(共 {n} 個帳號)", "(能量 / 连登读数本次未取到)": "(能量/連登讀數本次未取到)", ",日活保活 {n} 个": ",日活保活 {n} 個" }); diff --git a/desktop-tauri/ui/islands/ui.js b/desktop-tauri/ui/islands/ui.js index a19f297d..1eb026a3 100644 --- a/desktop-tauri/ui/islands/ui.js +++ b/desktop-tauri/ui/islands/ui.js @@ -1,29 +1,29 @@ -var lre=Object.defineProperty;var ore=(Si,xl,so)=>xl in Si?lre(Si,xl,{enumerable:!0,configurable:!0,writable:!0,value:so}):Si[xl]=so;var cn=(Si,xl,so)=>ore(Si,typeof xl!="symbol"?xl+"":xl,so);(function(){"use strict";function Si(e,t){for(var a=0;ao[c]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}function xl(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var so={exports:{}},Yd={};var gC;function Z5(){if(gC)return Yd;gC=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function a(o,c,d){var f=null;if(d!==void 0&&(f=""+d),c.key!==void 0&&(f=""+c.key),"key"in c){d={};for(var p in c)p!=="key"&&(d[p]=c[p])}else d=c;return c=d.ref,{$$typeof:e,type:o,key:f,ref:c!==void 0?c:null,props:d}}return Yd.Fragment=t,Yd.jsx=a,Yd.jsxs=a,Yd}var xC;function W5(){return xC||(xC=1,so.exports=Z5()),so.exports}var s=W5(),Cv={exports:{}},ct={};var bC;function J5(){if(bC)return ct;bC=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),c=Symbol.for("react.profiler"),d=Symbol.for("react.consumer"),f=Symbol.for("react.context"),p=Symbol.for("react.forward_ref"),h=Symbol.for("react.suspense"),b=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),v=Symbol.for("react.activity"),j=Symbol.for("react.view_transition"),w=Symbol.iterator;function S(M){return M===null||typeof M!="object"?null:(M=w&&M[w]||M["@@iterator"],typeof M=="function"?M:null)}var N={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},k=Object.assign,A={};function P(M,U,Z){this.props=M,this.context=U,this.refs=A,this.updater=Z||N}P.prototype.isReactComponent={},P.prototype.setState=function(M,U){if(typeof M!="object"&&typeof M!="function"&&M!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,M,U,"setState")},P.prototype.forceUpdate=function(M){this.updater.enqueueForceUpdate(this,M,"forceUpdate")};function R(){}R.prototype=P.prototype;function C(M,U,Z){this.props=M,this.context=U,this.refs=A,this.updater=Z||N}var E=C.prototype=new R;E.constructor=C,k(E,P.prototype),E.isPureReactComponent=!0;var D=Array.isArray;function I(){}var O={H:null,A:null,T:null,S:null},_=Object.prototype.hasOwnProperty;function z(M,U,Z){var ae=Z.ref;return{$$typeof:e,type:M,key:U,ref:ae!==void 0?ae:null,props:Z}}function H(M,U){return z(M.type,U,M.props)}function B(M){return typeof M=="object"&&M!==null&&M.$$typeof===e}function L(M){var U={"=":"=0",":":"=2"};return"$"+M.replace(/[=:]/g,function(Z){return U[Z]})}var F=/\/+/g;function $(M,U){return typeof M=="object"&&M!==null&&M.key!=null?L(""+M.key):U.toString(36)}function X(M){switch(M.status){case"fulfilled":return M.value;case"rejected":throw M.reason;default:switch(typeof M.status=="string"?M.then(I,I):(M.status="pending",M.then(function(U){M.status==="pending"&&(M.status="fulfilled",M.value=U)},function(U){M.status==="pending"&&(M.status="rejected",M.reason=U)})),M.status){case"fulfilled":return M.value;case"rejected":throw M.reason}}throw M}function K(M,U,Z,ae,ce){var W=typeof M;(W==="undefined"||W==="boolean")&&(M=null);var ue=!1;if(M===null)ue=!0;else switch(W){case"bigint":case"string":case"number":ue=!0;break;case"object":switch(M.$$typeof){case e:case t:ue=!0;break;case y:return ue=M._init,K(ue(M._payload),U,Z,ae,ce)}}if(ue)return ce=ce(M),ue=ae===""?"."+$(M,0):ae,D(ce)?(Z="",ue!=null&&(Z=ue.replace(F,"$&/")+"/"),K(ce,U,Z,"",function(he){return he})):ce!=null&&(B(ce)&&(ce=H(ce,Z+(ce.key==null||M&&M.key===ce.key?"":(""+ce.key).replace(F,"$&/")+"/")+ue)),U.push(ce)),1;ue=0;var ve=ae===""?".":ae+":";if(D(M))for(var ee=0;ee"u"?!1:e instanceof ShadowRoot||e instanceof Cn(e).ShadowRoot}function Qd(e){const{overflow:t,overflowX:a,overflowY:o,display:c}=yr(e);return/auto|scroll|overlay|hidden|clip/.test(t+o+a)&&c!=="inline"&&c!=="contents"}function tz(e){return/^(table|td|th)$/.test(Fs(e))}function Hm(e){try{if(e.matches(":popover-open"))return!0}catch{}try{return e.matches(":modal")}catch{return!1}}const nz=/transform|translate|scale|rotate|perspective|filter/,sz=/paint|layout|strict|content/,Ni=e=>!!e&&e!=="none";let Ev;function Av(e){const t=Rt(e)?yr(e):e;return Ni(t.transform)||Ni(t.translate)||Ni(t.scale)||Ni(t.rotate)||Ni(t.perspective)||!Rv()&&(Ni(t.backdropFilter)||Ni(t.filter))||nz.test(t.willChange||"")||sz.test(t.contain||"")}function rz(e){let t=ao(e);for(;pn(t)&&!ro(t);){if(Av(t))return t;if(Hm(t))return null;t=ao(t)}return null}function Rv(){return Ev==null&&(Ev=typeof CSS<"u"&&CSS.supports&&CSS.supports("-webkit-backdrop-filter","none")),Ev}function ro(e){return/^(html|body|#document)$/.test(Fs(e))}function yr(e){return Cn(e).getComputedStyle(e)}function Um(e){return Rt(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function ao(e){if(Fs(e)==="html")return e;const t=e.assignedSlot||e.parentNode||Gc(e)&&e.host||bl(e);return Gc(t)?t.host:t}function yC(e){const t=ao(e);return ro(t)?(e.ownerDocument||e).body:pn(t)&&Qd(t)?t:yC(t)}function Kc(e,t,a){var o;t===void 0&&(t=[]),a===void 0&&(a=!0);const c=yC(e),d=c===((o=e.ownerDocument)==null?void 0:o.body),f=Cn(c);if(d){const p=Ov(f);return t.concat(f,f.visualViewport||[],Qd(c)?c:[],p&&a?Kc(p):[])}else return t.concat(c,Kc(c,[],a))}function Ov(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}const Mv={...ez},jC={};function Ps(e,t){const a=x.useRef(jC);return a.current===jC&&(a.current=e(t)),a}const Dv=Mv.useInsertionEffect,az=Dv&&Dv!==Mv.useLayoutEffect?Dv:e=>e();function Ie(e){const t=Ps(lz).current;return t.next=e,az(t.effect),t.trampoline}function lz(){const e={next:void 0,callback:oz,trampoline:(...t)=>e.callback?.(...t),effect:()=>{e.callback=e.next}};return e}function oz(){}const Me=typeof document<"u"?x.useLayoutEffect:()=>{};function Iv(e,t){if(e&&!t)return e;if(!e&&t)return t;if(e||t)return{...e,...t}}const Pv={};function ta(e,t,a,o,c){if(!a&&!o&&!c&&!e)return Vm(t);let d=Vm(e);return t&&(d=Zd(d,t)),a&&(d=Zd(d,a)),o&&(d=Zd(d,o)),c&&(d=Zd(d,c)),d}function iz(e){if(e.length===0)return Pv;if(e.length===1)return Vm(e[0]);let t=Vm(e[0]);for(let a=1;a=65&&c<=90&&(typeof t=="function"||typeof t>"u")}function _v(e){return typeof e=="function"}function SC(e,t){return _v(e)?e(t):e??Pv}function dz(e,t){return t?e?(...a)=>{const o=a[0];if(CC(o)){const d=o;Fm(d);const f=t(...a);return d.baseUIHandlerPrevented||e?.(...a),f}const c=t(...a);return e?.(...a),c}:NC(t):e}function NC(e){return e&&((...t)=>{const a=t[0];return CC(a)&&Fm(a),e(...t)})}function Fm(e){return e.preventBaseUIHandler=()=>{e.baseUIHandlerPrevented=!0},e}function kC(e,t){return t?e?t+" "+e:t:e}function CC(e){return e!=null&&typeof e=="object"&&"nativeEvent"in e}function fz(e,t){return function(o,...c){const d=new URL(e);return d.searchParams.set("code",o.toString()),c.forEach(f=>d.searchParams.append("args[]",f)),`${t} error #${o}; visit ${d} for the full message.`}}const un=fz("https://base-ui.com/production-error","Base UI"),TC=x.createContext(void 0);function EC(e=!1){const t=x.useContext(TC);if(t===void 0&&!e)throw new Error(un(16));return t}function pz(e){const{focusableWhenDisabled:t,disabled:a,composite:o=!1,tabIndex:c=0,isNativeButton:d}=e,f=o&&t!==!1,p=o&&t===!1;return{props:x.useMemo(()=>{const b={onKeyDown(y){a&&t&&y.key!=="Tab"&&y.preventDefault()}};return o||(b.tabIndex=c,!d&&a&&(b.tabIndex=t?c:-1)),(d&&(t||f)||!d&&a)&&(b["aria-disabled"]=a),d&&(!t||p)&&(b.disabled=a),b},[o,a,t,f,p,d,c])}}function Gt(e){return e?.ownerDocument||document}function Yc(e,t,{detail:a=0}={}){e.dispatchEvent(new(Cn(e)).PointerEvent("click",{bubbles:!0,cancelable:!0,composed:!0,detail:a,shiftKey:t.shiftKey,ctrlKey:t.ctrlKey,altKey:t.altKey,metaKey:t.metaKey}))}function na(e={}){const{disabled:t=!1,focusableWhenDisabled:a,tabIndex:o=0,native:c=!0,composite:d}=e,f=x.useRef(null),p=EC(!0),h=d??p!==void 0,{props:b}=pz({focusableWhenDisabled:a,disabled:t,composite:h,tabIndex:o,isNativeButton:c}),y=x.useCallback(()=>{const w=f.current;Lv(w)&&h&&t&&b.disabled===void 0&&w.disabled&&(w.disabled=!1)},[t,b.disabled,h]);Me(y,[y]);const v=x.useCallback((w={})=>{const{onClick:S,onMouseDown:N,onKeyUp:k,onKeyDown:A,onPointerDown:P,...R}=w;return ta({onClick(C){if(t){C.preventDefault();return}S?.(C)},onMouseDown(C){t||N?.(C)},onKeyDown(C){if(t||(Fm(C),A?.(C),C.baseUIHandlerPrevented))return;const E=C.target===C.currentTarget,D=C.currentTarget,I=Lv(D),O=!c&&mz(D),_=E&&(c?I:!O),z=C.key==="Enter",H=C.key===" ",B=D.getAttribute("role"),L=B?.startsWith("menuitem")||B==="option"||B==="gridcell";if(E&&h&&H){if(C.defaultPrevented&&L)return;C.preventDefault(),(!c||I)&&(C.preventBaseUIHandler(),Yc(D,C));return}if(!_||c||!H&&!z){E&&O&&H&&C.preventDefault();return}C.defaultPrevented||(C.preventDefault(),z&&(C.preventBaseUIHandler(),Yc(D,C)))},onKeyUp(C){if(!t){if(Fm(C),k?.(C),C.target===C.currentTarget&&c&&h&&Lv(C.currentTarget)&&C.key===" "){C.preventDefault();return}C.baseUIHandlerPrevented||C.target===C.currentTarget&&!c&&!h&&!C.defaultPrevented&&C.key===" "&&(C.preventBaseUIHandler(),Yc(C.currentTarget,C))}},onPointerDown(C){if(t){C.preventDefault();return}P?.(C)}},c?{type:"button"}:{role:"button"},b,R)},[t,b,h,c]),j=Ie(w=>{f.current=w,y()});return{getButtonProps:v,buttonRef:j}}function Lv(e){return pn(e)&&e.tagName==="BUTTON"}function mz(e){return pn(e)&&e.tagName==="A"&&!!e.href}function sa(e,t,a,o){const c=Ps(AC).current;return gz(c,e,t,a,o)&&RC(c,[e,t,a,o]),c.callback}function hz(e){const t=Ps(AC).current;return xz(t,e)&&RC(t,e),t.callback}function AC(){return{callback:null,cleanup:null,refs:[]}}function gz(e,t,a,o,c){return e.refs[0]!==t||e.refs[1]!==a||e.refs[2]!==o||e.refs[3]!==c}function xz(e,t){return e.refs.length!==t.length||e.refs.some((a,o)=>a!==t[o])}function RC(e,t){if(e.refs=t,t.every(a=>a==null)){e.callback=null;return}e.callback=a=>{if(e.cleanup&&(e.cleanup(),e.cleanup=null),a!=null){const o=Array(t.length).fill(null);for(let c=0;c{for(let c=0;c=e}function OC(e){if(!x.isValidElement(e))return null;const t=e,a=t.props;return(zv(19)?a?.ref:t.ref)??null}function Kt(){}const Ir=Object.freeze([]),mn=Object.freeze({});function vz(e,t){const a={};for(const o in e){const c=e[o];if(t?.hasOwnProperty(o)){const d=t[o](c);d!=null&&Object.assign(a,d);continue}c===!0?a[`data-${o.toLowerCase()}`]="":c&&(a[`data-${o.toLowerCase()}`]=c.toString())}return a}function yz(e,t){return typeof e=="function"?e(t):e}function jz(e,t){return typeof e=="function"?e(t):e}function yt(e,t,a={}){let o=t.render;a.enabled!==!1&&(o=kz(o));const c=wz(t,a,o);if(a.enabled===!1)return null;const d=a.state??mn;return Cz(e,o,c,d)}function wz(e,t,a){const{className:o,style:c}=e,{state:d=mn,ref:f,props:p,stateAttributesMapping:h,enabled:b=!0}=t,y=b?yz(o,d):void 0,v=b?jz(c,d):void 0,j=b?vz(d,h):mn,w=b&&p?Sz(p):void 0,S=b?Iv(j,w)??{}:mn;return typeof document<"u"&&(b?Array.isArray(f)?S.ref=hz([S.ref,OC(a),...f]):S.ref=sa(S.ref,OC(a),f):sa(null,null)),b?(y!==void 0&&(S.className=kC(S.className,y)),v!==void 0&&(S.style=Iv(S.style,v)),S):mn}function Sz(e){return Array.isArray(e)?iz(e):ta(void 0,e)}const Nz=Symbol.for("react.lazy");function kz(e){if(e?.$$typeof!==Nz)return e;const t=x.Children.toArray(e)[0];return x.isValidElement(t)?t:e}function Cz(e,t,a,o){if(t){if(typeof t=="function")return t(a,o);const c=ta(a,t.props);return c.ref=a.ref,x.cloneElement(t,c)}if(e&&typeof e=="string")return Tz(e,a);throw new Error(un(8))}function Tz(e,t){return e==="button"?x.createElement("button",{type:"button",...t,key:t.key}):e==="img"?x.createElement("img",{alt:"",...t,key:t.key}):x.createElement(e,t)}const Ez=x.forwardRef(function(t,a){const{render:o,className:c,disabled:d=!1,focusableWhenDisabled:f=!1,nativeButton:p=!0,style:h,...b}=t,{getButtonProps:y,buttonRef:v}=na({disabled:d,focusableWhenDisabled:f,native:p});return yt("button",t,{state:{disabled:d},ref:[a,v],props:[b,y]})});function MC(e){var t,a,o="";if(typeof e=="string"||typeof e=="number")o+=e;else if(typeof e=="object")if(Array.isArray(e)){var c=e.length;for(t=0;ttypeof e=="boolean"?`${e}`:e===0?"0":e,PC=DC,Xc=(e,t)=>a=>{var o;if(t?.variants==null)return PC(e,a?.class,a?.className);const{variants:c,defaultVariants:d}=t,f=Object.keys(c).map(b=>{const y=a?.[b],v=d?.[b];if(y===null)return null;const j=IC(y)||IC(v);return c[b][j]}),p=a&&Object.entries(a).reduce((b,y)=>{let[v,j]=y;return j===void 0||(b[v]=j),b},{}),h=t==null||(o=t.compoundVariants)===null||o===void 0?void 0:o.reduce((b,y)=>{let{class:v,className:j,...w}=y;return Object.entries(w).every(S=>{let[N,k]=S;return Array.isArray(k)?k.includes({...d,...p}[N]):{...d,...p}[N]===k})?[...b,v,j]:b},[]);return PC(e,f,h,a?.class,a?.className)},Az=(e,t)=>{const a=new Array(e.length+t.length);for(let o=0;o({classGroupId:e,validator:t}),_C=(e=new Map,t=null,a)=>({nextPart:e,validators:t,classGroupId:a}),$m="-",LC=[],Oz="arbitrary..",Mz=e=>{const t=Iz(e),{conflictingClassGroups:a,conflictingClassGroupModifiers:o}=e;return{getClassGroupId:f=>{if(f.startsWith("[")&&f.endsWith("]"))return Dz(f);const p=f.split($m),h=p[0]===""&&p.length>1?1:0;return zC(p,h,t)},getConflictingClassGroupIds:(f,p)=>{if(p){const h=o[f],b=a[f];return h?b?Az(b,h):h:b||LC}return a[f]||LC}}},zC=(e,t,a)=>{if(e.length-t===0)return a.classGroupId;const c=e[t],d=a.nextPart.get(c);if(d){const b=zC(e,t+1,d);if(b)return b}const f=a.validators;if(f===null)return;const p=t===0?e.join($m):e.slice(t).join($m),h=f.length;for(let b=0;be.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const t=e.slice(1,-1),a=t.indexOf(":"),o=t.slice(0,a);return o?Oz+o:void 0})(),Iz=e=>{const{theme:t,classGroups:a}=e;return Pz(a,t)},Pz=(e,t)=>{const a=_C();for(const o in e){const c=e[o];Bv(c,a,o,t)}return a},Bv=(e,t,a,o)=>{const c=e.length;for(let d=0;d{if(typeof e=="string"){Lz(e,t,a);return}if(typeof e=="function"){zz(e,t,a,o);return}Bz(e,t,a,o)},Lz=(e,t,a)=>{const o=e===""?t:BC(t,e);o.classGroupId=a},zz=(e,t,a,o)=>{if(Hz(e)){Bv(e(o),t,a,o);return}t.validators===null&&(t.validators=[]),t.validators.push(Rz(a,e))},Bz=(e,t,a,o)=>{const c=Object.entries(e),d=c.length;for(let f=0;f{let a=e;const o=t.split($m),c=o.length;for(let d=0;d"isThemeGetter"in e&&e.isThemeGetter===!0,Uz=e=>{if(e<1)return{get:()=>{},set:()=>{}};let t=0,a=Object.create(null),o=Object.create(null);const c=(d,f)=>{a[d]=f,t++,t>e&&(t=0,o=a,a=Object.create(null))};return{get(d){let f=a[d];if(f!==void 0)return f;if((f=o[d])!==void 0)return c(d,f),f},set(d,f){d in a?a[d]=f:c(d,f)}}},Hv="!",HC=":",Vz=[],UC=(e,t,a,o,c)=>({modifiers:e,hasImportantModifier:t,baseClassName:a,maybePostfixModifierPosition:o,isExternal:c}),Fz=e=>{const{prefix:t,experimentalParseClassName:a}=e;let o=c=>{const d=[];let f=0,p=0,h=0,b;const y=c.length;for(let N=0;Nh?b-h:void 0;return UC(d,w,j,S)};if(t){const c=t+HC,d=o;o=f=>f.startsWith(c)?d(f.slice(c.length)):UC(Vz,!1,f,void 0,!0)}if(a){const c=o;o=d=>a({className:d,parseClassName:c})}return o},$z=e=>{const t=new Map;return e.orderSensitiveModifiers.forEach((a,o)=>{t.set(a,1e6+o)}),a=>{const o=[];let c=[];for(let d=0;d0&&(c.sort(),o.push(...c),c=[]),o.push(f)):c.push(f)}return c.length>0&&(c.sort(),o.push(...c)),o}},qz=e=>({cache:Uz(e.cacheSize),parseClassName:Fz(e),sortModifiers:$z(e),postfixLookupClassGroupIds:Gz(e),...Mz(e)}),Gz=e=>{const t=Object.create(null),a=e.postfixLookupClassGroups;if(a)for(let o=0;o{const{parseClassName:a,getClassGroupId:o,getConflictingClassGroupIds:c,sortModifiers:d,postfixLookupClassGroupIds:f}=t,p=[],h=e.trim().split(Kz);let b="";for(let y=h.length-1;y>=0;y-=1){const v=h[y],{isExternal:j,modifiers:w,hasImportantModifier:S,baseClassName:N,maybePostfixModifierPosition:k}=a(v);if(j){b=v+(b.length>0?" "+b:b);continue}let A=!!k,P;if(A){const I=N.substring(0,k);P=o(I);const O=P&&f[P]?o(N):void 0;O&&O!==P&&(P=O,A=!1)}else P=o(N);if(!P){if(!A){b=v+(b.length>0?" "+b:b);continue}if(P=o(N),!P){b=v+(b.length>0?" "+b:b);continue}A=!1}const R=w.length===0?"":w.length===1?w[0]:d(w).join(":"),C=S?R+Hv:R,E=C+P;if(p.indexOf(E)>-1)continue;p.push(E);const D=c(P,A);for(let I=0;I0?" "+b:b)}return b},Xz=(...e)=>{let t=0,a,o,c="";for(;t{if(typeof e=="string")return e;let t,a="";for(let o=0;o{let a,o,c,d;const f=h=>{const b=t.reduce((y,v)=>v(y),e());return a=qz(b),o=a.cache.get,c=a.cache.set,d=p,p(h)},p=h=>{const b=o(h);if(b)return b;const y=Yz(h,a);return c(h,y),y};return d=f,(...h)=>d(Xz(...h))},Zz=[],ks=e=>{const t=a=>a[e]||Zz;return t.isThemeGetter=!0,t.themeKey=e,t},FC=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,$C=/^\((?:(\w[\w-]*):)?(.+)\)$/i,Wz=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,Jz=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,eB=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,tB=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix|color|light-dark)\(.+\)$/,nB=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,sB=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,lo=e=>Wz.test(e),Nt=e=>!!e&&!Number.isNaN(Number(e)),qa=e=>!!e&&Number.isInteger(Number(e)),Uv=e=>e.endsWith("%")&&Nt(e.slice(0,-1)),vl=e=>Jz.test(e),qC=()=>!0,rB=e=>eB.test(e)&&!tB.test(e),Vv=()=>!1,aB=e=>nB.test(e),lB=e=>sB.test(e),oB=e=>!Ye(e)&&!Qe(e),iB=e=>e.startsWith("@container")&&(e[10]==="/"&&e[11]!==void 0||e[11]==="s"&&e[16]!==void 0&&e.startsWith("-size/",10)||e[11]==="n"&&e[18]!==void 0&&e.startsWith("-normal/",10)),cB=e=>oo(e,ZC,Vv),Ye=e=>FC.test(e),ki=e=>oo(e,WC,rB),GC=e=>oo(e,xB,Nt),uB=e=>oo(e,e1,qC),dB=e=>oo(e,JC,Vv),KC=e=>oo(e,XC,Vv),fB=e=>oo(e,QC,lB),qm=e=>oo(e,t1,aB),Qe=e=>$C.test(e),Wd=e=>Ci(e,WC),pB=e=>Ci(e,JC),YC=e=>Ci(e,XC),mB=e=>Ci(e,ZC),hB=e=>Ci(e,QC),Gm=e=>Ci(e,t1,!0),gB=e=>Ci(e,e1,!0),oo=(e,t,a)=>{const o=FC.exec(e);return o?o[1]?t(o[1]):a(o[2]):!1},Ci=(e,t,a=!1)=>{const o=$C.exec(e);return o?o[1]?t(o[1]):a:!1},XC=e=>e==="position"||e==="percentage",QC=e=>e==="image"||e==="url",ZC=e=>e==="length"||e==="size"||e==="bg-size",WC=e=>e==="length",xB=e=>e==="number",JC=e=>e==="family-name",e1=e=>e==="number"||e==="weight",t1=e=>e==="shadow",bB=Qz(()=>{const e=ks("color"),t=ks("font"),a=ks("text"),o=ks("font-weight"),c=ks("tracking"),d=ks("leading"),f=ks("breakpoint"),p=ks("container"),h=ks("spacing"),b=ks("radius"),y=ks("shadow"),v=ks("inset-shadow"),j=ks("text-shadow"),w=ks("drop-shadow"),S=ks("blur"),N=ks("perspective"),k=ks("aspect"),A=ks("ease"),P=ks("animate"),R=()=>["auto","avoid","all","avoid-page","page","left","right","column"],C=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],E=()=>[...C(),Qe,Ye],D=()=>["auto","hidden","clip","visible","scroll"],I=()=>["auto","contain","none"],O=()=>[Qe,Ye,h],_=()=>[lo,"full","auto",...O()],z=()=>[qa,"none","subgrid",Qe,Ye],H=()=>["auto",{span:["full",qa,Qe,Ye]},qa,Qe,Ye],B=()=>[qa,"auto",Qe,Ye],L=()=>["auto","min","max","fr",Qe,Ye],F=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],$=()=>["start","end","center","stretch","center-safe","end-safe"],X=()=>["auto",...O()],K=()=>[lo,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...O()],q=()=>[p,lo,"screen","full","dvw","lvw","svw","min","max","fit",...O()],Q=()=>[lo,"screen","full","lh","dvh","lvh","svh","min","max","fit",...O()],G=()=>[e,Qe,Ye],J=()=>[...C(),YC,KC,{position:[Qe,Ye]}],Y=()=>["no-repeat",{repeat:["","x","y","space","round"]}],re=()=>["auto","cover","contain",mB,cB,{size:[Qe,Ye]}],M=()=>[Uv,Wd,ki],U=()=>["","none","full",b,Qe,Ye],Z=()=>["",Nt,Wd,ki],ae=()=>["solid","dashed","dotted","double"],ce=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],W=()=>[Nt,Uv,YC,KC],ue=()=>["","none",S,Qe,Ye],ve=()=>["none",Nt,Qe,Ye],ee=()=>["none",Nt,Qe,Ye],he=()=>[Nt,Qe,Ye],te=()=>[lo,"full",...O()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[vl],breakpoint:[vl],color:[qC],container:[vl],"drop-shadow":[vl],ease:["in","out","in-out"],font:[oB],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[vl],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[vl],shadow:[vl],spacing:["px",Nt],text:[vl],"text-shadow":[vl],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",lo,Ye,Qe,k]}],container:["container"],"container-type":[{"@container":["","normal","size",Qe,Ye]}],"container-named":[iB],columns:[{columns:[Nt,"auto",Ye,Qe,p]}],"break-after":[{"break-after":R()}],"break-before":[{"break-before":R()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:E()}],overflow:[{overflow:D()}],"overflow-x":[{"overflow-x":D()}],"overflow-y":[{"overflow-y":D()}],overscroll:[{overscroll:I()}],"overscroll-x":[{"overscroll-x":I()}],"overscroll-y":[{"overscroll-y":I()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:_()}],"inset-x":[{"inset-x":_()}],"inset-y":[{"inset-y":_()}],start:[{"inset-s":_(),start:_()}],end:[{"inset-e":_(),end:_()}],"inset-bs":[{"inset-bs":_()}],"inset-be":[{"inset-be":_()}],top:[{top:_()}],right:[{right:_()}],bottom:[{bottom:_()}],left:[{left:_()}],visibility:["visible","invisible","collapse"],z:[{z:[qa,"auto",Qe,Ye]}],basis:[{basis:[lo,"full","auto",p,...O()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[Nt,lo,"auto","initial","none",Ye]}],grow:[{grow:["",Nt,Qe,Ye]}],shrink:[{shrink:["",Nt,Qe,Ye]}],order:[{order:[qa,"first","last","none",Qe,Ye]}],"grid-cols":[{"grid-cols":z()}],"col-start-end":[{col:H()}],"col-start":[{"col-start":B()}],"col-end":[{"col-end":B()}],"grid-rows":[{"grid-rows":z()}],"row-start-end":[{row:H()}],"row-start":[{"row-start":B()}],"row-end":[{"row-end":B()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":L()}],"auto-rows":[{"auto-rows":L()}],gap:[{gap:O()}],"gap-x":[{"gap-x":O()}],"gap-y":[{"gap-y":O()}],"justify-content":[{justify:[...F(),"normal"]}],"justify-items":[{"justify-items":[...$(),"normal"]}],"justify-self":[{"justify-self":["auto",...$()]}],"align-content":[{content:["normal",...F()]}],"align-items":[{items:[...$(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...$(),{baseline:["","last"]}]}],"place-content":[{"place-content":F()}],"place-items":[{"place-items":[...$(),"baseline"]}],"place-self":[{"place-self":["auto",...$()]}],p:[{p:O()}],px:[{px:O()}],py:[{py:O()}],ps:[{ps:O()}],pe:[{pe:O()}],pbs:[{pbs:O()}],pbe:[{pbe:O()}],pt:[{pt:O()}],pr:[{pr:O()}],pb:[{pb:O()}],pl:[{pl:O()}],m:[{m:X()}],mx:[{mx:X()}],my:[{my:X()}],ms:[{ms:X()}],me:[{me:X()}],mbs:[{mbs:X()}],mbe:[{mbe:X()}],mt:[{mt:X()}],mr:[{mr:X()}],mb:[{mb:X()}],ml:[{ml:X()}],"space-x":[{"space-x":O()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":O()}],"space-y-reverse":["space-y-reverse"],size:[{size:K()}],"inline-size":[{inline:["auto",...q()]}],"min-inline-size":[{"min-inline":["auto",...q()]}],"max-inline-size":[{"max-inline":["none",...q()]}],"block-size":[{block:["auto",...Q()]}],"min-block-size":[{"min-block":["auto",...Q()]}],"max-block-size":[{"max-block":["none",...Q()]}],w:[{w:[p,"screen",...K()]}],"min-w":[{"min-w":[p,"screen","none",...K()]}],"max-w":[{"max-w":[p,"screen","none","prose",{screen:[f]},...K()]}],h:[{h:["screen","lh",...K()]}],"min-h":[{"min-h":["screen","lh","none",...K()]}],"max-h":[{"max-h":["screen","lh","none",...K()]}],"font-size":[{text:["base",a,Wd,ki]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[o,gB,uB]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",Uv,Ye]}],"font-family":[{font:[pB,dB,t]}],"font-features":[{"font-features":[Ye]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[c,Qe,Ye]}],"line-clamp":[{"line-clamp":[Nt,"none",Qe,GC]}],leading:[{leading:["none",d,...O()]}],"list-image":[{"list-image":["none",Qe,Ye]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",Qe,Ye]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:G()}],"text-color":[{text:G()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...ae(),"wavy"]}],"text-decoration-thickness":[{decoration:[Nt,"from-font","auto",Qe,ki]}],"text-decoration-color":[{decoration:G()}],"underline-offset":[{"underline-offset":[Nt,"auto",Qe,Ye]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:O()}],"tab-size":[{tab:[qa,Qe,Ye]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",Qe,Ye]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",Qe,Ye]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:J()}],"bg-repeat":[{bg:Y()}],"bg-size":[{bg:re()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},qa,Qe,Ye],radial:["",Qe,Ye],conic:["",qa,Qe,Ye]},hB,fB]}],"bg-color":[{bg:G()}],"gradient-from-pos":[{from:M()}],"gradient-via-pos":[{via:M()}],"gradient-to-pos":[{to:M()}],"gradient-from":[{from:G()}],"gradient-via":[{via:G()}],"gradient-to":[{to:G()}],rounded:[{rounded:U()}],"rounded-s":[{"rounded-s":U()}],"rounded-e":[{"rounded-e":U()}],"rounded-t":[{"rounded-t":U()}],"rounded-r":[{"rounded-r":U()}],"rounded-b":[{"rounded-b":U()}],"rounded-l":[{"rounded-l":U()}],"rounded-ss":[{"rounded-ss":U()}],"rounded-se":[{"rounded-se":U()}],"rounded-ee":[{"rounded-ee":U()}],"rounded-es":[{"rounded-es":U()}],"rounded-tl":[{"rounded-tl":U()}],"rounded-tr":[{"rounded-tr":U()}],"rounded-br":[{"rounded-br":U()}],"rounded-bl":[{"rounded-bl":U()}],"border-w":[{border:Z()}],"border-w-x":[{"border-x":Z()}],"border-w-y":[{"border-y":Z()}],"border-w-s":[{"border-s":Z()}],"border-w-e":[{"border-e":Z()}],"border-w-bs":[{"border-bs":Z()}],"border-w-be":[{"border-be":Z()}],"border-w-t":[{"border-t":Z()}],"border-w-r":[{"border-r":Z()}],"border-w-b":[{"border-b":Z()}],"border-w-l":[{"border-l":Z()}],"divide-x":[{"divide-x":Z()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":Z()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...ae(),"hidden","none"]}],"divide-style":[{divide:[...ae(),"hidden","none"]}],"border-color":[{border:G()}],"border-color-x":[{"border-x":G()}],"border-color-y":[{"border-y":G()}],"border-color-s":[{"border-s":G()}],"border-color-e":[{"border-e":G()}],"border-color-bs":[{"border-bs":G()}],"border-color-be":[{"border-be":G()}],"border-color-t":[{"border-t":G()}],"border-color-r":[{"border-r":G()}],"border-color-b":[{"border-b":G()}],"border-color-l":[{"border-l":G()}],"divide-color":[{divide:G()}],"outline-style":[{outline:[...ae(),"none","hidden"]}],"outline-offset":[{"outline-offset":[Nt,Qe,Ye]}],"outline-w":[{outline:["",Nt,Wd,ki]}],"outline-color":[{outline:G()}],shadow:[{shadow:["","inner","none",y,Gm,qm]}],"shadow-color":[{shadow:G()}],"inset-shadow":[{"inset-shadow":["none",v,Gm,qm]}],"inset-shadow-color":[{"inset-shadow":G()}],"ring-w":[{ring:Z()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:G()}],"ring-offset-w":[{"ring-offset":[Nt,ki]}],"ring-offset-color":[{"ring-offset":G()}],"inset-ring-w":[{"inset-ring":Z()}],"inset-ring-color":[{"inset-ring":G()}],"text-shadow":[{"text-shadow":["none",j,Gm,qm]}],"text-shadow-color":[{"text-shadow":G()}],opacity:[{opacity:[Nt,Qe,Ye]}],"mix-blend":[{"mix-blend":[...ce(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":ce()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[Nt]}],"mask-image-linear-from-pos":[{"mask-linear-from":W()}],"mask-image-linear-to-pos":[{"mask-linear-to":W()}],"mask-image-linear-from-color":[{"mask-linear-from":G()}],"mask-image-linear-to-color":[{"mask-linear-to":G()}],"mask-image-t-from-pos":[{"mask-t-from":W()}],"mask-image-t-to-pos":[{"mask-t-to":W()}],"mask-image-t-from-color":[{"mask-t-from":G()}],"mask-image-t-to-color":[{"mask-t-to":G()}],"mask-image-r-from-pos":[{"mask-r-from":W()}],"mask-image-r-to-pos":[{"mask-r-to":W()}],"mask-image-r-from-color":[{"mask-r-from":G()}],"mask-image-r-to-color":[{"mask-r-to":G()}],"mask-image-b-from-pos":[{"mask-b-from":W()}],"mask-image-b-to-pos":[{"mask-b-to":W()}],"mask-image-b-from-color":[{"mask-b-from":G()}],"mask-image-b-to-color":[{"mask-b-to":G()}],"mask-image-l-from-pos":[{"mask-l-from":W()}],"mask-image-l-to-pos":[{"mask-l-to":W()}],"mask-image-l-from-color":[{"mask-l-from":G()}],"mask-image-l-to-color":[{"mask-l-to":G()}],"mask-image-x-from-pos":[{"mask-x-from":W()}],"mask-image-x-to-pos":[{"mask-x-to":W()}],"mask-image-x-from-color":[{"mask-x-from":G()}],"mask-image-x-to-color":[{"mask-x-to":G()}],"mask-image-y-from-pos":[{"mask-y-from":W()}],"mask-image-y-to-pos":[{"mask-y-to":W()}],"mask-image-y-from-color":[{"mask-y-from":G()}],"mask-image-y-to-color":[{"mask-y-to":G()}],"mask-image-radial":[{"mask-radial":[Qe,Ye]}],"mask-image-radial-from-pos":[{"mask-radial-from":W()}],"mask-image-radial-to-pos":[{"mask-radial-to":W()}],"mask-image-radial-from-color":[{"mask-radial-from":G()}],"mask-image-radial-to-color":[{"mask-radial-to":G()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":C()}],"mask-image-conic-pos":[{"mask-conic":[Nt]}],"mask-image-conic-from-pos":[{"mask-conic-from":W()}],"mask-image-conic-to-pos":[{"mask-conic-to":W()}],"mask-image-conic-from-color":[{"mask-conic-from":G()}],"mask-image-conic-to-color":[{"mask-conic-to":G()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:J()}],"mask-repeat":[{mask:Y()}],"mask-size":[{mask:re()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",Qe,Ye]}],filter:[{filter:["","none",Qe,Ye]}],blur:[{blur:ue()}],brightness:[{brightness:[Nt,Qe,Ye]}],contrast:[{contrast:[Nt,Qe,Ye]}],"drop-shadow":[{"drop-shadow":["","none",w,Gm,qm]}],"drop-shadow-color":[{"drop-shadow":G()}],grayscale:[{grayscale:["",Nt,Qe,Ye]}],"hue-rotate":[{"hue-rotate":[Nt,Qe,Ye]}],invert:[{invert:["",Nt,Qe,Ye]}],saturate:[{saturate:[Nt,Qe,Ye]}],sepia:[{sepia:["",Nt,Qe,Ye]}],"backdrop-filter":[{"backdrop-filter":["","none",Qe,Ye]}],"backdrop-blur":[{"backdrop-blur":ue()}],"backdrop-brightness":[{"backdrop-brightness":[Nt,Qe,Ye]}],"backdrop-contrast":[{"backdrop-contrast":[Nt,Qe,Ye]}],"backdrop-grayscale":[{"backdrop-grayscale":["",Nt,Qe,Ye]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[Nt,Qe,Ye]}],"backdrop-invert":[{"backdrop-invert":["",Nt,Qe,Ye]}],"backdrop-opacity":[{"backdrop-opacity":[Nt,Qe,Ye]}],"backdrop-saturate":[{"backdrop-saturate":[Nt,Qe,Ye]}],"backdrop-sepia":[{"backdrop-sepia":["",Nt,Qe,Ye]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":O()}],"border-spacing-x":[{"border-spacing-x":O()}],"border-spacing-y":[{"border-spacing-y":O()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",Qe,Ye]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[Nt,"initial",Qe,Ye]}],ease:[{ease:["linear","initial",A,Qe,Ye]}],delay:[{delay:[Nt,Qe,Ye]}],animate:[{animate:["none",P,Qe,Ye]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[N,Qe,Ye]}],"perspective-origin":[{"perspective-origin":E()}],rotate:[{rotate:ve()}],"rotate-x":[{"rotate-x":ve()}],"rotate-y":[{"rotate-y":ve()}],"rotate-z":[{"rotate-z":ve()}],scale:[{scale:ee()}],"scale-x":[{"scale-x":ee()}],"scale-y":[{"scale-y":ee()}],"scale-z":[{"scale-z":ee()}],"scale-3d":["scale-3d"],skew:[{skew:he()}],"skew-x":[{"skew-x":he()}],"skew-y":[{"skew-y":he()}],transform:[{transform:[Qe,Ye,"","none","gpu","cpu"]}],"transform-origin":[{origin:E()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:te()}],"translate-x":[{"translate-x":te()}],"translate-y":[{"translate-y":te()}],"translate-z":[{"translate-z":te()}],"translate-none":["translate-none"],zoom:[{zoom:[qa,Qe,Ye]}],accent:[{accent:G()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:G()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",Qe,Ye]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scrollbar-thumb-color":[{"scrollbar-thumb":G()}],"scrollbar-track-color":[{"scrollbar-track":G()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":O()}],"scroll-mx":[{"scroll-mx":O()}],"scroll-my":[{"scroll-my":O()}],"scroll-ms":[{"scroll-ms":O()}],"scroll-me":[{"scroll-me":O()}],"scroll-mbs":[{"scroll-mbs":O()}],"scroll-mbe":[{"scroll-mbe":O()}],"scroll-mt":[{"scroll-mt":O()}],"scroll-mr":[{"scroll-mr":O()}],"scroll-mb":[{"scroll-mb":O()}],"scroll-ml":[{"scroll-ml":O()}],"scroll-p":[{"scroll-p":O()}],"scroll-px":[{"scroll-px":O()}],"scroll-py":[{"scroll-py":O()}],"scroll-ps":[{"scroll-ps":O()}],"scroll-pe":[{"scroll-pe":O()}],"scroll-pbs":[{"scroll-pbs":O()}],"scroll-pbe":[{"scroll-pbe":O()}],"scroll-pt":[{"scroll-pt":O()}],"scroll-pr":[{"scroll-pr":O()}],"scroll-pb":[{"scroll-pb":O()}],"scroll-pl":[{"scroll-pl":O()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",Qe,Ye]}],fill:[{fill:["none",...G()]}],"stroke-w":[{stroke:[Nt,Wd,ki,GC]}],stroke:[{stroke:["none",...G()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{"container-named":["container-type"],overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","inset-bs","inset-be","start","end","top","right","bottom","left"],"inset-x":["start","end","right","left"],"inset-y":["inset-bs","inset-be","top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pbs","pbe","pt","pr","pb","pl"],px:["ps","pe","pr","pl"],py:["pbs","pbe","pt","pb"],m:["mx","my","ms","me","mbs","mbe","mt","mr","mb","ml"],mx:["ms","me","mr","ml"],my:["mbs","mbe","mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-bs","border-w-be","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-s","border-w-e","border-w-r","border-w-l"],"border-w-y":["border-w-bs","border-w-be","border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-bs","border-color-be","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-s","border-color-e","border-color-r","border-color-l"],"border-color-y":["border-color-bs","border-color-be","border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mbs","scroll-mbe","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-ms","scroll-me","scroll-mr","scroll-ml"],"scroll-my":["scroll-mbs","scroll-mbe","scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pbs","scroll-pbe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-ps","scroll-pe","scroll-pr","scroll-pl"],"scroll-py":["scroll-pbs","scroll-pbe","scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},postfixLookupClassGroups:["container-type"],orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}});function Ue(...e){return bB(DC(e))}const vB=Xc(["group/button inline-flex shrink-0 items-center justify-center gap-1.5 whitespace-nowrap border","font-medium transition-[background-color,border-color,color,transform,box-shadow] duration-150 ease-out","outline-none select-none active:translate-y-[0.5px]","disabled:pointer-events-none disabled:opacity-45 disabled:shadow-none","[&_svg]:pointer-events-none [&_svg]:shrink-0"],{variants:{variant:{default:"border-primary bg-primary font-semibold text-primary-on shadow-glow hover:border-primary-hover hover:bg-primary-hover",outline:"border-control-border bg-control text-foreground shadow-1 hover:border-control-border-hover hover:bg-control-hover",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"border-transparent bg-transparent text-subtle shadow-none hover:bg-control-hover hover:text-foreground",destructive:"border-destructive-bd bg-destructive-soft text-destructive hover:bg-destructive-hover",dashed:"border-dashed border-border-strong bg-transparent text-muted-foreground shadow-none hover:border-primary hover:text-primary-fg",link:"border-transparent bg-transparent text-primary shadow-none underline-offset-4 hover:underline"},size:{default:"h-[30px] rounded-md px-3 text-[12.5px]","2xs":"h-4 rounded-pill px-1.5 text-[10px]",xs:"h-6 rounded-sm px-2 text-[11.5px]",sm:"h-[26px] rounded-sm px-2.5 text-[12px]",lg:"h-9 rounded-md px-4 text-[13px]",icon:"h-[30px] w-[30px] rounded-md p-0","icon-2xs":"size-4 rounded-pill p-0","icon-xs":"size-6 rounded-sm p-0","icon-sm":"h-[26px] w-[26px] rounded-sm p-0","icon-lg":"size-9 rounded-md p-0"}},defaultVariants:{variant:"default",size:"default"}});function ne({className:e,variant:t,size:a,...o}){return s.jsx(Ez,{className:Ue(vB({variant:t,size:a}),e),...o})}const yB="data-valid",jB="data-invalid",wB={badInput:!1,customError:!1,patternMismatch:!1,rangeOverflow:!1,rangeUnderflow:!1,stepMismatch:!1,tooLong:!1,tooShort:!1,typeMismatch:!1,valid:null,valueMissing:!1},n1={valid:null,touched:!1,dirty:!1,filled:!1,focused:!1},SB={disabled:!1,...n1},Ti={valid(e){return e===null?null:e?{[yB]:""}:{[jB]:""}}},s1={invalid:void 0,name:void 0,validityData:{state:wB,errors:[],error:"",value:"",initialValue:null},setValidityData:Kt,disabled:void 0,setTouched:Kt,setDirty:Kt,setFilled:Kt,setFocused:Kt,validationMode:"onSubmit",shouldValidateOnChange:()=>!1,state:SB,registerFieldControl:Kt,validation:{getValidationProps:(e,t=mn)=>t,inputRef:{current:null},registeredInputs:new Map,registerInput:Kt,getInputControl:()=>null,commit:async()=>{},change:Kt}},r1=x.createContext(s1);function Na(e=!0){const t=x.useContext(r1);if(t.setValidityData===Kt&&!e)throw new Error(un(28));return t}const NB=x.createContext(void 0);function kB(e=!1){const t=x.useContext(NB);if(!t&&!e)throw new Error(un(86));return t}const CB=x.createContext({elementRef:{current:null},formRef:{current:{fields:new Map}},errors:{},clearErrors:Kt,validationMode:"onSubmit",submitCountRef:{current:0}});function Qc(){return x.useContext(CB)}let a1=0;function TB(e,t="mui"){const[a,o]=x.useState(e),c=e||a;return x.useEffect(()=>{a==null&&(a1+=1,o(`${t}-${a1}`))},[a,t]),c}const l1=Mv.useId;function Jd(e,t){if(l1!==void 0){const a=l1();return e??(t?`${t}-${a}`:a)}return TB(e,t)}function ka(e){return Jd(e,"base-ui")}const EB=x.createContext({controlId:void 0,registerControlId:Kt,resetControlId:Kt,labelId:void 0,setLabelId:Kt,messageIds:[],setMessageIds:Kt,getDescriptionProps:e=>e});function yl(){return x.useContext(EB)}function Fv(e,t,a,o=!0,c){const[d,f]=x.useState(),p=ka(c?`${c}-label`:void 0),h=e??t??d;return Me(()=>{const b=e||t||!o?void 0:AB(a.current,p);d!==b&&f(b)}),h}function AB(e,t){const a=RB(e);if(a)return!a.id&&t&&(a.id=t),a.id||void 0}function RB(e){if(!e)return;const t=e.parentElement;if(t&&t.tagName==="LABEL")return t;const a=e.id;if(a){const c=e.nextElementSibling;if(c&&c.htmlFor===a)return c}const o=e.labels;return o&&o[0]}function io(e={}){const{id:t,enabled:a=!0}=e,{controlId:o,registerControlId:c,resetControlId:d}=yl(),f=ka(),p=Ps(()=>Symbol()),h=x.useRef(!1),b=x.useRef(!1),y=Ie(()=>{!h.current||c===Kt||(h.current=!1,c(p.current,void 0))});return Me(()=>{if(!a||c===Kt){y();return}let v;if(t!==void 0)b.current=!0,v=t;else if(b.current)v=f;else{d();return}if(v===void 0){y();return}h.current=!0,c(p.current,v)},[t,a,c,d,f,p,y]),Me(()=>y,[y]),(a?o:void 0)??t??f}function OB(){return typeof navigator>"u"?{userAgent:"",platform:"",maxTouchPoints:0}:{userAgent:navigator.userAgent,platform:navigator.platform??"",maxTouchPoints:navigator.maxTouchPoints??0}}const{userAgent:MB,platform:DB,maxTouchPoints:IB}=OB(),Km=MB.toLowerCase(),ef=DB.toLowerCase(),tf=/^i(os$|p)/.test(ef)||ef==="macintel"&&IB>1,o1="android",Ym=ef===o1||Km.includes(o1),i1=!tf&&ef.startsWith("mac");ef.startsWith("win");const PB=i1||tf,jl=typeof CSS<"u"&&!!CSS.supports?.("-webkit-backdrop-filter:none"),c1=!jl&&Km.includes("firefox");!jl&&Km.includes("chrom");const _B=PB,$v=/jsdom|happydom/.test(Km);function ir(e){let t=e.activeElement;for(;t?.shadowRoot?.activeElement!=null;)t=t.shadowRoot.activeElement;return t}function Ze(e,t){if(!e||!t)return!1;const a=t.getRootNode?.();if(e.contains(t))return!0;if(a&&Gc(a)){let o=t;for(;o;){if(e===o)return!0;o=o.parentNode||o.host}}return!1}function fs(e){return"composedPath"in e?e.composedPath()[0]??e.target:e.target}const qv="data-base-ui-focusable",u1="input:not([type='hidden']):not([disabled]),[contenteditable]:not([contenteditable='false']),textarea:not([disabled])",Ei="ArrowLeft",Ai="ArrowRight",Gv="ArrowUp",Xm="ArrowDown",d1="data-starting-style",LB="data-ending-style",zB={[d1]:""},BB={[LB]:""},co={transitionStatus(e){return e==="starting"?zB:e==="ending"?BB:null}},HB="data-open",UB="data-closed",VB="data-anchor-hidden",f1="data-popup-open",FB="data-pressed",$B={[f1]:""},qB={[f1]:"",[FB]:""},GB={[HB]:""},KB={[UB]:""},YB={[VB]:""},Kv={open(e){return e?$B:null}},Yv={open(e){return e?qB:null}},Zc={open(e){return e?GB:KB},anchorHidden(e){return e?YB:null}},Xv={...Zc,...co},Qv="data-trigger-disabled";function Qm(e,t){if(!Rt(e))return!1;const a=e;if(t.hasElement(a))return!a.hasAttribute(Qv);for(const[,o]of t.entries())if(Ze(o,a))return!o.hasAttribute(Qv);return!1}function Zv(e,t){if(t==null)return!1;if("composedPath"in e)return e.composedPath().includes(t);const a=e;return a.target!=null&&t.contains(a.target)}function XB(e){return e.matches("html,body")}function Zm(e){return pn(e)&&e.matches(u1)}function QB(e){return e?.closest(`button,a[href],[role="button"],select,[tabindex]:not([tabindex="-1"]),${u1}`)!=null}function Wv(e){return e?e.getAttribute("role")==="combobox"&&Zm(e):!1}function ZB(e){if(!e||$v)return!0;try{return e.matches(":focus-visible")}catch{return!0}}function Wm(e){return e?e.hasAttribute(qv)?e:e.querySelector(`[${qv}]`)||e:null}function uo(e,t,a=!0){return e.filter(c=>c.parentId===t).flatMap(c=>[...!a||c.context?.open?[c]:[],...uo(e,c.id,a)])}function p1(e,t){let a=[],o=e.find(c=>c.id===t)?.parentId;for(;o;){const c=e.find(d=>d.id===o);o=c?.parentId,c&&(a=a.concat(c))}return a}function Cs(e){e.preventDefault(),e.stopPropagation()}function WB(e){return"nativeEvent"in e}function Jm(e){return e.pointerType===""&&e.isTrusted?!0:Ym&&e.pointerType?e.type==="click"&&e.buttons===1:e.detail===0&&!e.pointerType}function Jv(e){return $v?!1:!Ym&&e.width===0&&e.height===0||Ym&&e.width===1&&e.height===1&&e.pressure===0&&e.detail===0&&e.pointerType==="mouse"||e.width<1&&e.height<1&&e.pressure===0&&e.detail===0&&e.pointerType==="touch"}function fo(e,t){const a=["mouse","pen"];return t||a.push("",void 0),a.includes(e)}function JB(e){const t=e.type;return t==="click"||t==="mousedown"||t==="keydown"||t==="keyup"}const Wc=Math.min,wl=Math.max,eh=Math.round,Ri=Math.floor,Sl=e=>({x:e,y:e}),e4={left:"right",right:"left",bottom:"top",top:"bottom"};function m1(e,t,a){return wl(e,Wc(t,a))}function po(e,t){return typeof e=="function"?e(t):e}function ra(e){return e.split("-")[0]}function Nl(e){return e.split("-")[1]}function ey(e){return e==="x"?"y":"x"}function ty(e){return e==="y"?"height":"width"}function aa(e){const t=e[0];return t==="t"||t==="b"?"y":"x"}function ny(e){return ey(aa(e))}function t4(e,t,a){a===void 0&&(a=!1);const o=Nl(e),c=ny(e),d=ty(c);let f=c==="x"?o===(a?"end":"start")?"right":"left":o==="start"?"bottom":"top";return t.reference[d]>t.floating[d]&&(f=th(f)),[f,th(f)]}function n4(e){const t=th(e);return[sy(e),t,sy(t)]}function sy(e){return e.includes("start")?e.replace("start","end"):e.replace("end","start")}const h1=["left","right"],g1=["right","left"],s4=["top","bottom"],r4=["bottom","top"];function a4(e,t,a){switch(e){case"top":case"bottom":return a?t?g1:h1:t?h1:g1;case"left":case"right":return t?s4:r4;default:return[]}}function l4(e,t,a,o){const c=Nl(e);let d=a4(ra(e),a==="start",o);return c&&(d=d.map(f=>f+"-"+c),t&&(d=d.concat(d.map(sy)))),d}function th(e){const t=ra(e);return e4[t]+e.slice(t.length)}function o4(e){var t,a,o,c;return{top:(t=e.top)!=null?t:0,right:(a=e.right)!=null?a:0,bottom:(o=e.bottom)!=null?o:0,left:(c=e.left)!=null?c:0}}function x1(e){return typeof e!="number"?o4(e):{top:e,right:e,bottom:e,left:e}}function nf(e){const{x:t,y:a,width:o,height:c}=e;return{width:o,height:c,top:a,left:t,right:t+o,bottom:a+c,x:t,y:a}}function nh(e,t,a){return Math.floor(e/t)!==a}function mo(e,t){return t<0||t>=e.length}function sh(e,t){return _s(e.current,{disabledIndices:t})}function ry(e,t){return _s(e.current,{decrement:!0,startingIndex:e.current.length,disabledIndices:t})}function _s(e,{startingIndex:t=-1,decrement:a=!1,disabledIndices:o,amount:c=1}={}){let d=t;do d+=a?-c:c;while(d>=0&&d<=e.length-1&&ho(e,d,o));return d}function i4(e,{event:t,orientation:a,loopFocus:o,onLoop:c,rtl:d,cols:f,disabledIndices:p,minIndex:h,maxIndex:b,prevIndex:y,stopEvent:v=!1}){let j=y,w;if(t.key===Gv?w="up":t.key===Xm&&(w="down"),w){const S=[],N=[];let k=!1,A=0;{let _=null,z=-1;e.forEach((H,B)=>{if(H==null)return;A+=1;const L=H.closest('[role="row"]');L&&(k=!0),(L!==_||z===-1)&&(_=L,z+=1,S[z]=[]),S[z].push(B),N[B]=z})}let P=!1,R=0;if(k)for(const _ of S){const z=_.length;z>R&&(R=z),z!==f&&(P=!0)}const C=P&&A{if(!P||y===-1)return;const z=N[y];if(z==null)return;const H=S[z].indexOf(y),B=_==="up"?-1:1;for(let L=z+B,F=0;F=S.length){if(!o||C)return;if(L=L<0?S.length-1:0,c){const X=Math.min(H,S[L].length-1),K=S[L][X]??S[L][0],q=c(t,y,K);L=N[q]??L}}const $=S[L];for(let X=Math.min(H,$.length-1);X>=0;X-=1){const K=$[X];if(!ho(e,K,p))return K}}},I=_=>{if(!C||y===-1)return;const z=y%E,H=_==="up"?-E:E,B=b-b%E,L=Ri(b/E)+1;for(let F=y-z+H,$=0;$b){if(!o)return;F=F<0?B:0}const X=Math.min(F+E-1,b);for(let K=Math.min(F+z,X);K>=F;K-=1)if(!ho(e,K,p))return K}};v&&Cs(t);const O=D(w)??I(w);if(O!==void 0)j=O;else if(y===-1)j=w==="up"?b:h;else if(j=_s(e,{startingIndex:y,amount:E,decrement:w==="up",disabledIndices:p}),o){if(w==="up"&&(y-E_?H:H-E,c&&(j=c(t,y,j))}w==="down"&&y+E>b&&(j=_s(e,{startingIndex:y%E-E,amount:E,disabledIndices:p}),c&&(j=c(t,y,j)))}mo(e,j)&&(j=y)}if(a==="both"){const S=Ri(y/f);t.key===(d?Ei:Ai)&&(v&&Cs(t),y%f!==f-1?(j=_s(e,{startingIndex:y,disabledIndices:p}),o&&nh(j,f,S)&&(j=_s(e,{startingIndex:y-y%f-1,disabledIndices:p}),c&&(j=c(t,y,j)))):o&&(j=_s(e,{startingIndex:y-y%f-1,disabledIndices:p}),c&&(j=c(t,y,j))),nh(j,f,S)&&(j=y)),t.key===(d?Ai:Ei)&&(v&&Cs(t),y%f!==0?(j=_s(e,{startingIndex:y,decrement:!0,disabledIndices:p}),o&&nh(j,f,S)&&(j=_s(e,{startingIndex:y+(f-y%f),decrement:!0,disabledIndices:p}),c&&(j=c(t,y,j)))):o&&(j=_s(e,{startingIndex:y+(f-y%f),decrement:!0,disabledIndices:p}),c&&(j=c(t,y,j))),nh(j,f,S)&&(j=y));const N=Ri(b/f)===S;mo(e,j)&&(o&&N?(j=t.key===(d?Ai:Ei)?b:_s(e,{startingIndex:y-y%f-1,disabledIndices:p}),c&&(j=c(t,y,j))):j=y)}return j}function ho(e,t,a){if(typeof a=="function"?a(t):a?.includes(t)??!1)return!0;const c=e[t];return c?!rh(c)||c.matches(":disabled")?!0:!a&&(c.hasAttribute("disabled")||c.getAttribute("aria-disabled")==="true"):!1}function c4(e){return e.visibility==="hidden"||e.visibility==="collapse"}function rh(e,t=e?yr(e):null){return!e||!e.isConnected||!t||c4(t)?!1:typeof e.checkVisibility=="function"?e.checkVisibility():t.display!=="none"&&t.display!=="contents"}const u4='a[href],button,input,select,textarea,summary,details,iframe,object,embed,[tabindex],[contenteditable]:not([contenteditable="false"]),audio[controls],video[controls]';function d4(e){const t=e.assignedSlot;if(t)return t;if(e.parentElement)return e.parentElement;const a=e.getRootNode();return Gc(a)?a.host:null}function ay(e){for(const t of Array.from(e.children))if(Fs(t)==="summary")return t;return null}function f4(e,t){const a=ay(t);return!!a&&(e===a||Ze(a,e))}function b1(e){const t=e?Fs(e):"";return e!=null&&e.matches(u4)&&(t!=="summary"||e.parentElement!=null&&Fs(e.parentElement)==="details"&&ay(e.parentElement)===e)&&(t!=="details"||ay(e)==null)&&(t!=="input"||e.type!=="hidden")}function v1(e){if(!b1(e)||!e.isConnected||e.matches(":disabled"))return!1;for(let t=e;t;t=d4(t)){const a=t!==e,o=Fs(t)==="slot";if(t.hasAttribute("inert")||a&&Fs(t)==="details"&&!t.open&&!f4(e,t)||t.hasAttribute("hidden")||!o&&!p4(t,a))return!1}return!0}function p4(e,t){const a=yr(e);return t?a.display!=="none":rh(e,a)}function y1(e){const t=e.tabIndex;if(t<0){const a=Fs(e);if(a==="details"||a==="audio"||a==="video"||pn(e)&&e.isContentEditable)return 0}return t}function ly(e){if(Fs(e)!=="input")return null;const t=e;return t.type==="radio"&&t.name!==""?t:null}function m4(e,t){const a=ly(e);if(!a)return!0;const o=t.find(c=>{const d=ly(c);return d?.name===a.name&&d.form===a.form&&d.checked});return o?o===a:t.find(c=>{const d=ly(c);return d?.name===a.name&&d.form===a.form})===a}function j1(e){if(pn(e)&&Fs(e)==="slot"){const t=e.assignedElements({flatten:!0});if(t.length>0)return t}return pn(e)&&e.shadowRoot?Array.from(e.shadowRoot.children):Array.from(e.children)}function w1(e,t){j1(e).forEach(a=>{b1(a)&&t.push(a),w1(a,t)})}function S1(e,t,a){j1(e).forEach(o=>{pn(o)&&o.matches(t)&&a.push(o),S1(o,t,a)})}function oy(e){return v1(e)&&y1(e)>=0}function N1(e){const t=[];return w1(e,t),t.filter(v1)}function sf(e){const t=N1(e);return t.filter(a=>y1(a)>=0&&m4(a,t))}function k1(e,t){const a=sf(e),o=a.length;if(o===0)return;const c=ir(Gt(e)),d=a.indexOf(c),f=d===-1?t===1?0:o-1:d+t;return a[f]}function iy(e){return k1(Gt(e).body,1)||e}function C1(e){return k1(Gt(e).body,-1)||e}function T1(e,t){if(!e)return null;const a=sf(Gt(e).body),o=a.length;if(o===0)return null;const c=a.indexOf(e);if(c===-1)return null;const d=(c+t+o)%o;return a[d]}function h4(e){return T1(e,1)}function g4(e){return T1(e,-1)}function Jc(e,t){const a=t||e.currentTarget,o=e.relatedTarget;return!o||!Ze(a,o)}function x4(e){sf(e).forEach(a=>{a.dataset.tabindex=a.getAttribute("tabindex")||"",a.setAttribute("tabindex","-1")})}function E1(e){const t=[];S1(e,"[data-tabindex]",t),t.forEach(a=>{const o=a.dataset.tabindex;delete a.dataset.tabindex,o?a.setAttribute("tabindex",o):a.removeAttribute("tabindex")})}function cy(e){x.useEffect(e,Ir)}const rf=0;class la{constructor(){cn(this,"currentId",rf);cn(this,"clear",()=>{this.currentId!==rf&&(clearTimeout(this.currentId),this.currentId=rf)});cn(this,"disposeEffect",()=>this.clear)}static create(){return new la}start(t,a){this.clear(),this.currentId=setTimeout(()=>{this.currentId=rf,a()},t)}isStarted(){return this.currentId!==rf}}function er(){const e=Ps(la.create).current;return cy(e.disposeEffect),e}function b4(e,t){return e.matches(":disabled")?!1:!t||e.form===t?!0:e.form===null&&!e.hasAttribute("form")}const v4=x.createContext({disabled:!1});function A1(){return x.useContext(v4)}var uy={exports:{}},$s={};var R1;function y4(){if(R1)return $s;R1=1;var e=Xd();function t(y){var v="https://react.dev/errors/"+y;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),uy.exports=y4(),uy.exports}var Ts=M1();const ah=null;class j4{constructor(){cn(this,"callbacks",[]);cn(this,"callbacksCount",0);cn(this,"nextId",1);cn(this,"startId",1);cn(this,"isScheduled",!1);cn(this,"tick",t=>{this.isScheduled=!1;const a=this.callbacks,o=this.callbacksCount;if(this.callbacks=[],this.callbacksCount=0,this.startId=this.nextId,o>0)for(let c=0;c=this.callbacks.length||this.callbacks[a]!==null&&(this.callbacks[a]=null,this.callbacksCount-=1)}}let lh=new j4;class Ga{constructor(){cn(this,"currentId",ah);cn(this,"cancel",()=>{this.currentId!==ah&&(lh.cancel(this.currentId),this.currentId=ah)});cn(this,"disposeEffect",()=>this.cancel)}static create(){return new Ga}static request(t){return lh.request(t)}static cancel(t){return lh.cancel(t)}request(t){this.cancel(),this.currentId=lh.request(()=>{this.currentId=ah,t()})}}function eu(){const e=Ps(Ga.create).current;return cy(e.disposeEffect),e}function kl(e){return e==null?e:"current"in e?e.current:e}let oh=null;function w4(e){if(!oh){const t=[];oh=t,queueMicrotask(()=>{oh=null,Ts.flushSync(()=>{for(const a of t)a()})})}oh.push(e)}function D1(e,t=!1,a=!1){const o=eu();return Ie((c,d=null)=>{o.cancel();const f=kl(e);if(f==null)return;const p=f,h=()=>{if(!a){Ts.flushSync(c);return}w4(()=>{d?.aborted||c()})};if(typeof p.getAnimations!="function"||globalThis.BASE_UI_ANIMATIONS_DISABLED){c();return}function b(){Promise.all(p.getAnimations().map(y=>y.finished)).then(()=>{d?.aborted||h()},()=>{if(d?.aborted)return;if(p.getAnimations().some(v=>v.pending||v.playState!=="finished")){b();return}h()})}if(t){const y=d1;if(!p.hasAttribute(y)){o.request(b);return}const v=new MutationObserver(()=>{p.hasAttribute(y)||(v.disconnect(),b())});v.observe(p,{attributes:!0,attributeFilter:[y]}),d?.addEventListener("abort",()=>v.disconnect(),{once:!0});return}o.request(b)})}function oa(e){const{enabled:t=!0,open:a,ref:o,batch:c=!1,onComplete:d}=e,f=Ie(d),p=D1(o,a,c);x.useEffect(()=>{if(!t)return;const h=new AbortController;return p(f,h.signal),()=>{h.abort()}},[t,a,f,p])}function Oi(e,t=!1,a=!1,o=!1){const[c,d]=x.useState(e&&t?"idle":void 0),[f,p]=x.useState(e&&!o);return e&&!f&&(p(!0),d("starting")),!e&&f&&c!=="ending"&&!a&&d("ending"),!e&&!f&&c==="ending"&&d(void 0),Me(()=>{if(!e&&f&&c!=="ending"&&a){const h=Ga.request(()=>{d("ending")});return()=>{Ga.cancel(h)}}},[e,f,c,a]),Me(()=>{if(!e||t)return;const h=Ga.request(()=>{d(void 0)});return()=>{Ga.cancel(h)}},[t,e]),Me(()=>{if(!e||!t)return;e&&f&&c!=="idle"&&d("starting");const h=Ga.request(()=>{d("idle")});return()=>{Ga.cancel(h)}},[t,e,f,c]),{mounted:f,setMounted:p,transitionStatus:c}}function Ka({controlled:e,default:t,name:a,state:o="value"}){const{current:c}=x.useRef(e!==void 0),[d,f]=x.useState(t),p=c&&e!==void 0?e:d,h=x.useCallback(b=>{c||f(b)},[]);return[p,h]}function tu(e,t,a,o,c=!0,d){const{registerFieldControl:f}=Na(),p=Ps(()=>Symbol());Me(()=>{const h=p.current;if(!c){f(h,void 0);return}f(h,{controlRef:e,getValue:o,id:t,name:d,value:a})},[e,c,o,t,d,f,p,a]),Me(()=>{const h=p.current;return()=>{f(h,void 0)}},[f,p])}function ia(e,t){const a=x.useRef(e),o=Ie(t);Me(()=>{a.current!==e&&o(a.current),a.current=e},[e,o])}const Qn="none",go="trigger-press",qs="trigger-hover",ih="trigger-focus",ch="outside-press",af="item-press",dy="close-press",lf="input-change",Ya="input-clear",S4="input-press",xo="focus-out",nu="escape-key",fy="list-navigation",I1="keyboard",P1="pointer",_1="cancel-open",N4="disabled",py="imperative-action",k4="window-resize";function qe(e,t,a,o){let c=!1,d=!1;const f=o??mn;return{reason:e,event:t??new Event("base-ui"),cancel(){c=!0},allowPropagation(){d=!0},get isCanceled(){return c},get isPropagationAllowed(){return d},trigger:a,...f}}function C4(e,t,a){const o=a??mn;return{reason:e,event:t??new Event("base-ui"),...o}}const T4=x.forwardRef(function(t,a){const{render:o,className:c,id:d,name:f,value:p,disabled:h=!1,onValueChange:b,defaultValue:y,autoFocus:v=!1,style:j,...w}=t,{state:S,name:N,disabled:k,setTouched:A,setDirty:P,validityData:R,setFocused:C,setFilled:E,validationMode:D,validation:I}=Na(),{clearErrors:O,elementRef:_,submitCountRef:z}=Qc(),H=k||h,B=N??f,L={...S,disabled:H},{labelId:F}=yl(),$=io({id:d}),[X]=Ka({controlled:p,default:y,name:"FieldControl",state:"value"}),K=p!==void 0,q=K?X:void 0,Q=q==null?void 0:String(q),G=Ie(()=>I.inputRef.current?.value);tu(I.inputRef,$,Q,G,!H,f),Me(()=>{const M=Q??I.inputRef.current?.value;M!==void 0&&E(M!=="")},[Q,I.inputRef,E]),ia(Q,()=>{Q!==void 0&&(O(B),P(Q!==(R.initialValue??"")),I.change(Q))});const J=x.useRef(null),Y=er();return Me(()=>{v&&J.current===ir(Gt(J.current))&&C(!0)},[v,C]),yt("input",t,{ref:[a,J],state:L,props:[{id:$,disabled:H,name:B,ref:I.inputRef,"aria-labelledby":F,autoFocus:v,...K?{value:q}:{defaultValue:y},onChange(M){const U=M.currentTarget.value,Z=qe(Qn,M.nativeEvent);b?.(U,Z),!K&&(P(U!==(R.initialValue??"")),E(U!==""),!M.nativeEvent.defaultPrevented&&!Z.isCanceled&&(O(B),I.change(U)))},onFocus(){C(!0)},onBlur(M){if(A(!0),C(!1),D==="onBlur"){const U=M.currentTarget.value;I.commit(U),K&&queueMicrotask(()=>{const Z=I.inputRef.current?.value;Z!==void 0&&Z!==U&&Z!==(R.initialValue??"")&&I.commit(Z)})}},onKeyDown(M){if(M.currentTarget.tagName==="INPUT"&&M.key==="Enter"){A(!0);const U=M.currentTarget.value,Z=M.currentTarget.form;if(Z&&Z===_.current&&!M.defaultPrevented){const ae=M.currentTarget,ce=z.current;Y.start(0,()=>{z.current===ce&&I.commit(ae.value)})}else I.commit(U)}}},w,M=>I.getValidationProps(H,M)],stateAttributesMapping:Ti})}),E4=x.forwardRef(function(t,a){return s.jsx(T4,{ref:a,...t})});function Fe({className:e,type:t,ref:a,...o}){return s.jsx(E4,{ref:a,type:t,"data-slot":"input",className:Ue("h-[30px] w-full min-w-0 rounded-md border border-control-border bg-control px-2.5","text-[12.5px] text-foreground outline-none","transition-[border-color,box-shadow] duration-150 ease-out","placeholder:text-muted-foreground","hover:border-control-border-hover","focus:border-primary focus:shadow-focus","disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-surface-3 disabled:text-muted-foreground","file:inline-flex file:border-0 file:bg-transparent file:text-foreground",e),...o})}function Mi({className:e,...t}){return s.jsx("textarea",{"data-slot":"textarea",className:Ue("min-h-26 w-full resize-y rounded-md border border-control-border bg-control px-3 py-2.5","font-mono text-[12px] leading-[1.6] text-foreground outline-none","transition-[border-color,box-shadow] duration-150 ease-out","placeholder:text-muted-foreground","hover:border-control-border-hover","focus:border-primary focus:shadow-focus","disabled:cursor-not-allowed disabled:bg-surface-3 disabled:text-muted-foreground",e),...t})}function Di({className:e,...t}){return s.jsx("div",{"data-slot":"input-group",role:"group",className:Ue("group/input-group relative flex h-[30px] w-full min-w-0 items-center rounded-md border border-control-border bg-control","transition-[border-color,box-shadow] duration-150 ease-out","outline-none","has-[[data-slot=input-group-control]:focus-visible]:border-primary","has-[[data-slot=input-group-control]:focus-visible]:shadow-focus","has-[[data-slot=input-group-control]:hover:not(:focus-visible)]:border-control-border-hover","has-[>textarea]:h-auto","has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:pl-1.5","has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:pr-1.5","has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col","has-[>[data-align=block-start]]:[&>[data-slot=input-group-control]]:pb-1.5","has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col","has-[>[data-align=block-end]]:[&>[data-slot=input-group-control]]:pt-1.5",e),...t})}const A4=Xc(["flex h-auto cursor-text items-center justify-center gap-1.5 select-none","text-[12px] font-medium text-muted-foreground","group-data-[disabled=true]/input-group:opacity-50"],{variants:{align:{"inline-start":"order-first pl-[9px] has-[>button]:-ml-1","inline-end":"order-last pr-[9px] has-[>button]:-mr-1","block-start":"order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-1.5","block-end":"order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-1.5"}},defaultVariants:{align:"inline-start"}});function Ii({className:e,align:t="inline-start",...a}){return s.jsx("div",{role:"group","data-slot":"input-group-addon","data-align":t,className:Ue(A4({align:t}),e),onClick:o=>{o.target.closest("button")||o.currentTarget.parentElement?.querySelector("input")?.focus()},...a})}const R4=Xc("flex items-center shadow-none",{variants:{size:{xs:"h-6 gap-1 rounded-xs px-1.5",sm:"h-8 gap-1.5 rounded-sm px-2.5","icon-xs":"size-6 rounded-xs p-0","icon-sm":"size-8 rounded-sm p-0"}},defaultVariants:{size:"xs"}});function O4({className:e,type:t="button",variant:a="ghost",size:o="xs",...c}){return s.jsx(ne,{type:t,"data-size":o,variant:a,className:Ue(R4({size:o}),e),...c})}function Pi({className:e,...t}){return s.jsx(Fe,{"data-slot":"input-group-control",className:Ue("flex-1 rounded-none border-0 bg-transparent shadow-none focus:border-0 focus:shadow-none",e),...t})}function M4(e){return yt(e.defaultTagName??"div",e,e)}const D4=Xc("inline-flex w-fit shrink-0 items-center justify-center gap-[5px] overflow-hidden whitespace-nowrap border font-semibold",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground",secondary:"border-transparent bg-secondary text-secondary-foreground",destructive:"border-destructive-bd bg-destructive-soft text-destructive",outline:"border-control-border bg-control text-subtle",ghost:"border-transparent bg-transparent text-muted-foreground",link:"border-transparent bg-transparent text-primary underline-offset-4 hover:underline",success:"border-success-bd bg-success-soft text-success",warning:"border-warning-bd bg-warning-soft text-warning",info:"border-info-bd bg-info-soft text-info",brand:"border-primary-bd bg-primary-soft text-primary-fg",cn:"border-cn-bd bg-cn-soft text-cn",intl:"border-intl-bd bg-intl-soft text-intl",sensitive:"border-sensitive-bd bg-sensitive-soft text-sensitive"},shape:{pill:"min-h-[21px] rounded-pill px-[9px] py-px text-[11.5px]",tag:"min-h-[19px] rounded-xs px-2 py-0 text-[11px]"}},defaultVariants:{variant:"default",shape:"pill"}});function ze({className:e,variant:t,shape:a,render:o,...c}){return M4({render:o,defaultTagName:"span",props:ta({"data-slot":"badge"},c,{className:Ue(D4({variant:t,shape:a}),e)})})}function my({className:e,...t}){return s.jsx("span",{className:Ue("size-1.5 flex-none rounded-full bg-current",e),...t})}function bo(e,t){if(typeof window>"u")return e;const a=window.wbI18n;return a?a.t(e,t)??e:e}function of({className:e,...t}){return s.jsx("svg",{"data-slot":"spinner",role:"status","aria-label":bo("加载中"),viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",className:Ue("size-4 animate-spin [animation-duration:0.7s]",e),...t,children:s.jsx("path",{d:"M21 12a9 9 0 1 1-6.219-8.56"})})}function Je({className:e,...t}){return s.jsx("label",{"data-slot":"label",className:Ue("flex items-center gap-[6px] text-[11.5px] text-muted-foreground",e),...t})}const L1={clipPath:"inset(50%)",overflow:"hidden",whiteSpace:"nowrap",border:0,padding:0,width:1,height:1,margin:-1},_i={...L1,position:"fixed",top:0,left:0},su={...L1,position:"absolute"},z1=x.createContext(void 0);function I4(){const e=x.useContext(z1);if(e===void 0)throw new Error(un(63));return e}const P4="data-checked",_4="data-unchecked",B1={...Ti,checked(e){return e?{[P4]:""}:{[_4]:""}}},L4=x.forwardRef(function(t,a){const{checked:o,className:c,defaultChecked:d,"aria-labelledby":f,form:p,id:h,inputRef:b,name:y,nativeButton:v=!1,onCheckedChange:j,readOnly:w=!1,required:S=!1,disabled:N=!1,render:k,uncheckedValue:A,value:P,style:R,...C}=t,{clearErrors:E}=Qc(),{state:D,setTouched:I,setDirty:O,validityData:_,setFilled:z,setFocused:H,validationMode:B,disabled:L,name:F,validation:$}=Na(),{labelId:X}=yl(),K=L||N,q=F??y,Q=x.useRef(null),G=sa(Q,b,$.inputRef),J=x.useRef(null),Y=ka(),re=io({id:h}),M=v?void 0:re,[U,Z]=Ka({controlled:o,default:!!d,name:"Switch",state:"checked"});tu(J,Y,U,void 0,!K,y),Me(()=>{z(U)},[U,z]),ia(U,()=>{E(q),O(U!==_.initialValue),$.change(U)});const{getButtonProps:ae,buttonRef:ce}=na({disabled:K,native:v}),W=Fv(f,X,Q,!v,M),ue={id:v?re:Y,role:"switch","aria-checked":U,"aria-readonly":w||void 0,"aria-required":S||void 0,"aria-labelledby":W,onFocus(){K||H(!0)},onBlur(){const te=Q.current;!te||K||(I(!0),H(!1),B==="onBlur"&&$.commit(te.checked))},onClick(te){if(w||K)return;te.preventDefault();const ke=Q.current;ke&&Yc(ke,te)}},ve={...$.getValidationProps(K),checked:U,disabled:K,form:p,id:M,name:q,required:S,style:q?su:_i,tabIndex:-1,type:"checkbox","aria-hidden":!0,ref:G,onChange(te){if(te.nativeEvent.defaultPrevented)return;if(w){te.preventDefault();return}const ke=te.currentTarget.checked,le=qe(Qn,te.nativeEvent);j?.(ke,le),!le.isCanceled&&Z(ke)},onClick(te){te.stopPropagation()},onFocus(){J.current?.focus()},...P!==void 0?{value:P}:mn},ee=x.useMemo(()=>({...D,checked:U,disabled:K,readOnly:w,required:S}),[D,U,K,w,S]),he=yt("span",t,{state:ee,ref:[a,J,ce],props:[ue,C,ae,te=>$.getValidationProps(K,te)],stateAttributesMapping:B1});return s.jsxs(z1.Provider,{value:ee,children:[he,!U&&q&&A!==void 0&&s.jsx("input",{type:"hidden",form:p,name:q,value:A,disabled:K}),s.jsx("input",{...ve,suppressHydrationWarning:!0})]})}),z4=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,p=I4();return yt("span",t,{state:p,ref:a,stateAttributesMapping:B1,props:f})});function ns({className:e,size:t="default",...a}){const o=t==="sm";return s.jsx(L4,{"data-slot":"switch",className:Ue("relative inline-flex flex-none cursor-pointer items-center rounded-pill border-0 bg-border-strong p-0","transition-colors duration-[180ms] ease-out","data-checked:bg-primary","focus-visible:shadow-focus focus-visible:outline-none","data-disabled:cursor-not-allowed data-disabled:opacity-50",o?"h-[14px] w-6":"h-[21px] w-9",e),...a,children:s.jsx(z4,{"data-slot":"switch-thumb",className:Ue("block rounded-full bg-primary-on shadow-1","transition-transform duration-[180ms] [transition-timing-function:cubic-bezier(.3,1.4,.6,1)]",o?"size-[10px] translate-x-0.5 data-checked:translate-x-[10px]":"size-[17px] translate-x-0.5 data-checked:translate-x-[15px]")})})}function B4(e){if(!e)return null;for(const t of e.elements){const a=t.tagName;if(a==="BUTTON"||a==="INPUT"){const o=t;if(o.type==="submit")return o}}return null}const H4="data-checked",U4="data-unchecked";function H1(e){return{checked(t){return e.indeterminate?{}:t?{[H4]:""}:{[U4]:""}},...Ti}}const V4=x.createContext(void 0);function F4(){return x.useContext(V4)}const U1=x.createContext(void 0);function $4(){const e=x.useContext(U1);if(e===void 0)throw new Error(un(14));return e}const q4="data-parent",G4=x.forwardRef(function(t,a){const{checked:o,className:c,defaultChecked:d=!1,"aria-labelledby":f,disabled:p=!1,form:h,id:b,indeterminate:y=!1,inputRef:v,name:j,onCheckedChange:w,parent:S=!1,readOnly:N=!1,render:k,required:A=!1,uncheckedValue:P,value:R,nativeButton:C=!1,style:E,...D}=t,{clearErrors:I}=Qc(),{disabled:O,name:_,setDirty:z,setFilled:H,setFocused:B,setTouched:L,state:F,validationMode:$,validityData:X,validation:K}=Na(),q=A1(),{labelId:Q,registerControlId:G,getDescriptionProps:J}=yl(),Y=F4(),re=Y?.allValues===void 0?void 0:Y.parent,M=re!==void 0,U=O||q.disabled||Y?.disabled||p,Z=_??j,ae=R??Z,ce=ka(),W=Y?.registerControlId!==G,ue=io({id:b||void 0,enabled:W}),ve=C?ue:ce;let ee={};M&&(S?ee=re.getParentProps():ae!==void 0&&(ee=re.getChildProps(ae)));const{checked:he=o,indeterminate:te=y,onCheckedChange:ke,...le}=ee,de=Y?.value,Se=x.useRef(null),{getButtonProps:Te,buttonRef:_e}=na({disabled:U,native:C}),Ae=Y?.validation??K,[oe,me]=Ka({controlled:ae!==void 0&&de!==void 0&&!S?de.includes(ae):he,default:d,name:"Checkbox",state:"checked"}),pe=M?!!he:oe,Ce=M&&te||y;tu(Se,ce,oe,void 0,!Y&&!U,j);const Ne=re?.registerChildId,be=x.useRef(null),De=Ae.registerInput,Ge=Y?ae:void 0,Ct=x.useCallback(it=>De(it,{controlRef:Se,value:Ge}),[De,Ge]),Tt=sa(v,be,S?void 0:Ct),Mt=Fv(f,Q,be,!C,ue);Me(()=>{be.current&&(be.current.indeterminate=Ce),Y||H(oe)},[oe,Ce,Y,H]),ia(oe,()=>{Y||(I(Z),z(oe!==X.initialValue),Ae.change(oe))});const ot=ta({checked:oe,disabled:U,form:h,name:S?void 0:Z,id:C?void 0:ue,required:A,ref:Tt,style:Z?su:_i,tabIndex:-1,type:"checkbox","aria-hidden":!0,onChange(it){if(it.nativeEvent.defaultPrevented)return;if(N){it.preventDefault();return}const $t=it.currentTarget.checked,Vn=qe(Qn,it.nativeEvent);if(w?.($t,Vn),!Vn.isCanceled&&(ke?.($t,Vn),!Vn.isCanceled&&(me($t),ae!==void 0&&Y!==void 0&&!S&&!M))){const rn=$t?[...Y.value,ae]:Y.value.filter(nt=>nt!==ae);Y.setValue(rn,Vn)}},onClick(it){it.stopPropagation()},onFocus(){Se.current?.focus()}},R!==void 0?{value:(Y?oe&&R:R)||""}:mn,J,it=>Ae.getValidationProps(U,it));x.useEffect(()=>{if(!re||ae===void 0)return;const it=re.disabledStatesRef.current;return it.set(ae,U),()=>{it.delete(ae)}},[re,U,ae]);const Kn=x.useMemo(()=>({...F,checked:pe,disabled:U,readOnly:N,required:A,indeterminate:Ce}),[F,pe,U,N,A,Ce]),ms=H1(Kn),Yn=yt("span",t,{state:Kn,ref:[_e,Se,a],props:[{id:ve,role:"checkbox","aria-checked":Ce?"mixed":pe,"aria-readonly":N||void 0,"aria-required":A||void 0,"aria-labelledby":Mt,[q4]:S?"":void 0,onFocus(){U||B(!0)},onBlur(){const it=be.current;it&&(L(!0),B(!1),$==="onBlur"&&Ae.commit(Y?de:it.checked))},onKeyDown(it){if(it.key!=="Enter"||(it.preventBaseUIHandler(),it.defaultPrevented))return;const $t=be.current?.form??null,Vn=it.currentTarget,rn=it.nativeEvent,nt=it.preventDefault,Dt=rn.preventDefault;let qt=!1;it.preventDefault=()=>{qt=!0,nt.call(it)},rn.preventDefault=()=>{qt=!0,Dt.call(rn)},Dt.call(rn),Cn(Vn).queueMicrotask(()=>{it.preventDefault=nt,rn.preventDefault=Dt,qt||B4($t)?.click()})},onClick(it){if(N||U)return;it.preventDefault();const $t=be.current;$t&&Yc($t,it)}},D,le,Te,J,it=>Ae.getValidationProps(U,it)],stateAttributesMapping:ms}),vs=Yn.props.id;return Me(()=>{if(!(!Ne||S||ae===void 0||vs===void 0))return Ne(ae,vs)},[Ne,S,ae,vs]),s.jsxs(U1.Provider,{value:Kn,children:[Yn,!oe&&!Y&&Z&&!S&&P!==void 0&&s.jsx("input",{type:"hidden",form:h,name:Z,value:P,disabled:U}),s.jsx("input",{...ot,suppressHydrationWarning:!0})]})}),K4=x.forwardRef(function(t,a){const{render:o,className:c,style:d,keepMounted:f=!1,...p}=t,h=$4(),b=h.checked||h.indeterminate,{mounted:y,transitionStatus:v,setMounted:j}=Oi(b),w=x.useRef(null),S={...h,transitionStatus:v};oa({batch:!0,enabled:!b,open:b,ref:w,onComplete(){b||j(!1)}});const k={...H1(h),...co},A=f||y,P=yt("span",t,{ref:[a,w],state:S,stateAttributesMapping:k,props:p});return A?P:null});function Pr({className:e,...t}){return s.jsx(G4,{"data-slot":"checkbox",className:Ue("group/checkbox relative inline-flex size-3.5 shrink-0 cursor-pointer items-center justify-center rounded-[3px] border border-control-border bg-control","outline-none transition-colors duration-150 ease-out","hover:border-control-border-hover","data-checked:border-primary data-checked:bg-primary","focus-visible:shadow-focus","data-disabled:cursor-not-allowed data-disabled:opacity-45",e),...t,children:s.jsx(K4,{"data-slot":"checkbox-indicator",className:"grid place-content-center text-primary-foreground data-unchecked:hidden",children:s.jsxs("svg",{viewBox:"0 0 12 12",className:"size-2.5","aria-hidden":"true",children:[s.jsx("path",{d:"M2 6h8",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",fill:"none",className:"hidden group-aria-[checked=indeterminate]/checkbox:block"}),s.jsx("path",{d:"M2.5 6.2 4.8 8.5 9.5 3.8",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",fill:"none",className:"group-aria-[checked=indeterminate]/checkbox:hidden"})]})})})}function hy(e){return Array.isArray(e)?e.map(t=>hy(t)).join(","):e==null?"":String(e)}const V1=new Map;function Y4(e,t){const a=JSON.stringify({locale:hy(e),options:t}),o=V1.get(a);if(o)return o;const c=new Intl.NumberFormat(e,t);return V1.set(a,c),c}function F1(e,t,a){return e==null?"":Y4(t,a).format(e)}function Li(e,t=Number.MIN_SAFE_INTEGER,a=Number.MAX_SAFE_INTEGER){return Math.max(t,Math.min(e,a))}function X4(e,t,a){return(e-t)*100/(a-t)}const $1=x.createContext(void 0);function q1(){const e=x.useContext($1);if(e===void 0)throw new Error(un(51));return e}const Q4="data-complete",Z4="data-indeterminate",W4="data-progressing",gy={status(e){return e==="progressing"?{[W4]:""}:e==="complete"?{[Q4]:""}:e==="indeterminate"?{[Z4]:""}:null}},J4=x.forwardRef(function(t,a){const{format:o,getAriaValueText:c,locale:d,max:f=100,min:p=0,value:h,render:b,className:y,children:v,style:j,...w}=t,[S,N]=x.useState();let k="indeterminate",A=null,P=null,R="",C="indeterminate progress";if(h!=null&&Number.isFinite(h)){const _=X4(h,p,f);A=Li(Number.isNaN(_)?0:_,0,100),P=Li(h,p,f),k=P===f?"complete":"progressing",R=o?F1(P,d,o):F1(A/100,d,{style:"percent"}),C=R}const E=x.useMemo(()=>({status:k}),[k]),D={"aria-labelledby":S,"aria-valuemax":f,"aria-valuemin":p,"aria-valuenow":P??void 0,"aria-valuetext":c?c(R,h):C,role:"progressbar",children:s.jsxs(x.Fragment,{children:[v,s.jsx("span",{role:"presentation",style:_i,children:"x"})]})},I=x.useMemo(()=>({formattedValue:R,percentageValue:A,setLabelId:N,state:E,value:h}),[R,A,N,E,h]),O=yt("div",t,{state:E,ref:a,props:[D,w],stateAttributesMapping:gy});return s.jsx($1.Provider,{value:I,children:O})}),eH=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,{state:p}=q1();return yt("div",t,{state:p,ref:a,props:f,stateAttributesMapping:gy})}),tH=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,{percentageValue:p,state:h}=q1(),b=p==null?{}:{insetInlineStart:0,height:"inherit",width:`${p}%`};return yt("div",t,{state:h,ref:a,props:[{style:b},f],stateAttributesMapping:gy})});function cf({className:e,children:t,value:a,...o}){return s.jsxs(J4,{value:a,"data-slot":"progress",className:Ue("flex w-full flex-wrap items-center gap-3",e),...o,children:[t,s.jsx(nH,{children:s.jsx(sH,{})})]})}function nH({className:e,...t}){return s.jsx(eH,{"data-slot":"progress-track",className:Ue("relative flex h-1.5 w-full items-center overflow-x-hidden overflow-y-hidden rounded-pill bg-surface-3",e),...t})}function sH({className:e,...t}){return s.jsx(tH,{"data-slot":"progress-indicator",className:Ue("h-full rounded-[inherit] bg-primary transition-[width] duration-300 ease-out",e),...t})}const xy=[];let by;function rH(){return by}function aH(e){xy.push(e)}function uh(e){const t=(a,o)=>{const c=Ps(lH).current;let d;try{by=c;for(const f of xy)f.before(c);d=e(a,o);for(const f of xy)f.after(c);c.didInitialize=!0}finally{by=void 0}return d};return t.displayName=e.displayName||e.name,t}function G1(e){return x.forwardRef(uh(e))}function lH(){return{didInitialize:!1}}const K1=x.createContext(void 0);function uf(e){const t=x.useContext(K1);if(t===void 0&&!e)throw new Error(un(72));return t}function oH(e,t){return t!=null&&!fo(t)?0:typeof e=="function"?e():e}function zi(e,t,a){const o=oH(e,a);return typeof o=="number"?o:o?.[t]}function Y1(e){return typeof e=="function"?e():e}function X1(e,t){return t||e==="click"||e==="mousedown"}function iH(e){return e?.includes("mouse")&&e!=="mousedown"}const Q1=x.createContext({hasProvider:!1,timeoutMs:0,delayRef:{current:0},initialDelayRef:{current:0},timeout:new la,currentIdRef:{current:null},currentContextRef:{current:null}});function cH(e,t){e.current=t.current}function uH(e){const{children:t,delay:a,timeoutMs:o=0}=e,c=x.useRef(a),d=x.useRef(a),f=x.useRef(null),p=x.useRef(null),h=er();return Me(()=>{if(d.current=a,!f.current){c.current=a;return}c.current={open:zi(c.current,"open"),close:zi(a,"close")}},[a,f,c,d]),s.jsx(Q1.Provider,{value:x.useMemo(()=>({hasProvider:!0,delayRef:c,initialDelayRef:d,currentIdRef:f,timeoutMs:o,currentContextRef:p,timeout:h}),[o,h]),children:t})}function dH(e,t={open:!1}){const{open:a}=t,o="rootStore"in e?e.rootStore:e,c=o.useState("floatingId"),d=x.useContext(Q1),{currentIdRef:f,delayRef:p,timeoutMs:h,initialDelayRef:b,currentContextRef:y,hasProvider:v,timeout:j}=d,[w,S]=x.useState(!1),N=x.useRef(a);return Me(()=>{N.current=a},[a]),Me(()=>{function k(){y.current?.setIsInstantPhase(!1),f.current=null,y.current=null,p.current=b.current,j.clear()}if(f.current&&!a&&f.current===c){if(S(!1),h){const A=c;return j.start(h,()=>{o.select("open")||f.current&&f.current!==A||k()}),()=>{(N.current||f.current!==A)&&j.clear()}}k()}},[a,c,f,p,h,b,y,j,o]),Me(()=>{if(!a)return;const k=y.current,A=f.current;j.clear(),y.current={onOpenChange:o.setOpen,setIsInstantPhase:S},f.current=c,p.current={open:0,close:zi(b.current,"close")},A!==null&&A!==c?(S(!0),k?.setIsInstantPhase(!0),k?.onOpenChange(!1,qe(Qn))):(S(!1),k?.setIsInstantPhase(!1))},[a,c,o,f,p,b,y,j]),Me(()=>()=>{if(f.current===c){if(y.current=null,!N.current)return;f.current=null,cH(p,b),j.clear()}},[y,f,p,c,b,j]),x.useMemo(()=>({activeIdRef:f,hasProvider:v,delayRef:p,isInstantPhase:w}),[f,v,p,w])}function St(e,t,a,o){return e.addEventListener(t,a,o),()=>{e.removeEventListener(t,a,o)}}function Xa(...e){return()=>{for(let t=0;t{t.current=t.next}};return t}const ru=x.forwardRef(function(t,a){const[o,c]=x.useState();Me(()=>{_B&&jl&&c("button")},[]);const d={tabIndex:0,role:o};return s.jsx("span",{...t,ref:a,style:_i,"aria-hidden":o?void 0:!0,...d,"data-base-ui-focus-guard":""})});function df(e){return`data-base-ui-${e}`}let dh=0;function fh(e,t={}){const{preventScroll:a=!1,sync:o=!1,shouldFocus:c}=t;cancelAnimationFrame(dh);function d(){c&&!c()||e?.focus({preventScroll:a})}if(o)return d(),Kt;const f=requestAnimationFrame(d);return dh=f,()=>{dh===f&&(cancelAnimationFrame(f),dh=0)}}const vy={inert:new WeakMap,"aria-hidden":new WeakMap},Z1="data-base-ui-inert",yy={inert:new WeakSet,"aria-hidden":new WeakSet};let ff=new WeakMap,jy=0;function pH(e){return yy[e]}function W1(e){return e?Gc(e)?e.host:W1(e.parentNode):null}const J1=(e,t)=>t.map(a=>{if(e.contains(a))return a;const o=W1(a);return e.contains(o)?o:null}).filter(a=>a!=null),eT=e=>{const t=new Set;return e.forEach(a=>{let o=a;for(;o&&!t.has(o);)t.add(o),o=o.parentNode}),t},tT=(e,t,a)=>{const o=[],c=d=>{!d||a.has(d)||Array.from(d.children).forEach(f=>{Fs(f)!=="script"&&(t.has(f)?c(f):o.push(f))})};return c(e),o};function mH(e,t,a,o,{mark:c=!0}){let d=null;o?d="inert":a&&(d="aria-hidden");let f=null,p=null;const h=J1(t,e),b=c?tT(t,eT(h),new Set(h)):[],y=[],v=[];if(d){const j=vy[d],w=pH(d);p=w,f=j;const S=J1(t,Array.from(t.querySelectorAll("[aria-live]"))),N=h.concat(S);tT(t,eT(N),new Set(N)).forEach(A=>{const P=A.getAttribute(d),R=P!==null&&P!=="false",C=(j.get(A)||0)+1;j.set(A,C),y.push(A),C===1&&R&&w.add(A),R||A.setAttribute(d,d==="inert"?"":"true")})}return c&&b.forEach(j=>{const w=(ff.get(j)||0)+1;ff.set(j,w),v.push(j),w===1&&j.setAttribute(Z1,"")}),jy+=1,()=>{f&&y.forEach(j=>{const S=(f.get(j)||0)-1;f.set(j,S),S||(!p?.has(j)&&d&&j.removeAttribute(d),p?.delete(j))}),c&&v.forEach(j=>{const w=(ff.get(j)||0)-1;ff.set(j,w),w||j.removeAttribute(Z1)}),jy-=1,jy||(vy.inert=new WeakMap,vy["aria-hidden"]=new WeakMap,yy.inert=new WeakSet,yy["aria-hidden"]=new WeakSet,ff=new WeakMap)}}function nT(e,t={}){const{ariaHidden:a=!1,inert:o=!1,mark:c=!0}=t,d=Gt(e[0]).body;return mH(e,d,a,o,{mark:c})}const hH=500,gH={style:{transition:"none"}},sT="data-base-ui-click-trigger",rT={fallbackAxisSide:"none"},aT={fallbackAxisSide:"end"},xH={clipPath:"inset(50%)",position:"fixed",top:0,left:0},lT=x.createContext(null),oT=()=>x.useContext(lT),bH=df("portal");function iT(e={}){const{ref:t,container:a,componentProps:o=mn,elementProps:c}=e,d=Jd(),p=oT()?.portalNode,[h,b]=x.useState(null),[y,v]=x.useState(null),j=Ie(k=>{k!==null&&v(k)}),w=x.useRef(null);Me(()=>{if(a===null){w.current&&(w.current=null,v(null),b(null));return}const k=(a&&(Tv(a)?a:a.current))??p??document.body;if(k==null){w.current&&(w.current=null,v(null),b(null));return}w.current!==k&&(w.current=k,v(null),b(k))},[a,p]);const S=yt("div",o,{ref:[t,j],props:[{id:d,[bH]:""},c]}),N=h&&S?Ts.createPortal(S,h):null;return{node:y,nodeId:x.isValidElement(S)?S.props.id:void 0,subtree:N}}const ph=x.forwardRef(function(t,a){const{render:o,className:c,style:d,children:f,container:p,portalOwnerRole:h,...b}=t,{node:y,nodeId:v,subtree:j}=iT({container:p,ref:a,componentProps:t,elementProps:b}),w=x.useRef(null),S=x.useRef(null),N=x.useRef(null),k=x.useRef(null),[A,P]=x.useState(null),R=x.useRef(!1),C=A?.modal,E=A?.open,D=!!A&&!A.modal&&A.open&&!!y;x.useEffect(()=>{if(!y||C)return;function O(_){y&&_.relatedTarget&&Jc(_)&&(_.type==="focusin"?R.current&&(E1(y),R.current=!1):(x4(y),R.current=!0))}return Xa(St(y,"focusin",O,!0),St(y,"focusout",O,!0))},[y,C]),Me(()=>{!y||E!==!0||!R.current||(E1(y),R.current=!1)},[E,y]);const I=x.useMemo(()=>({beforeOutsideRef:w,afterOutsideRef:S,beforeInsideRef:N,afterInsideRef:k,portalNode:y,setFocusManagerState:P}),[y]);return s.jsxs(x.Fragment,{children:[j,s.jsxs(lT.Provider,{value:I,children:[D&&y&&s.jsx(ru,{"data-type":"outside",ref:w,onFocus:O=>{if(Jc(O,y))N.current?.focus();else{const _=A?A.domReference:null;C1(_)?.focus()}}}),D&&y&&s.jsx("span",{role:h,"aria-owns":v,style:xH}),y&&Ts.createPortal(f,y),D&&y&&s.jsx(ru,{"data-type":"outside",ref:S,onFocus:O=>{if(Jc(O,y))k.current?.focus();else{const _=A?A.domReference:null;iy(_)?.focus(),A?.closeOnFocusOut&&A?.onOpenChange(!1,qe(xo,O.nativeEvent))}}})]})]})});function cT(){const e=new Map;return{emit(t,a){e.get(t)?.forEach(o=>o(a))},on(t,a){e.has(t)||e.set(t,new Set),e.get(t).add(a)},off(t,a){e.get(t)?.delete(a)}}}class vH{constructor(){cn(this,"nodesRef",{current:[]});cn(this,"events",cT())}addNode(t){this.nodesRef.current.push(t)}removeNode(t){const a=this.nodesRef.current.findIndex(o=>o===t);a!==-1&&this.nodesRef.current.splice(a,1)}}const uT=x.createContext(null),dT=x.createContext(null),au=()=>x.useContext(uT)?.id||null,Bi=e=>{const t=x.useContext(dT);return e??t};function yH(e){const t=Jd(),a=Bi(e),o=au();return Me(()=>{if(!t)return;const c={id:t,parentId:o};return a?.addNode(c),()=>{a?.removeNode(c)}},[a,t,o]),t}function jH(e){const{children:t,id:a}=e,o=au();return s.jsx(uT.Provider,{value:x.useMemo(()=>({id:a,parentId:o}),[a,o]),children:t})}function wH(e){const{children:t,externalTree:a}=e,o=Ps(()=>a??new vH).current;return s.jsx(dT.Provider,{value:o,children:t})}function SH(e,t){const a=Cn(fs(e));return e instanceof a.KeyboardEvent?"keyboard":e instanceof a.FocusEvent?t||"keyboard":"pointerType"in e?e.pointerType||"keyboard":"touches"in e?"touch":e instanceof a.MouseEvent?t||(e.detail===0?"keyboard":"mouse"):""}const fT=20;let vo=[];function wy(){vo=vo.filter(e=>e.deref()?.isConnected)}function pT(e){wy(),e&&Fs(e)!=="body"&&(vo.push(new WeakRef(e)),vo.length>fT&&(vo=vo.slice(-fT)))}function mT(){return wy(),vo[vo.length-1]?.deref()}function NH(e){return e?oy(e)?e:sf(e)[0]||e:null}function hT(e){if(e.hasAttribute("tabindex")&&!e.hasAttribute("data-tabindex")||!e.getAttribute("role")?.includes("dialog"))return;const a=N1(e).filter(c=>{const d=c.getAttribute("data-tabindex")||"";return oy(c)||c.hasAttribute("data-tabindex")&&!d.startsWith("-")}),o=e.getAttribute("tabindex");a.length===0?o!=="0"&&(e.setAttribute("tabindex","0"),e.setAttribute("data-tabindex","0")):(o!=="-1"||e.hasAttribute("data-tabindex")&&e.getAttribute("data-tabindex")!=="-1")&&(e.setAttribute("tabindex","-1"),e.setAttribute("data-tabindex","-1"))}function mh(e){const{context:t,children:a,disabled:o=!1,initialFocus:c=!0,returnFocus:d=!0,restoreFocus:f=!1,modal:p=!0,closeOnFocusOut:h=!0,openInteractionType:b="",nextFocusableElement:y,previousFocusableElement:v,beforeContentFocusGuardRef:j,externalTree:w,getInsideElements:S}=e,N="rootStore"in t?t.rootStore:t,k=N.useState("open"),A=N.useState("domReferenceElement"),P=N.useState("floatingElement"),{events:R,dataRef:C}=N.context,E=Ie(()=>C.current.floatingContext?.nodeId),D=c===!1,I=Wv(A)&&D,O=Zn(c),_=Zn(d),z=Zn(b),H=Zn(k),B=Bi(w),L=oT(),F=x.useRef(!1),$=x.useRef(!1),X=x.useRef(!1),K=x.useRef(null),q=x.useRef(""),Q=x.useRef(""),G=x.useRef(null),J=x.useRef(null),Y=sa(G,j,L?.beforeInsideRef),re=sa(J,L?.afterInsideRef),M=er(),U=er(),Z=eu(),ae=L!=null,ce=Wm(P),W=Ie((ee=ce)=>ee?sf(ee):[]),ue=Ie(()=>S?.().filter(ee=>ee!=null)??[]);x.useEffect(()=>{if(o||!p)return;function ee(te){te.key==="Tab"&&Ze(ce,ir(Gt(ce)))&&W().length===0&&!I&&Cs(te)}const he=Gt(ce);return St(he,"keydown",ee)},[o,ce,p,I,W]),x.useEffect(()=>{if(o||!k)return;const ee=Gt(ce);function he(){X.current=!1}function te(le){const de=fs(le),Se=ue(),Te=Ze(P,de)||Ze(A,de)||Ze(L?.portalNode,de)||Se.some(_e=>_e===de||Ze(_e,de));X.current=!Te,Q.current=le.pointerType||"keyboard",de?.closest(`[${sT}]`)&&($.current=!0,U.start(0,()=>{$.current=!1}))}function ke(){Q.current="keyboard"}return Xa(St(ee,"pointerdown",te,!0),St(ee,"pointerup",he,!0),St(ee,"pointercancel",he,!0),St(ee,"keydown",ke,!0),he)},[o,P,A,ce,k,L,U,ue]),x.useEffect(()=>{if(o||!h)return;const ee=Gt(ce);function he(){$.current=!0,U.start(0,()=>{$.current=!1})}function te(Se){const Te=fs(Se);oy(Te)&&(K.current=Te)}function ke(Se){const Te=Se.relatedTarget,_e=Se.currentTarget,Ae=fs(Se);p&&Te==null&&Ae!=null&&Ze(P,Ae)&&pT(Ae),queueMicrotask(()=>{const oe=E(),me=N.context.triggerElements,pe=ue(),Ce=Te?.hasAttribute(df("focus-guard"))&&[G.current,J.current,L?.beforeInsideRef.current,L?.afterInsideRef.current,L?.beforeOutsideRef.current,L?.afterOutsideRef.current,kl(v),kl(y)].includes(Te),Ne=!(Ze(A,Te)||Ze(P,Te)||Ze(Te,P)||Ze(L?.portalNode,Te)||pe.some(be=>be===Te||Ze(be,Te))||me.hasMatchingElement(be=>Ze(be,Te))||Ce||B&&(uo(B.nodesRef.current,oe).find(be=>Ze(be.context?.elements.floating,Te)||Ze(be.context?.elements.domReference,Te))||p1(B.nodesRef.current,oe).find(be=>[be.context?.elements.floating,Wm(be.context?.elements.floating)].includes(Te)||be.context?.elements.domReference===Te)));if(_e===A&&ce&&hT(ce),f&&_e!==A&&!rh(Ae)&&ir(ee)===ee.body){if(pn(ce)&&(ce.focus(),f==="popup")){Z.request(()=>{ce.focus()});return}const be=W(),De=K.current,Ge=(De&&be.includes(De)?De:null)||be[be.length-1]||ce;pn(Ge)&&Ge.focus()}if(C.current.insideReactTree){C.current.insideReactTree=!1;return}(I||!p)&&Te&&Ne&&!$.current&&(I||Te!==mT())&&(F.current=!0,N.setOpen(!1,qe(xo,Se)))})}function le(){X.current||(C.current.insideReactTree=!0,M.start(0,()=>{C.current.insideReactTree=!1}))}const de=pn(A)?A:null;if(!(!P&&!de))return Xa(de&&St(de,"focusout",ke),de&&St(de,"pointerdown",he),P&&St(P,"focusin",te),P&&St(P,"focusout",ke),P&&L&&St(P,"focusout",le,!0))},[o,A,P,ce,p,B,L,N,h,f,W,I,E,C,M,U,Z,y,v,ue]),x.useEffect(()=>{if(o||!P||!k)return;const ee=Array.from(L?.portalNode?.querySelectorAll(`[${df("portal")}]`)||[]),te=(B?p1(B.nodesRef.current,E()):[]).find(_e=>Wv(_e.context?.elements.domReference||null))?.context?.elements.domReference,le=[...[P,...ee,G.current,J.current,L?.beforeOutsideRef.current,L?.afterOutsideRef.current,...ue()],te,kl(v),kl(y),I?A:null].filter(_e=>_e!=null),de=nT(le,{ariaHidden:p||I,mark:!1}),Se=[P,...ee].filter(_e=>_e!=null),Te=nT(Se);return()=>{Te(),de()}},[k,o,A,P,p,L,I,B,E,y,v,ue]),Me(()=>{if(!k||o||!pn(ce))return;q.current="",Q.current="";const ee=Gt(ce),he=ir(ee);queueMicrotask(()=>{const te=O.current,ke=typeof te=="function"?te(z.current||""):te;if(ke===void 0||ke===!1||Ze(ce,he))return;let de=null;const Se=()=>(de==null&&(de=W(ce)),de[0]||ce);let Te;ke===!0||ke===null?Te=Se():Te=kl(ke),Te=Te||Se();const _e=Ze(ce,ir(ee));fh(Te,{preventScroll:Te===ce,shouldFocus(){if(!H.current)return!1;if(_e)return!0;const Ae=ir(ee);return!(Ae!==Te&&Ze(ce,Ae))}})})},[o,k,ce,W,O,z,H]),Me(()=>{if(o||!ce)return;const ee=Gt(ce),he=ir(ee),te=z.current==null;pT(he);function ke(de){if(de.open||(q.current=SH(de.nativeEvent,Q.current)),de.reason===qs&&de.nativeEvent.type==="mouseleave"&&(F.current=!0),de.reason===ch)if(de.nested)F.current=!1;else if(Jm(de.nativeEvent)||Jv(de.nativeEvent))F.current=!1;else{let Se=!1;Gt(ce).createElement("div").focus({get preventScroll(){return Se=!0,!1}}),Se?F.current=!1:F.current=!0}}R.on("openchange",ke);function le(de){const Se=_.current;let Te=typeof Se=="function"?Se(de):Se;if(Te===void 0||Te===!1)return null;Te===null&&(Te=!0);const _e=A?.isConnected?A:null,Ae=he?.isConnected&&Fs(he)!=="body"?he:null;let oe=te?Ae||_e:_e||Ae;return oe||(oe=mT()||null),typeof Te=="boolean"?oe:kl(Te)||oe||null}return()=>{R.off("openchange",ke);const de=ir(ee),Se=ue(),Te=Ze(P,de)||Se.some(me=>me===de||Ze(me,de))||B&&uo(B.nodesRef.current,E(),!1).some(me=>Ze(me.context?.elements.floating,de)),_e=_.current,Ae=q.current,oe=le(Ae);queueMicrotask(()=>{const me=NH(oe),pe=typeof _e!="boolean";if(_e&&!F.current&&pn(me)&&(!(!pe&&me!==de&&de!==ee.body)||Te)){const Ce={preventScroll:!0};Ae==="keyboard"&&(Ce.focusVisible=!0),me.focus(Ce)}F.current=!1})}},[o,P,ce,_,z,R,B,A,E,ue]),Me(()=>{if(!jl||k||!P)return;const ee=ir(Gt(P));!pn(ee)||!Zm(ee)||Ze(P,ee)&&ee.blur()},[k,P]),Me(()=>{if(!(o||!L))return L.setFocusManagerState({modal:p,closeOnFocusOut:h,open:k,onOpenChange:N.setOpen,domReference:A}),()=>{L.setFocusManagerState(null)}},[o,L,p,k,N,h,A]),Me(()=>{if(!(o||!ce))return hT(ce),()=>{queueMicrotask(wy)}},[o,ce]);const ve=!o&&(p?!I:!0)&&(ae||p);return s.jsxs(x.Fragment,{children:[ve&&s.jsx(ru,{"data-type":"inside",ref:Y,onFocus:ee=>{if(p){const he=W();fh(he[he.length-1])}else L?.portalNode&&(F.current=!1,Jc(ee,L.portalNode)?iy(A)?.focus():kl(v??L.beforeOutsideRef)?.focus())}}),a,ve&&s.jsx(ru,{"data-type":"inside",ref:re,onFocus:ee=>{p?fh(W()[0]):L?.portalNode&&(h&&(F.current=!0),Jc(ee,L.portalNode)?C1(A)?.focus():kl(y??L.afterOutsideRef)?.focus())}})]})}function hh(e,t={}){const{enabled:a=!0,event:o="click",toggle:c=!0,ignoreMouse:d=!1,stickIfOpen:f=!0,touchOpenDelay:p=0,reason:h=go}=t,b="rootStore"in e?e.rootStore:e,y=b.context.dataRef,v=x.useRef(void 0),j=eu(),w=er(),S=x.useMemo(()=>{function N(A,P,R,C){const E=qe(h,P,R);A&&C==="touch"&&p>0?w.start(p,()=>{b.setOpen(!0,E)}):b.setOpen(A,E)}function k(A,P,R){const C=y.current.openEvent,E=b.select("domReferenceElement")!==P;return A&&E||!A||!c?!0:C&&f?!R(C.type):!1}return{onPointerDown(A){v.current=fo(A.pointerType,!0)&&Jv(A.nativeEvent)?"virtual":A.pointerType},onMouseDown(A){const P=v.current,R=A.nativeEvent,C=b.select("open");if(A.button!==0||o==="click"||fo(P,!0)&&d)return;const E=k(C,A.currentTarget,O=>O==="click"||O==="mousedown"),D=fs(R);if(Zm(D)){N(E,R,D,P);return}const I=A.currentTarget;j.request(()=>{N(E,R,I,P)})},onClick(A){if(o==="mousedown-only")return;const P=v.current;if(o==="mousedown"&&P){v.current=void 0;return}if(fo(P,!0)&&d)return;const R=b.select("open"),C=k(R,A.currentTarget,E=>E==="click"||E==="mousedown"||E==="keydown"||E==="keyup");N(C,A.nativeEvent,A.currentTarget,P)},onKeyDown(){v.current=void 0}}},[y,o,d,h,b,f,c,j,w,p]);return x.useMemo(()=>a?{reference:S}:mn,[a,S])}function kH(e,t){let a=null,o=null,c=!1;return{contextElement:e||void 0,getBoundingClientRect(){const d=e?.getBoundingClientRect()||{width:0,height:0,x:0,y:0},f=t.axis==="x"||t.axis==="both",p=t.axis==="y"||t.axis==="both",h=["mouseenter","mousemove"].includes(t.dataRef.current.openEvent?.type||"")&&t.pointerType!=="touch";let b=d.width,y=d.height,v=d.x,j=d.y;return a==null&&t.x&&f&&(a=d.x-t.x),o==null&&t.y&&p&&(o=d.y-t.y),v-=a||0,j-=o||0,b=0,y=0,!c||h?(b=t.axis==="y"?d.width:0,y=t.axis==="x"?d.height:0,v=f&&t.x!=null?t.x:v,j=p&&t.y!=null?t.y:j):c&&!h&&(y=t.axis==="x"?d.height:y,b=t.axis==="y"?d.width:b),c=!0,{width:b,height:y,x:v,y:j,top:j,right:v+b,bottom:j+y,left:v}}}}function gT(e){return e!=null&&e.clientX!=null}function CH(e,t={}){const{enabled:a=!0,axis:o="both"}=t,c="rootStore"in e?e.rootStore:e,d=c.useState("open"),f=c.useState("floatingElement"),p=c.useState("domReferenceElement"),h=c.context.dataRef,b=x.useRef(!1),y=x.useRef(null),[v,j]=x.useState(),[w,S]=x.useState([]),N=Ie(C=>{c.set("positionReference",C)}),k=Ie((C,E,D)=>{b.current||h.current.openEvent&&!gT(h.current.openEvent)||c.set("positionReference",kH(D??p,{x:C,y:E,axis:o,dataRef:h,pointerType:v}))}),A=Ie(C=>{d?y.current||(k(C.clientX,C.clientY,C.currentTarget),S([])):k(C.clientX,C.clientY,C.currentTarget)}),P=fo(v)?f:d;x.useEffect(()=>{if(!a){N(p);return}if(!P)return;function C(){y.current?.(),y.current=null}const E=Cn(f);function D(I){const O=fs(I);Ze(f,O)?C():k(I.clientX,I.clientY)}return!h.current.openEvent||gT(h.current.openEvent)?y.current=St(E,"mousemove",D):N(p),C},[P,a,f,h,p,c,k,N,w]),x.useEffect(()=>()=>{c.set("positionReference",null)},[c]),x.useEffect(()=>{a&&!f&&(b.current=!1)},[a,f]),x.useEffect(()=>{!a&&d&&(b.current=!0)},[a,d]);const R=x.useMemo(()=>{function C(E){j(E.pointerType)}return{onPointerDown:C,onPointerEnter:C,onMouseMove:A,onMouseEnter:A}},[A]);return x.useMemo(()=>a?{reference:R,trigger:R}:{},[a,R])}function TH(){return!1}function EH(e){return{escapeKey:typeof e=="boolean"?e:e?.escapeKey??!1,outsidePress:typeof e=="boolean"?e:e?.outsidePress??!0}}function pf(e,t={}){const{enabled:a=!0,escapeKey:o=!0,outsidePress:c=!0,outsidePressEvent:d="sloppy",referencePress:f=TH,bubbles:p,externalTree:h}=t,b="rootStore"in e?e.rootStore:e,y=b.useState("open"),v=b.useState("floatingElement"),{dataRef:j,events:w}=b.context,S=Bi(h),N=Ie(typeof c=="function"?c:()=>!1),k=typeof c=="function"?N:c,A=k!==!1,P=Ie(()=>d),{escapeKey:R,outsidePress:C}=EH(p),E=x.useRef(!1),D=x.useRef(!1),I=x.useRef(!1),O=x.useRef(!1),_=x.useRef(!1),z=x.useRef(""),H=x.useRef(null),B=er(),L=er(),F=Ie(()=>{L.clear(),j.current.insideReactTree=!1}),$=Ie(M=>{const U=j.current.floatingContext?.nodeId;return(S?uo(S.nodesRef.current,U):[]).some(ae=>ae.context?.open&&!ae.context.dataRef.current[M])}),X=Ie(M=>Zv(M,b.select("floatingElement"))||Zv(M,b.select("domReferenceElement"))),K=Ie(M=>{f()&&b.setOpen(!1,qe(go,M.nativeEvent))}),q=Ie(M=>{if(!y||!a||!o||M.key!=="Escape"||_.current||!R&&$("__escapeKeyBubbles"))return;const U=WB(M)?M.nativeEvent:M,Z=qe(nu,U);b.setOpen(!1,Z),Z.isCanceled||M.preventDefault(),!R&&!Z.isPropagationAllowed&&M.stopPropagation()}),Q=Ie(()=>{j.current.insideReactTree=!0,L.start(0,F)}),G=Ie(M=>{if(!y||!a||M.button!==0)return;const U=fs(M.nativeEvent);Ze(b.select("floatingElement"),U)&&(E.current||(E.current=!0,D.current=!1))}),J=Ie(M=>{!y||!a||(M.defaultPrevented||M.nativeEvent.defaultPrevented)&&E.current&&(D.current=!0)});x.useEffect(()=>{function M(U){U.open||(O.current=!1)}return w.on("openchange",M),()=>{w.off("openchange",M)}},[w]),x.useEffect(()=>{if(!y||!a)return y||(O.current=!1),F;j.current.__escapeKeyBubbles=R,j.current.__outsidePressBubbles=C;const M=new la,U=new la,Z=Gt(v);function ae(){M.clear(),_.current=!0}function ce(){M.start(jl?5:0,()=>{_.current=!1})}function W(){I.current=!0,U.start(0,()=>{I.current=!1})}function ue(){E.current=!1,D.current=!1}function ve(){const Ne=z.current,be=Ne==="pen"||!Ne?"mouse":Ne,De=P(),Ge=typeof De=="function"?De():De;return typeof Ge=="string"?Ge:Ge[be]}function ee(Ne){const be=ve();return be==="intentional"&&Ne.type!=="click"||be==="sloppy"&&Ne.type==="click"}function he(Ne){const be=j.current.floatingContext?.nodeId,De=S&&uo(S.nodesRef.current,be).some(Ge=>Zv(Ne,Ge.context?.elements.floating));return X(Ne)||De}function te(Ne){if(ee(Ne)){Ne.type!=="click"&&!X(Ne)&&(U.clear(),I.current=!1),F();return}if(j.current.insideReactTree){F();return}const be=fs(Ne),De=`[${df("inert")}]`,Ge=Rt(be)?be.getRootNode():null,Ct=Array.from((Gc(Ge)?Ge:Gt(b.select("floatingElement"))).querySelectorAll(De)),Tt=b.context.triggerElements;if(be&&(Tt.hasElement(be)||Tt.hasMatchingElement(ot=>Ze(ot,be))))return;let Mt=Rt(be)?be:null;for(;Mt&&!ro(Mt);){const ot=ao(Mt);if(ro(ot)||!Rt(ot))break;Mt=ot}if(!(Ct.length&&Rt(be)&&!XB(be)&&!Ze(be,b.select("floatingElement"))&&Ct.every(ot=>!Ze(Mt,ot)))){if(pn(be)&&!("touches"in Ne)){const ot=ro(be),Kn=yr(be),ms=/auto|scroll/,Yn=ot||ms.test(Kn.overflowX),vs=ot||ms.test(Kn.overflowY),it=Yn&&be.clientWidth>0&&be.scrollWidth>be.clientWidth,$t=vs&&be.clientHeight>0&&be.scrollHeight>be.clientHeight,Vn=Kn.direction==="rtl",rn=$t&&(Vn?Ne.offsetX<=be.offsetWidth-be.clientWidth:Ne.offsetX>be.clientWidth),nt=it&&Ne.offsetY>be.clientHeight;if(rn||nt)return}if(!he(Ne)){if(ve()==="intentional"){if(Ne.detail!==0&&!Jm(Ne)&&!O.current)return;if(I.current){U.clear(),I.current=!1;return}}typeof k=="function"&&!k(Ne)||$("__outsidePressBubbles")||(b.setOpen(!1,qe(ch,Ne)),F())}}}function ke(Ne){ve()!=="sloppy"||Ne.pointerType==="touch"||!b.select("open")||!a||X(Ne)||te(Ne)}function le(Ne){if(ve()!=="sloppy"||!b.select("open")||!a||X(Ne))return;const be=Ne.touches[0];be&&(H.current={startTime:Date.now(),startX:be.clientX,startY:be.clientY,dismissOnTouchEnd:!1,dismissOnMouseDown:!0},B.start(1e3,()=>{H.current&&(H.current.dismissOnTouchEnd=!1,H.current.dismissOnMouseDown=!1)}))}function de(Ne,be){const De=fs(Ne);if(!De)return;const Ge=St(De,Ne.type,()=>{be(Ne),Ge()})}function Se(Ne){z.current="touch",de(Ne,le)}function Te(Ne){B.clear(),Ne.type==="pointerdown"&&(Ne.button===0&&(O.current=!0),z.current=Ne.pointerType),!(Ne.type==="mousedown"&&H.current&&!H.current.dismissOnMouseDown)&&de(Ne,be=>{be.type==="pointerdown"?ke(be):te(be)})}function _e(Ne){if(Ne.type==="pointercancel"&&(O.current=!1),!E.current)return;const be=D.current;if(ue(),ve()==="intentional"){if(Ne.type==="pointercancel"){be&&W();return}if(!he(Ne)){if(be){W();return}typeof k=="function"&&!k(Ne)||(U.clear(),I.current=!0,F())}}}function Ae(Ne){if(ve()!=="sloppy"||!H.current||X(Ne))return;const be=Ne.touches[0];if(!be)return;const De=Math.abs(be.clientX-H.current.startX),Ge=Math.abs(be.clientY-H.current.startY),Ct=Math.sqrt(De*De+Ge*Ge);Ct>5&&(H.current.dismissOnTouchEnd=!0),Ct>10&&(te(Ne),B.clear(),H.current=null)}function oe(Ne){de(Ne,Ae)}function me(Ne){ve()!=="sloppy"||!H.current||X(Ne)||(H.current.dismissOnTouchEnd&&te(Ne),B.clear(),H.current=null)}function pe(Ne){de(Ne,me)}const Ce=Xa(o&&Xa(St(Z,"keydown",q),St(Z,"compositionstart",ae),St(Z,"compositionend",ce)),A&&Xa(St(Z,"click",Te,!0),St(Z,"pointerdown",Te,!0),St(Z,"pointerup",_e,!0),St(Z,"pointercancel",_e,!0),St(Z,"mousedown",Te,!0),St(Z,"mouseup",_e,!0),St(Z,"touchstart",Se,{capture:!0,passive:!0}),St(Z,"touchmove",oe,{capture:!0,passive:!0}),St(Z,"touchend",pe,{capture:!0,passive:!0})));return()=>{Ce(),M.clear(),U.clear(),ue(),I.current=!1,F()}},[j,v,o,A,k,y,a,R,C,q,F,P,$,X,S,b,B]);const Y=x.useMemo(()=>({onKeyDown:q,onPointerDown:K,onClick:K}),[q,K]),re=x.useMemo(()=>({onKeyDown:q,onPointerDown:J,onMouseDown:J,onClickCapture:Q,onMouseDownCapture(M){Q(),G(M)},onPointerDownCapture(M){Q(),G(M)},onMouseUpCapture:Q,onTouchEndCapture:Q,onTouchMoveCapture:Q}),[q,Q,G,J]);return x.useMemo(()=>a?{reference:Y,floating:re,trigger:Y}:{},[a,Y,re])}function xT(e,t,a){let{reference:o,floating:c}=e;const d=aa(t),f=ny(t),p=ty(f),h=ra(t),b=d==="y",y=o.x+o.width/2-c.width/2,v=o.y+o.height/2-c.height/2,j=o[p]/2-c[p]/2;let w;switch(h){case"top":w={x:y,y:o.y-c.height};break;case"bottom":w={x:y,y:o.y+o.height};break;case"right":w={x:o.x+o.width,y:v};break;case"left":w={x:o.x-c.width,y:v};break;default:w={x:o.x,y:o.y}}const S=Nl(t);return S&&(w[f]+=j*(S==="end"?1:-1)*(a&&b?-1:1)),w}async function AH(e,t){var a;t===void 0&&(t={});const{x:o,y:c,platform:d,rects:f,elements:p,strategy:h}=e,{boundary:b="clippingAncestors",rootBoundary:y="viewport",elementContext:v="floating",altBoundary:j=!1,padding:w=0}=po(t,e),S=x1(w),k=p[j?v==="floating"?"reference":"floating":v],A=nf(await d.getClippingRect({element:(a=await(d.isElement==null?void 0:d.isElement(k)))==null||a?k:k.contextElement||await(d.getDocumentElement==null?void 0:d.getDocumentElement(p.floating)),boundary:b,rootBoundary:y,strategy:h})),P=v==="floating"?{x:o,y:c,width:f.floating.width,height:f.floating.height}:f.reference,R=await(d.getOffsetParent==null?void 0:d.getOffsetParent(p.floating)),C=await(d.isElement==null?void 0:d.isElement(R))&&await(d.getScale==null?void 0:d.getScale(R))||{x:1,y:1},E=nf(d.convertOffsetParentRelativeRectToViewportRelativeRect?await d.convertOffsetParentRelativeRectToViewportRelativeRect({elements:p,rect:P,offsetParent:R,strategy:h}):P);return{top:(A.top-E.top+S.top)/C.y,bottom:(E.bottom-A.bottom+S.bottom)/C.y,left:(A.left-E.left+S.left)/C.x,right:(E.right-A.right+S.right)/C.x}}const RH=50,OH=async(e,t,a)=>{const{placement:o="bottom",strategy:c="absolute",middleware:d=[],platform:f}=a,p=f.detectOverflow?f:{...f,detectOverflow:AH},h=await(f.isRTL==null?void 0:f.isRTL(t));let b=await f.getElementRects({reference:e,floating:t,strategy:c}),{x:y,y:v}=xT(b,o,h),j=o,w=0;const S={};for(let N=0;NF<=0)){var H,B;const F=(((H=d.flip)==null?void 0:H.index)||0)+1,$=I[F];if($&&(!(v==="alignment"?P!==aa($):!1)||z.every(q=>aa(q.placement)===P?q.overflows[0]>0:!0)))return{data:{index:F,overflows:z},reset:{placement:$}};let X=(B=z.filter(K=>K.overflows[0]<=0).sort((K,q)=>K.overflows[1]-q.overflows[1])[0])==null?void 0:B.placement;if(!X)switch(w){case"bestFit":{var L;const K=(L=z.filter(q=>{if(D){const Q=aa(q.placement);return Q===P||Q==="y"}return!0}).map(q=>[q.placement,q.overflows.filter(Q=>Q>0).reduce((Q,G)=>Q+G,0)]).sort((q,Q)=>q[1]-Q[1])[0])==null?void 0:L[0];K&&(X=K);break}case"initialPlacement":X=p;break}if(c!==X)return{reset:{placement:X}}}return{}}}},bT=new Set(["left","top"]);async function DH(e,t){const{placement:a,platform:o,elements:c}=e,d=await(o.isRTL==null?void 0:o.isRTL(c.floating)),f=ra(a),p=Nl(a),h=aa(a)==="y",b=bT.has(f)?-1:1,y=d&&h?-1:1,v=po(t,e);let{mainAxis:j,crossAxis:w,alignmentAxis:S}=typeof v=="number"?{mainAxis:v,crossAxis:0,alignmentAxis:null}:{mainAxis:v.mainAxis||0,crossAxis:v.crossAxis||0,alignmentAxis:v.alignmentAxis};return p&&typeof S=="number"&&(w=p==="end"?S*-1:S),h?{x:w*y,y:j*b}:{x:j*b,y:w*y}}const IH=function(e){return e===void 0&&(e=0),{name:"offset",options:e,async fn(t){var a,o;const{x:c,y:d,placement:f,middlewareData:p}=t,h=await DH(t,e);return f===((a=p.offset)==null?void 0:a.placement)&&(o=p.arrow)!=null&&o.alignmentOffset?{}:{x:c+h.x,y:d+h.y,data:{...h,placement:f}}}}},PH=function(e){return e===void 0&&(e={}),{name:"shift",options:e,async fn(t){const{x:a,y:o,placement:c,platform:d}=t,{mainAxis:f=!0,crossAxis:p=!1,limiter:h={fn:P=>{let{x:R,y:C}=P;return{x:R,y:C}}},...b}=po(e,t),y={x:a,y:o},v=await d.detectOverflow(t,b),j=aa(c),w=ey(j);let S=y[w],N=y[j];const k=(P,R)=>m1(R+v[P==="y"?"top":"left"],R,R-v[P==="y"?"bottom":"right"]);f&&(S=k(w,S)),p&&(N=k(j,N));const A=h.fn({...t,[w]:S,[j]:N});return{...A,data:{x:A.x-a,y:A.y-o,enabled:{[w]:f,[j]:p}}}}}},_H=function(e){return e===void 0&&(e={}),{options:e,fn(t){var a,o;const{x:c,y:d,placement:f,rects:p,middlewareData:h}=t,{offset:b=0,mainAxis:y=!0,crossAxis:v=!0}=po(e,t),j={x:c,y:d},w=aa(f),S=ey(w);let N=j[S],k=j[w];const A=po(b,t),P=typeof A=="number"?{mainAxis:A,crossAxis:0}:{mainAxis:(a=A.mainAxis)!=null?a:0,crossAxis:(o=A.crossAxis)!=null?o:0};if(y){const E=S==="y"?"height":"width",D=p.reference[S]-p.floating[E]+P.mainAxis,I=p.reference[S]+p.reference[E]-P.mainAxis;NI&&(N=I)}if(v){var R,C;const E=S==="y"?"width":"height",D=bT.has(ra(f)),I=p.reference[w]-p.floating[E]+(D&&((R=h.offset)==null?void 0:R[w])||0)+(D?0:P.crossAxis),O=p.reference[w]+p.reference[E]+(D?0:((C=h.offset)==null?void 0:C[w])||0)-(D?P.crossAxis:0);kO&&(k=O)}return{[S]:N,[w]:k}}}},LH=function(e){return e===void 0&&(e={}),{name:"size",options:e,async fn(t){const{placement:a,rects:o,platform:c,elements:d}=t,{apply:f=()=>{},...p}=po(e,t),h=await c.detectOverflow(t,p),b=ra(a),y=Nl(a),v=aa(a)==="y",{width:j,height:w}=o.floating;let S,N;b==="top"||b==="bottom"?(S=b,N=y===(await(c.isRTL==null?void 0:c.isRTL(d.floating))?"start":"end")?"left":"right"):(N=b,S=y==="end"?"top":"bottom");const k=w-h.top-h.bottom,A=j-h.left-h.right,P=Wc(w-h[S],k),R=Wc(j-h[N],A),C=t.middlewareData.shift,E=!C;let D=P,I=R;C!=null&&C.enabled.x&&(I=A),C!=null&&C.enabled.y&&(D=k),E&&!y&&(v?I=j-2*wl(h.left,h.right):D=w-2*wl(h.top,h.bottom)),await f({...t,availableWidth:I,availableHeight:D});const O=await c.getDimensions(d.floating);return j!==O.width||w!==O.height?{reset:{rects:!0}}:{}}}};function vT(e){const t=yr(e);let a=parseFloat(t.width)||0,o=parseFloat(t.height)||0;const c=pn(e),d=c?e.offsetWidth:a,f=c?e.offsetHeight:o,p=eh(a)!==d||eh(o)!==f;return p&&(a=d,o=f),{width:a,height:o,$:p}}function Sy(e){return Rt(e)?e:e.contextElement}function lu(e){const t=Sy(e);if(!pn(t))return Sl(1);const a=t.getBoundingClientRect(),{width:o,height:c,$:d}=vT(t);let f=(d?eh(a.width):a.width)/o,p=(d?eh(a.height):a.height)/c;return(!f||!Number.isFinite(f))&&(f=1),(!p||!Number.isFinite(p))&&(p=1),{x:f,y:p}}const zH=Sl(0);function yT(e){const t=Cn(e);return!Rv()||!t.visualViewport?zH:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function BH(e,t,a){return t===void 0&&(t=!1),!!a&&t&&a===Cn(e)}function Hi(e,t,a,o){t===void 0&&(t=!1),a===void 0&&(a=!1);const c=e.getBoundingClientRect(),d=Sy(e);let f=Sl(1);t&&(o?Rt(o)&&(f=lu(o)):f=lu(e));const p=BH(d,a,o)?yT(d):Sl(0);let h=(c.left+p.x)/f.x,b=(c.top+p.y)/f.y,y=c.width/f.x,v=c.height/f.y;if(d&&o){const j=Cn(d),w=Rt(o)?Cn(o):o;let S=j,N=Ov(S);for(;N&&w!==S;){const k=lu(N),A=N.getBoundingClientRect(),P=yr(N),R=A.left+(N.clientLeft+parseFloat(P.paddingLeft))*k.x,C=A.top+(N.clientTop+parseFloat(P.paddingTop))*k.y;h*=k.x,b*=k.y,y*=k.x,v*=k.y,h+=R,b+=C,S=Cn(N),N=Ov(S)}}return nf({width:y,height:v,x:h,y:b})}function gh(e,t){const a=Um(e).scrollLeft;return t?t.left+a:Hi(bl(e)).left+a}function jT(e,t){const a=e.getBoundingClientRect(),o=a.left+t.scrollLeft-gh(e,a),c=a.top+t.scrollTop;return{x:o,y:c}}function HH(e){let{elements:t,rect:a,offsetParent:o,strategy:c}=e;const d=c==="fixed",f=bl(o),p=t?Hm(t.floating):!1;if(o===f||p&&d)return a;let h={scrollLeft:0,scrollTop:0},b=Sl(1);const y=Sl(0),v=pn(o);if((v||!d)&&((Fs(o)!=="body"||Qd(f))&&(h=Um(o)),v)){const w=Hi(o);b=lu(o),y.x=w.x+o.clientLeft,y.y=w.y+o.clientTop}const j=f&&!v&&!d?jT(f,h):Sl(0);return{width:a.width*b.x,height:a.height*b.y,x:a.x*b.x-h.scrollLeft*b.x+y.x+j.x,y:a.y*b.y-h.scrollTop*b.y+y.y+j.y}}function UH(e){return e.getClientRects?Array.from(e.getClientRects()):[]}function VH(e){const t=Um(e),a=e.ownerDocument.body,o=wl(e.scrollWidth,e.clientWidth,a.scrollWidth,a.clientWidth),c=wl(e.scrollHeight,e.clientHeight,a.scrollHeight,a.clientHeight);let d=-t.scrollLeft+gh(e);const f=-t.scrollTop;return yr(a).direction==="rtl"&&(d+=wl(e.clientWidth,a.clientWidth)-o),{width:o,height:c,x:d,y:f}}const FH=25;function $H(e,t,a){a===void 0&&(a="viewport");const o=a==="layoutViewport",c=Cn(e),d=bl(e),f=c.visualViewport;let p=d.clientWidth,h=d.clientHeight,b=0,y=0;if(f){const j=!Rv()||t==="fixed";o?j||(b=-f.offsetLeft,y=-f.offsetTop):(p=f.width,h=f.height,j&&(b=f.offsetLeft,y=f.offsetTop))}if(gh(d)<=0){const j=d.ownerDocument,w=j.body,S=getComputedStyle(w),N=j.compatMode==="CSS1Compat"&&parseFloat(S.marginLeft)+parseFloat(S.marginRight)||0,k=Math.abs(d.clientWidth-w.clientWidth-N),A=getComputedStyle(d).scrollbarGutter==="stable both-edges"?k/2:k;A<=FH&&(p-=A)}return{width:p,height:h,x:b,y}}function qH(e,t){const a=Hi(e,!0,t==="fixed"),o=a.top+e.clientTop,c=a.left+e.clientLeft,d=lu(e),f=e.clientWidth*d.x,p=e.clientHeight*d.y,h=c*d.x,b=o*d.y;return{width:f,height:p,x:h,y:b}}function wT(e,t,a){let o;if(t==="viewport"||t==="layoutViewport")o=$H(e,a,t);else if(t==="document")o=VH(bl(e));else if(Rt(t))o=qH(t,a);else{const c=yT(e);o={x:t.x-c.x,y:t.y-c.y,width:t.width,height:t.height}}return nf(o)}function GH(e,t){const a=t.get(e);if(a)return a;let o=Kc(e,[],!1).filter(p=>Rt(p)&&Fs(p)!=="body"),c=null;const d=yr(e).position==="fixed";let f=d?ao(e):e;for(;Rt(f)&&!ro(f);){const p=yr(f),h=Av(f),b=c?c.position:d?"fixed":"";!h&&(b==="fixed"||b==="absolute"&&p.position==="static")?o=o.filter(v=>v!==f):c=p,f=ao(f)}return t.set(e,o),o}function KH(e){let{element:t,boundary:a,rootBoundary:o,strategy:c}=e;const f=[...a==="clippingAncestors"?Hm(t)?[]:GH(t,this._c):[].concat(a),o],p=wT(t,f[0],c);let h=p.top,b=p.right,y=p.bottom,v=p.left;for(let j=1;j{p(!1,1e-7)},1e3)}I=!1}try{o=new IntersectionObserver(O,{...D,root:d.ownerDocument})}catch{o=new IntersectionObserver(O,D)}o.observe(e)}const h=Cn(e),b=()=>p(a);return h.addEventListener("resize",b),p(!0),()=>{h.removeEventListener("resize",b),f()}}function TT(e,t,a,o){o===void 0&&(o={});const{ancestorScroll:c=!0,ancestorResize:d=!0,elementResize:f=typeof ResizeObserver=="function",layoutShift:p=typeof IntersectionObserver=="function",animationFrame:h=!1}=o,b=Sy(e),y=c||d?[...b?Kc(b):[],...t?Kc(t):[]]:[];y.forEach(A=>{c&&A.addEventListener("scroll",a),d&&A.addEventListener("resize",a)});const v=b&&p?WH(b,a,d):null;let j=-1,w=null;f&&(w=new ResizeObserver(A=>{let[P]=A;P&&P.target===b&&w&&t&&(w.unobserve(t),cancelAnimationFrame(j),j=requestAnimationFrame(()=>{var R;(R=w)==null||R.observe(t)})),a()}),b&&!h&&w.observe(b),t&&w.observe(t));let S,N=h?Hi(e):null;h&&k();function k(){const A=Hi(e);N&&!CT(N,A)&&a(),N=A,S=requestAnimationFrame(k)}return a(),()=>{var A;y.forEach(P=>{c&&P.removeEventListener("scroll",a),d&&P.removeEventListener("resize",a)}),v?.(),(A=w)==null||A.disconnect(),w=null,h&&cancelAnimationFrame(S)}}const JH=IH,eU=PH,tU=MH,nU=LH,sU=_H,rU=(e,t,a)=>{const o=new Map,c=a??{},d={...kT,...c.platform,_c:o};return OH(e,t,{...c,platform:d})};var aU=typeof document<"u",lU=function(){},xh=aU?x.useLayoutEffect:lU;function bh(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(typeof e=="function"&&e.toString()===t.toString())return!0;let a,o,c;if(e&&t&&typeof e=="object"){if(Array.isArray(e)){if(a=e.length,a!==t.length)return!1;for(o=a;o--!==0;)if(!bh(e[o],t[o]))return!1;return!0}if(c=Object.keys(e),a=c.length,a!==Object.keys(t).length)return!1;for(o=a;o--!==0;)if(!{}.hasOwnProperty.call(t,c[o]))return!1;for(o=a;o--!==0;){const d=c[o];if(!(d==="_owner"&&e.$$typeof)&&!bh(e[d],t[d]))return!1}return!0}return e!==e&&t!==t}function ET(e){return typeof window>"u"?1:(e.ownerDocument.defaultView||window).devicePixelRatio||1}function AT(e,t){const a=ET(e);return Math.round(t*a)/a}function ky(e){const t=x.useRef(e);return xh(()=>{t.current=e}),t}function oU(e){e===void 0&&(e={});const{placement:t="bottom",strategy:a="absolute",middleware:o=[],platform:c,elements:{reference:d,floating:f}={},transform:p=!0,whileElementsMounted:h,open:b}=e,[y,v]=x.useState({x:0,y:0,strategy:a,placement:t,middlewareData:{},isPositioned:!1}),[j,w]=x.useState(o);bh(j,o)||w(o);const[S,N]=x.useState(null),[k,A]=x.useState(null),P=x.useCallback(q=>{q!==D.current&&(D.current=q,N(q))},[]),R=x.useCallback(q=>{q!==I.current&&(I.current=q,A(q))},[]),C=d||S,E=f||k,D=x.useRef(null),I=x.useRef(null),O=x.useRef(y),_=h!=null,z=ky(h),H=ky(c),B=ky(b),L=x.useCallback(()=>{if(!D.current||!I.current)return;const q={placement:t,strategy:a,middleware:j};H.current&&(q.platform=H.current),rU(D.current,I.current,q).then(Q=>{const G={...Q,isPositioned:B.current!==!1};F.current&&!bh(O.current,G)&&(O.current=G,Ts.flushSync(()=>{v(G)}))})},[j,t,a,H,B]);xh(()=>{b===!1&&O.current.isPositioned&&(O.current.isPositioned=!1,v(q=>({...q,isPositioned:!1})))},[b]);const F=x.useRef(!1);xh(()=>(F.current=!0,()=>{F.current=!1}),[]),xh(()=>{if(C&&(D.current=C),E&&(I.current=E),C&&E){if(z.current)return z.current(C,E,L);L()}},[C,E,L,z,_]);const $=x.useMemo(()=>({reference:D,floating:I,setReference:P,setFloating:R}),[P,R]),X=x.useMemo(()=>({reference:C,floating:E}),[C,E]),K=x.useMemo(()=>{const q={position:a,left:0,top:0};if(!X.floating)return q;const Q=AT(X.floating,y.x),G=AT(X.floating,y.y);return p?{...q,transform:"translate("+Q+"px, "+G+"px)",...ET(X.floating)>=1.5&&{willChange:"transform"}}:{position:a,left:Q,top:G}},[a,p,X.floating,y.x,y.y]);return x.useMemo(()=>({...y,update:L,refs:$,elements:X,floatingStyles:K}),[y,L,$,X,K])}const iU=(e,t)=>{const a=JH(e);return{name:a.name,fn:a.fn,options:[e,t]}},cU=(e,t)=>{const a=eU(e);return{name:a.name,fn:a.fn,options:[e,t]}},uU=(e,t)=>({fn:sU(e).fn,options:[e,t]}),dU=(e,t)=>{const a=tU(e);return{name:a.name,fn:a.fn,options:[e,t]}},fU=(e,t)=>{const a=nU(e);return{name:a.name,fn:a.fn,options:[e,t]}};var Cy={exports:{}},Ty={};var RT;function pU(){if(RT)return Ty;RT=1;var e=Xd();function t(v,j){return v===j&&(v!==0||1/v===1/j)||v!==v&&j!==j}var a=typeof Object.is=="function"?Object.is:t,o=e.useState,c=e.useEffect,d=e.useLayoutEffect,f=e.useDebugValue;function p(v,j){var w=j(),S=o({inst:{value:w,getSnapshot:j}}),N=S[0].inst,k=S[1];return d(function(){N.value=w,N.getSnapshot=j,h(N)&&k({inst:N})},[v,w,j]),c(function(){return h(N)&&k({inst:N}),v(function(){h(N)&&k({inst:N})})},[v]),f(w),w}function h(v){var j=v.getSnapshot;v=v.value;try{var w=j();return!a(v,w)}catch{return!0}}function b(v,j){return j()}var y=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?b:p;return Ty.useSyncExternalStore=e.useSyncExternalStore!==void 0?e.useSyncExternalStore:y,Ty}var OT;function MT(){return OT||(OT=1,Cy.exports=pU()),Cy.exports}var Ey=MT(),Ay={exports:{}},Ry={};var DT;function mU(){if(DT)return Ry;DT=1;var e=Xd(),t=MT();function a(b,y){return b===y&&(b!==0||1/b===1/y)||b!==b&&y!==y}var o=typeof Object.is=="function"?Object.is:a,c=t.useSyncExternalStore,d=e.useRef,f=e.useEffect,p=e.useMemo,h=e.useDebugValue;return Ry.useSyncExternalStoreWithSelector=function(b,y,v,j,w){var S=d(null);if(S.current===null){var N={hasValue:!1,value:null};S.current=N}else N=S.current;S=p(function(){function A(D){if(!P){if(P=!0,R=D,D=j(D),w!==void 0&&N.hasValue){var I=N.value;if(w(I,D))return C=I}return C=D}if(I=C,o(R,D))return I;var O=j(D);return w!==void 0&&w(I,O)?(R=D,I):(R=D,C=O)}var P=!1,R,C,E=v===void 0?null:v;return[function(){return A(y())},E===null?void 0:function(){return A(E())}]},[y,v,j,w]);var k=c(b,S[0],S[1]);return f(function(){N.hasValue=!0,N.value=k},[k]),h(k),k},Ry}var IT;function hU(){return IT||(IT=1,Ay.exports=mU()),Ay.exports}var gU=hU();const xU=zv(19)?vU:yU;function PT(e,t,a,o,c){return xU(e,t,a,o,c)}function bU(e,t,a,o,c){const d=x.useCallback(()=>t(e.getSnapshot(),a,o,c),[e,t,a,o,c]);return Ey.useSyncExternalStore(e.subscribe,d,d)}aH({before(e){e.syncIndex=0,e.didInitialize||(e.syncTick=1,e.syncHooks=[],e.didChangeStore=!0,e.getSnapshot=()=>{let t=!1;for(let a=0;a0&&(e.didChangeStore&&(e.didChangeStore=!1,e.subscribe=t=>{const a=new Set;for(const c of e.syncHooks)a.add(c.store);const o=[];for(const c of a)o.push(c.subscribe(t));return()=>{for(const c of o)c()}}),Ey.useSyncExternalStore(e.subscribe,e.getSnapshot,e.getSnapshot))}});function vU(e,t,a,o,c){const d=rH();if(!d)return bU(e,t,a,o,c);const f=d.syncIndex;d.syncIndex+=1;let p;return d.didInitialize?(p=d.syncHooks[f],(p.store!==e||p.selector!==t||!Object.is(p.a1,a)||!Object.is(p.a2,o)||!Object.is(p.a3,c))&&(p.store!==e&&(d.didChangeStore=!0),p.store=e,p.selector=t,p.a1=a,p.a2=o,p.a3=c,p.value=t(e.getSnapshot(),a,o,c))):(p={store:e,selector:t,a1:a,a2:o,a3:c,value:t(e.getSnapshot(),a,o,c)},d.syncHooks.push(p)),p.value}function yU(e,t,a,o,c){return gU.useSyncExternalStoreWithSelector(e.subscribe,e.getSnapshot,e.getSnapshot,d=>t(d,a,o,c))}class jU{constructor(t){cn(this,"subscribe",t=>(this.listeners.add(t),()=>{this.listeners.delete(t)}));cn(this,"getSnapshot",()=>this.state);this.state=t,this.listeners=new Set,this.updateTick=0}static create(t){return new this(t)}setState(t){if(this.state===t)return;this.state=t,this.updateTick+=1;const a=this.updateTick;for(const o of this.listeners){if(a!==this.updateTick)return;o(t)}}update(t){for(const a in t)if(!Object.is(this.state[a],t[a])){this.setState({...this.state,...t});return}}set(t,a){Object.is(this.state[t],a)||this.setState({...this.state,[t]:a})}notifyAll(){const t={...this.state};this.setState(t)}use(t,a,o,c){return PT(this,t,a,o,c)}}class ou extends jU{constructor(t,a={},o){super(t),this.context=a,this.selectors=o}useSyncedValue(t,a){x.useDebugValue(t);const o=this;Me(()=>{o.state[t]!==a&&o.set(t,a)},[o,t,a])}useSyncedValueWithCleanup(t,a){const o=this;Me(()=>(o.state[t]!==a&&o.set(t,a),()=>{o.set(t,void 0)}),[o,t,a])}useSyncedValues(t){const a=this,o=Object.values(t);Me(()=>{a.update(t)},[a,...o])}useControlledProp(t,a){x.useDebugValue(t);const o=this,c=a!==void 0;Me(()=>{c&&!Object.is(o.state[t],a)&&o.setState({...o.state,[t]:a})},[o,t,a,c])}select(t,a,o,c){const d=this.selectors[t];return d(this.state,a,o,c)}useState(t,a,o,c){return x.useDebugValue(t),PT(this,this.selectors[t],a,o,c)}useContextCallback(t,a){x.useDebugValue(t);const o=Ie(a??Kt);this.context[t]=o}useStateSetter(t){const a=x.useRef(void 0);return a.current===void 0&&(a.current=o=>{this.set(t,o)}),a.current}observe(t,a){let o;typeof t=="function"?o=t:o=this.selectors[t];let c=o(this.state);return a(c,c,this),this.subscribe(d=>{const f=o(d);if(!Object.is(c,f)){const p=c;c=f,a(f,p,this)}})}}const wU={open:e=>e.open,transitionStatus:e=>e.transitionStatus,domReferenceElement:e=>e.domReferenceElement,referenceElement:e=>e.positionReference??e.referenceElement,floatingElement:e=>e.floatingElement,floatingId:e=>e.floatingId};class Oy extends ou{constructor(a){const{syncOnly:o,nested:c,onOpenChange:d,triggerElements:f,...p}=a;super({...p,positionReference:p.referenceElement,domReferenceElement:p.referenceElement},{onOpenChange:d,dataRef:{current:{}},events:cT(),nested:c,triggerElements:f},wU);cn(this,"syncOpenEvent",(a,o)=>{(!a||!this.state.open||o!=null&&JB(o))&&(this.context.dataRef.current.openEvent=a?o:void 0)});cn(this,"dispatchOpenChange",(a,o)=>{this.syncOpenEvent(a,o.event);const c={open:a,reason:o.reason,nativeEvent:o.event,nested:this.context.nested,triggerElement:o.trigger};this.context.events.emit("openchange",c)});cn(this,"setOpen",(a,o)=>{if(this.syncOnly){this.context.onOpenChange?.(a,o);return}this.dispatchOpenChange(a,o),this.context.onOpenChange?.(a,o)});this.syncOnly=o}}function SU(e){const{popupStore:t,treatPopupAsFloatingElement:a=!1,floatingRootContext:o,floatingId:c,nested:d,onOpenChange:f}=e,p=t.useState("open"),h=t.useState("activeTriggerElement"),b=t.useState(a?"popupElement":"positionerElement"),y=t.context.triggerElements,v=f,j=x.useRef(null);o===void 0&&j.current===null&&(j.current=new Oy({open:p,transitionStatus:void 0,referenceElement:h,floatingElement:b,triggerElements:y,onOpenChange:v,floatingId:c,syncOnly:!0,nested:d}));const w=o??j.current;return t.useSyncedValue("floatingId",c),Me(()=>{const S={open:p,floatingId:c,referenceElement:h,floatingElement:b};Rt(h)&&(S.domReferenceElement=h),w.state.positionReference===w.state.referenceElement&&(S.positionReference=h),w.update(S)},[p,c,h,b,w]),w.context.onOpenChange=v,w.context.nested=d,w}const mf={tabIndex:-1,[qv]:""};function _T(e){return t=>t==="touch"?e.current:!0}function My(e,t=!1){const a=Jd(),o=au()!=null,c=Ps(()=>e(a,o)).current;return SU({popupStore:c,treatPopupAsFloatingElement:t,floatingRootContext:c.state.floatingRootContext,floatingId:a,nested:o,onOpenChange:c.setOpen}),c}function Dy({handle:e,store:t}){return Me(()=>e.attachStore(t),[e,t]),null}function LT(e){const t=e.context.triggerElements.size;e.select("open")&&e.state.triggerCount!==t&&e.set("triggerCount",t)}function NU(e,t){const a=x.useRef(null);return Ie(o=>{const c=a.current;if(c!==null){if(c.element===o&&c.store===t&&c.id===e)return;a.current=null;const d=c.store;d.context.triggerElements.getById(c.id)===c.element&&(d.context.triggerElements.delete(c.id),LT(d))}o!==null&&e!==void 0&&(a.current={store:t,id:e,element:o},t.context.triggerElements.add(e,o),LT(t))})}function Iy(e,t,a,o=!1){let c=e.preventUnmountingOnClose;t?c=!1:o&&(c=!0);const d=a?.id??null;let f=e.activeTriggerId,p=e.activeTriggerElement;return(d||t)&&(f=d,p=a??null),{open:t,preventUnmountingOnClose:c,activeTriggerId:f,activeTriggerElement:p}}function zT(e){let t=!1;return e.preventUnmountOnClose=()=>{t=!0},()=>t}function kU(e,t,a,o={}){const c=a.reason,d=c===qs,f=t&&c===ih,p=!t&&(c===go||c===nu),h=zT(a);if(e.context.onOpenChange?.(t,a),a.isCanceled)return;o.onBeforeDispatch?.(),e.state.floatingRootContext.dispatchOpenChange(t,a);const b=()=>{const y=Iy(e.state,t,a.trigger,h()),v={...o.extraState,...y};f?v.instantType="focus":p?v.instantType="dismiss":d&&(v.instantType=void 0),e.update(v)};d?Ts.flushSync(b):b()}function BT(e,t,a,o){const c=a.useState("isMountedByTrigger",e),d=NU(e,a),f=Ie(h=>{const b=a.select("open"),y=a.select("activeTriggerId");if(y===e){const v={activeTriggerElement:h,...b?o:null};a.update(v);return}if(y==null&&b){const v={activeTriggerId:e??null,activeTriggerElement:h,...o};a.update(v)}}),p=Ie(h=>{d(h),h&&f(h)});return Me(()=>(p(t.current),()=>p(null)),[p,t,a,e]),Me(()=>{if(c){const h={activeTriggerElement:t.current,...o};a.update(h)}},[c,a,t,...Object.values(o)]),{registerTrigger:p,isMountedByThisTrigger:c}}function Py(e,t={}){const{closeOnActiveTriggerUnmount:a=!1}=t,o=x.useRef(null),c=e.useState("open"),d=e.useState("triggerCount"),f=e.useState("activeTriggerId"),p=e.useState("activeTriggerElement");Me(()=>{if(!c){o.current=null,e.state.triggerCount!==0&&e.set("triggerCount",0);return}const h=e.context.triggerElements.size,b={};e.state.triggerCount!==h&&(b.triggerCount=h);const y=e.select("activeTriggerId");let v=null;if(y){const j=e.context.triggerElements.getById(y);if(j)o.current=y,j!==e.state.activeTriggerElement&&(b.activeTriggerElement=j);else{for(const[w,S]of e.context.triggerElements.entries())if(S===e.state.activeTriggerElement){b.activeTriggerId=w,b.activeTriggerElement=S,o.current=w;break}b.activeTriggerId===void 0&&(o.current===y?v=y:o.current=null)}}else o.current=null;if(!v&&!y&&h===1){const j=e.context.triggerElements.entries().next();if(!j.done){const[w,S]=j.value;b.activeTriggerId=w,b.activeTriggerElement=S,o.current=w}}(b.triggerCount!==void 0||b.activeTriggerId!==void 0||b.activeTriggerElement!==void 0)&&e.update(b),v&&a&&queueMicrotask(()=>{if(e.select("open")&&e.select("activeTriggerId")===v&&!e.context.triggerElements.getById(v)){const j=qe(Qn);e.setOpen(!1,j),j.isCanceled||e.update({activeTriggerId:null,activeTriggerElement:null})}})},[c,e,d,f,p,a])}function _y(e,t,a,o){const{mounted:c,setMounted:d,transitionStatus:f}=Oi(e,!1,!1,o),p=t.useState("preventUnmountingOnClose"),h=e?!1:p;t.useSyncedValues({mounted:c,transitionStatus:f,preventUnmountingOnClose:h});const b=Ie(()=>{d(!1),t.update({activeTriggerId:null,activeTriggerElement:null,mounted:!1,preventUnmountingOnClose:!1}),a?.(),t.context.onOpenChangeComplete?.(!1)});return oa({enabled:c&&!e&&!h,open:e,ref:t.context.popupRef,onComplete(){e||b()}}),{forceUnmount:b,transitionStatus:f}}function Ly(e,t){e.useSyncedValues(t),Me(()=>()=>{e.update({activeTriggerProps:mn,inactiveTriggerProps:mn,popupProps:mn})},[e])}function HT(e,t){Me(()=>{!t&&e.state.openMethod!==null&&e.set("openMethod",null)},[t,e]),Me(()=>()=>{e.state.openMethod!==null&&e.set("openMethod",null)},[e])}class vh{constructor(){this.idMap=new Map}add(t,a){this.idMap.set(t,a)}delete(t){this.idMap.delete(t)}hasElement(t){for(const a of this.idMap.values())if(a===t)return!0;return!1}hasMatchingElement(t){for(const a of this.idMap.values())if(t(a))return!0;return!1}getById(t){return this.idMap.get(t)}entries(){return this.idMap.entries()}elements(){return this.idMap.values()}get size(){return this.idMap.size}}function zy(e,t,a=!1){return{open:!1,openProp:void 0,mounted:!1,transitionStatus:void 0,floatingRootContext:new Oy({open:!1,transitionStatus:void 0,floatingElement:null,referenceElement:null,triggerElements:e,floatingId:t,syncOnly:!0,nested:a,onOpenChange:void 0}),floatingId:t,triggerCount:0,preventUnmountingOnClose:!1,payload:void 0,activeTriggerId:null,activeTriggerElement:null,triggerIdProp:void 0,popupElement:null,positionerElement:null,activeTriggerProps:mn,inactiveTriggerProps:mn,popupProps:mn}}const hf=e=>e.triggerIdProp??e.activeTriggerId,By=e=>e.openProp??e.open,UT=e=>(e.popupElement?.id??e.floatingId)||void 0;function VT(e,t){return t!==void 0&&By(e)&&hf(e)===t}function CU(e,t){return VT(e,t)?!0:t!==void 0&&By(e)&&hf(e)==null&&e.triggerCount===1}const Hy={open:By,mounted:e=>e.mounted,transitionStatus:e=>e.transitionStatus,floatingRootContext:e=>e.floatingRootContext,triggerCount:e=>e.triggerCount,preventUnmountingOnClose:e=>e.preventUnmountingOnClose,payload:e=>e.payload,activeTriggerId:hf,activeTriggerElement:e=>e.mounted?e.activeTriggerElement:null,popupId:UT,isTriggerActive:(e,t)=>t!==void 0&&hf(e)===t,isOpenedByTrigger:(e,t)=>VT(e,t),isMountedByTrigger:(e,t)=>t!==void 0&&hf(e)===t&&e.mounted,triggerProps:(e,t)=>t?e.activeTriggerProps:e.inactiveTriggerProps,triggerPopupId:(e,t)=>CU(e,t)?UT(e):void 0,popupProps:e=>e.popupProps,popupElement:e=>e.popupElement,positionerElement:e=>e.positionerElement};function FT(e){const t=x.useCallback(o=>e===void 0?Kt:e.subscribeStore(o),[e]),a=x.useCallback(()=>e===void 0?void 0:e.store,[e]);return Ey.useSyncExternalStore(t,a,()=>e?.serverStore)}function $T(e){const{open:t=!1,onOpenChange:a,elements:o={}}=e,c=Jd(),d=au()!=null,f=Ps(()=>new Oy({open:t,transitionStatus:void 0,onOpenChange:a,referenceElement:o.reference??null,floatingElement:o.floating??null,triggerElements:new vh,floatingId:c,syncOnly:!1,nested:d})).current;return Me(()=>{const p={open:t,floatingId:c};o.reference!==void 0&&(p.referenceElement=o.reference,p.domReferenceElement=Rt(o.reference)?o.reference:null),o.floating!==void 0&&(p.floatingElement=o.floating),f.update(p)},[t,c,o.reference,o.floating,f]),f.context.onOpenChange=a,f.context.nested=d,f}function TU(e){return EU(e,e.rootContext)}function EU(e,t){const{nodeId:a,externalTree:o}=e,c=t.useState("referenceElement"),d=t.useState("floatingElement"),f=t.useState("domReferenceElement"),p=t.useState("open"),h=t.useState("floatingId"),[b,y]=x.useState(null),[v,j]=x.useState(void 0),[w,S]=x.useState(void 0),N=x.useRef(null),k=Bi(o),A=x.useMemo(()=>({reference:c,floating:d,domReference:f}),[c,d,f]),P=oU({...e,elements:{...A,...b&&{reference:b}}}),R=Rt(v)?v:null,C=w===void 0?t.state.floatingElement:w;t.useSyncedValue("referenceElement",v??null),t.useSyncedValue("domReferenceElement",v===void 0?f:R),t.useSyncedValue("floatingElement",C);const E=x.useCallback(H=>{const B=Rt(H)?{getBoundingClientRect:()=>H.getBoundingClientRect(),getClientRects:()=>H.getClientRects(),contextElement:H}:H;y(B),P.refs.setReference(B)},[P.refs]),D=x.useCallback(H=>{(Rt(H)||H===null)&&(N.current=H,j(H)),(Rt(P.refs.reference.current)||P.refs.reference.current===null||H!==null&&!Rt(H))&&P.refs.setReference(H)},[P.refs,j]),I=x.useCallback(H=>{S(H),P.refs.setFloating(H)},[P.refs]),O=x.useMemo(()=>({...P.refs,setReference:D,setFloating:I,setPositionReference:E,domReference:N}),[P.refs,D,I,E]),_=x.useMemo(()=>({...P.elements,domReference:f}),[P.elements,f]),z=x.useMemo(()=>({...P,dataRef:t.context.dataRef,open:p,onOpenChange:t.setOpen,events:t.context.events,floatingId:h,refs:O,elements:_,nodeId:a,rootStore:t}),[P,O,_,a,t,p,h]);return Me(()=>{f&&(N.current=f)},[f]),Me(()=>{t.context.dataRef.current.floatingContext=z;const H=k?.nodesRef.current.find(B=>B.id===a);H&&(H.context=z)}),x.useMemo(()=>({...P,context:z,refs:O,elements:_,rootStore:t}),[P,O,_,z,t])}const Uy=i1&&jl;function AU(e,t={}){const{enabled:a=!0,delay:o}=t,c="rootStore"in e?e.rootStore:e,{events:d,dataRef:f}=c.context,p=x.useRef(!1),h=x.useRef(null),b=x.useRef(!0),y=er();x.useEffect(()=>{const j=c.select("domReferenceElement");if(!a)return;const w=Cn(j);function S(){const A=c.select("domReferenceElement");!c.select("open")&&pn(A)&&A===ir(Gt(A))&&(p.current=!0,h.current=A)}function N(){b.current=!0}function k(){b.current=!1}return Xa(St(w,"blur",S),Uy&&St(w,"keydown",N,!0),Uy&&St(w,"pointerdown",k,!0))},[c,a]),x.useEffect(()=>{if(!a)return;function j(w){if(w.reason===go||w.reason===nu){const S=c.select("domReferenceElement");Rt(S)&&(h.current=S,p.current=!0)}}return d.on("openchange",j),()=>{d.off("openchange",j)}},[d,a,c]);const v=x.useMemo(()=>{function j(){p.current=!1,h.current=null}return{onMouseLeave(){j()},onFocus(w){const S=w.currentTarget;if(p.current){if(h.current===S)return;j()}const N=fs(w.nativeEvent);if(Rt(N)){if(Uy&&!w.relatedTarget){if(!b.current&&!Zm(N))return}else if(!ZB(N))return}const k=Qm(w.relatedTarget,c.context.triggerElements),{nativeEvent:A,currentTarget:P}=w,R=typeof o=="function"?o():o;if(c.select("open")&&k||R===0||R===void 0){c.setOpen(!0,qe(ih,A,P));return}y.start(R,()=>{p.current||c.setOpen(!0,qe(ih,A,P))})},onBlur(w){j();const S=w.relatedTarget,N=w.nativeEvent,k=Rt(S)&&S.hasAttribute(df("focus-guard"))&&S.getAttribute("data-type")==="outside";y.start(0,()=>{const A=c.select("domReferenceElement"),P=ir(Gt(A));!S&&P===A||Ze(f.current.floatingContext?.refs.floating.current,P)||Ze(A,P)||k||Qm(S??P,c.context.triggerElements)||c.setOpen(!1,qe(ih,N))})}}},[f,o,c,y]);return x.useMemo(()=>a?{reference:v,trigger:v}:{},[a,v])}class Vy{constructor(){cn(this,"dispose",()=>{this.openChangeTimeout.clear(),this.restTimeout.clear()});cn(this,"disposeEffect",()=>this.dispose);this.pointerType=void 0,this.interactedInside=!1,this.handler=void 0,this.blockMouseMove=!0,this.performedPointerEventsMutation=!1,this.pointerEventsScopeElement=null,this.pointerEventsReferenceElement=null,this.pointerEventsFloatingElement=null,this.restTimeoutPending=!1,this.openChangeTimeout=new la,this.restTimeout=new la,this.handleCloseOptions=void 0}static create(){return new Vy}}const yh=new WeakMap;function jh(e){if(!e.performedPointerEventsMutation)return;const t=e.pointerEventsScopeElement;t&&yh.get(t)===e&&(e.pointerEventsScopeElement?.style.removeProperty("pointer-events"),e.pointerEventsReferenceElement?.style.removeProperty("pointer-events"),e.pointerEventsFloatingElement?.style.removeProperty("pointer-events"),yh.delete(t)),e.performedPointerEventsMutation=!1,e.pointerEventsScopeElement=null,e.pointerEventsReferenceElement=null,e.pointerEventsFloatingElement=null}function qT(e,t){const{scopeElement:a,referenceElement:o,floatingElement:c}=t,d=yh.get(a);d&&d!==e&&jh(d),jh(e),e.performedPointerEventsMutation=!0,e.pointerEventsScopeElement=a,e.pointerEventsReferenceElement=o,e.pointerEventsFloatingElement=c,yh.set(a,e),a.style.pointerEvents="none",o.style.pointerEvents="auto",c.style.pointerEvents="auto"}function Fy(e){const t=e.context.dataRef.current,a=Ps(()=>t.hoverInteractionState??Vy.create()).current;return t.hoverInteractionState||(t.hoverInteractionState=a),cy(t.hoverInteractionState.disposeEffect),t.hoverInteractionState}function GT(e,t={}){const{enabled:a=!0,closeDelay:o=0,nodeId:c}=t,d="rootStore"in e?e.rootStore:e,f=d.useState("open"),p=d.useState("floatingElement"),h=d.useState("domReferenceElement"),{dataRef:b}=d.context,y=Bi(),v=au(),j=Fy(d),w=er(),S=Ie(()=>X1(b.current.openEvent?.type,j.interactedInside)),N=Ie(()=>iH(b.current.openEvent?.type)),k=Ie(()=>{jh(j)});Me(()=>{f||(j.pointerType=void 0,j.restTimeoutPending=!1,j.interactedInside=!1,k())},[f,j,k]),x.useEffect(()=>k,[k]),Me(()=>{if(a&&f&&j.handleCloseOptions?.blockPointerEvents&&N()&&Rt(h)&&p){const A=h,P=p,R=Gt(p),C=y?.nodesRef.current.find(O=>O.id===v)?.context?.elements.floating;C&&(C.style.pointerEvents="");const E=j.pointerEventsScopeElement!==P?j.pointerEventsScopeElement:null,D=C!==P?C:null,I=j.handleCloseOptions?.getScope?.()??E??D??A.closest("[data-rootownerid]")??R.body;return qT(j,{scopeElement:I,referenceElement:A,floatingElement:P}),()=>{k()}}},[a,f,h,p,j,N,y,v,k]),x.useEffect(()=>{if(!a)return;function A(){return!!(y&&v&&uo(y.nodesRef.current,v).length>0)}function P(O){const _=zi(o,"close",j.pointerType),z=()=>{d.setOpen(!1,qe(qs,O)),y?.events.emit("floating.closed",O)};_?j.openChangeTimeout.start(_,z):(j.openChangeTimeout.clear(),z())}function R(O){const _=fs(O);if(!QB(_)){j.interactedInside=!1;return}j.interactedInside=_?.closest("[aria-haspopup]")!=null}function C(){j.openChangeTimeout.clear(),w.clear(),y?.events.off("floating.closed",D),k()}function E(O){if(A()&&y){y.events.on("floating.closed",D);return}if(Qm(O.relatedTarget,d.context.triggerElements))return;const _=b.current.floatingContext?.nodeId??c,z=O.relatedTarget;if(!(y&&_&&Rt(z)&&uo(y.nodesRef.current,_,!1).some(B=>Ze(B.context?.elements.floating,z)))){if(j.handler){j.handler(O);return}k(),N()&&!S()&&P(O)}}function D(O){!y||!v||A()||w.start(0,()=>{y.events.off("floating.closed",D),d.setOpen(!1,qe(qs,O)),y.events.emit("floating.closed",O)})}const I=p;return Xa(I&&St(I,"mouseenter",C),I&&St(I,"mouseleave",E),I&&St(I,"pointerdown",R,!0),()=>{y?.events.off("floating.closed",D)})},[a,p,d,b,o,c,N,S,k,j,y,v,w])}const RU={current:null};function KT(e,t={}){const{enabled:a=!0,delay:o=0,handleClose:c=null,mouseOnly:d=!1,restMs:f=0,move:p=!0,triggerElementRef:h=RU,externalTree:b,isActiveTrigger:y=!0,getHandleCloseContext:v,isClosing:j,shouldOpen:w,guardStaleOpen:S=!1}=t,N="rootStore"in e?e.rootStore:e,{dataRef:k,events:A}=N.context,P=Bi(b),R=Fy(N),C=x.useRef(!1),E=Zn(c),D=Zn(o),I=Zn(f),O=Zn(a),_=Zn(w),z=Zn(j),H=Ie(()=>X1(k.current.openEvent?.type,R.interactedInside)),B=Ie(()=>_.current?.()!==!1),L=Ie((X,K,q)=>{const Q=N.context.triggerElements;if(Q.hasElement(K))return!X||!Ze(X,K);if(!Rt(q))return!1;const G=q;return Q.hasMatchingElement(J=>Ze(J,G))&&(!X||!Ze(X,G))}),F=Ie(()=>{if(!R.handler)return;Gt(N.select("domReferenceElement")).removeEventListener("mousemove",R.handler),R.handler=void 0}),$=Ie(()=>{jh(R)});return y&&(R.handleCloseOptions=c?.__options),x.useEffect(()=>F,[F]),x.useEffect(()=>{if(!a)return;function X(K){K.open?C.current=!1:(C.current=K.reason===qs,F(),R.openChangeTimeout.clear(),R.restTimeout.clear(),R.blockMouseMove=!0,R.restTimeoutPending=!1)}return A.on("openchange",X),()=>{A.off("openchange",X)}},[a,A,R,F]),x.useEffect(()=>{if(!a)return;function X(Y,re=!0){const M=zi(D.current,"close",R.pointerType);M?R.openChangeTimeout.start(M,()=>{N.setOpen(!1,qe(qs,Y)),P?.events.emit("floating.closed",Y)}):re&&(R.openChangeTimeout.clear(),N.setOpen(!1,qe(qs,Y)),P?.events.emit("floating.closed",Y))}const K=h.current??(y?N.select("domReferenceElement"):null);if(!Rt(K))return;function q(Y){if(R.openChangeTimeout.clear(),R.blockMouseMove=!1,d&&!fo(R.pointerType))return;const re=Y1(I.current),M=zi(D.current,"open",R.pointerType),U=fs(Y),Z=Y.currentTarget??null,ae=N.select("domReferenceElement");let ce=Z;if(Rt(U)&&!N.context.triggerElements.hasElement(U)){for(const de of N.context.triggerElements.elements())if(Ze(de,U)){ce=de;break}}Rt(Z)&&Rt(ae)&&!N.context.triggerElements.hasElement(Z)&&Ze(Z,ae)&&(ce=ae);const W=ce==null?!1:L(ae,ce,U),ue=N.select("open"),ve=z.current?.()??N.select("transitionStatus")==="ending",ee=!ue&&ve&&C.current,he=!W&&Rt(ce)&&Rt(ae)&&Ze(ae,ce)&&ee,te=re>0&&!M,ke=W&&(ue||ee)||he,le=!ue||W;if(ke){B()&&N.setOpen(!0,qe(qs,Y,ce));return}te||(M?R.openChangeTimeout.start(M,()=>{le&&B()&&N.setOpen(!0,qe(qs,Y,ce))}):le&&B()&&N.setOpen(!0,qe(qs,Y,ce)))}function Q(Y){if(H()){$();return}F();const re=N.select("domReferenceElement"),M=Gt(re);R.restTimeout.clear(),R.restTimeoutPending=!1;const U=k.current.floatingContext??v?.();if(Qm(Y.relatedTarget,N.context.triggerElements))return;if(E.current&&U){N.select("open")||R.openChangeTimeout.clear();const ae=h.current;R.handler=E.current({...U,tree:P,x:Y.clientX,y:Y.clientY,onClose(){$(),F(),O.current&&!H()&&ae===N.select("domReferenceElement")&&X(Y,!0)}}),M.addEventListener("mousemove",R.handler),R.handler(Y);return}(R.pointerType!=="touch"||!Ze(N.select("floatingElement"),Y.relatedTarget))&&X(Y)}function G(Y){Ze(K,Y.relatedTarget)||(R.openChangeTimeout.clear(),R.restTimeout.clear(),R.restTimeoutPending=!1)}const J=S?St(K,"mouseout",G):void 0;return p?Xa(St(K,"mousemove",q,{once:!0}),St(K,"mouseenter",q),St(K,"mouseleave",Q),J):Xa(St(K,"mouseenter",q),St(K,"mouseleave",Q),J)},[F,$,k,D,N,a,E,R,y,L,H,d,p,I,h,P,O,v,z,B,S]),x.useMemo(()=>{if(!a)return;function X(K){R.pointerType=K.pointerType}return{onPointerDown:X,onPointerEnter:X,onMouseMove(K){const{nativeEvent:q}=K,Q=K.currentTarget,G=N.select("domReferenceElement"),J=N.select("open"),Y=L(G,Q,K.target);if(d&&!fo(R.pointerType))return;if(J&&Y&&R.handleCloseOptions?.blockPointerEvents){const U=N.select("floatingElement");if(U){const Z=R.handleCloseOptions?.getScope?.()??Q.ownerDocument.body;qT(R,{scopeElement:Z,referenceElement:Q,floatingElement:U})}}const re=Y1(I.current);if(J&&!Y||re===0||!Y&&R.restTimeoutPending&&K.movementX**2+K.movementY**2<2)return;R.restTimeout.clear();function M(){if(R.restTimeoutPending=!1,H())return;const U=N.select("open");!R.blockMouseMove&&(!U||Y)&&B()&&N.setOpen(!0,qe(qs,q,Q))}R.pointerType==="touch"?Ts.flushSync(()=>{M()}):Y&&J?M():(R.restTimeoutPending=!0,R.restTimeout.start(re,M))}}},[a,R,H,L,d,N,I,B])}const OU="Escape";function YT(e){return jl&&e.movementX===0&&e.movementY===0}function wh(e,t,a){switch(e){case"vertical":return t;case"horizontal":return a;default:return t||a}}function Sh(e,t){return wh(t,e===Gv||e===Xm,e===Ei||e===Ai)}function $y(e,t,a){return wh(t,e===Xm,a?e===Ei:e===Ai)||e==="Enter"||e===" "||e===""}function MU(e,t,a){return wh(t,a?e===Ei:e===Ai,e===Xm)}function DU(e,t,a,o){const c=a?e===Ai:e===Ei,d=e===Gv;return t==="both"||t==="horizontal"&&o?e===OU:wh(t,c,d)}function XT(e,t){const{listRef:a,activeIndex:o,onNavigate:c=()=>{},enabled:d=!0,selectedIndex:f=null,allowEscape:p=!1,loopFocus:h=!1,nested:b=!1,rtl:y=!1,virtual:v=!1,focusItemOnOpen:j="auto",focusItemOnHover:w=!0,openOnArrowKeyDown:S=!0,disabledIndices:N=void 0,orientation:k="vertical",parentOrientation:A,id:P,resetOnPointerLeave:R=!0,externalTree:C,grid:E}=t,D=E!=null,I="rootStore"in e?e.rootStore:e,O=I.useState("open"),_=I.useState("floatingElement"),z=I.useState("domReferenceElement"),H=I.context.dataRef,B=Wm(_),L=Wv(z),F=Zn(B),$=au(),X=Bi(C),K=x.useRef(j),q=x.useRef(f??-1),Q=x.useRef(null),G=x.useRef(!0),J=Ie(pe=>{c(q.current===-1?null:q.current,pe)}),Y=x.useRef(!!_),re=x.useRef(O),M=x.useRef(!1),U=x.useRef(!1),Z=x.useRef(null),ae=Zn(N),ce=Zn(O),W=Zn(f),ue=Zn(R),ve=eu(),ee=eu(),he=Ie(()=>{function pe(De){v?X?.events.emit("virtualfocus",De):Z.current=fh(De,{sync:M.current,preventScroll:!0})}const Ce=a.current[q.current],Ne=U.current;Ce&&pe(Ce),(M.current?De=>De():De=>ve.request(De))(()=>{const De=a.current[q.current]||Ce;if(!De)return;Ce||pe(De),Te&&(Ne||!G.current)&&De.scrollIntoView?.({block:"nearest",inline:"nearest"})})});Me(()=>{H.current.orientation=k},[H,k]),Me(()=>{d&&(O&&_?(q.current=f??-1,K.current&&f!=null&&(U.current=!0,J())):Y.current&&(q.current=-1,J()))},[d,O,_,f,J]),Me(()=>{if(d){if(!O){M.current=!1;return}if(_)if(o==null){if(M.current=!1,W.current!=null)return;if(Y.current&&(q.current=-1,he()),(!re.current||!Y.current)&&K.current&&(Q.current!=null||K.current===!0&&Q.current==null)){let pe=0;const Ce=()=>{a.current[0]==null?(pe<2&&(pe?be=>ee.request(be):queueMicrotask)(Ce),pe+=1):(q.current=Q.current==null||$y(Q.current,k,y)||b?sh(a):ry(a),Q.current=null,J())};Ce()}}else mo(a.current,o)||(q.current=o,he(),U.current=!1)}},[d,O,_,o,W,b,a,k,y,J,he,ee]),Me(()=>{if(!d||_||!X||v||!Y.current)return;const pe=X.nodesRef.current,Ce=pe.find(De=>De.id===$)?.context?.elements.floating,Ne=ir(Gt(z??Ce??null)),be=pe.some(De=>De.context&&Ze(De.context.elements.floating,Ne));Ce&&!be&&G.current&&Ce.focus({preventScroll:!0})},[d,_,z,X,$,v]),Me(()=>{re.current=O,Y.current=!!_}),Me(()=>{O||(Q.current=null,K.current=j)},[O,j]);const te=o!=null,ke=Ie(pe=>{if(!ce.current)return;const Ce=a.current.indexOf(pe.currentTarget);Ce!==-1&&(q.current!==Ce||o!==Ce)&&(q.current=Ce,J(pe))}),le=Ie(()=>A??X?.nodesRef.current.find(pe=>pe.id===$)?.context?.dataRef?.current.orientation),de=Ie(()=>sh(a,ae.current)),Se=Ie(pe=>{if(G.current=!1,M.current=!0,pe.which===229||!ce.current&&pe.currentTarget===F.current)return;if(b&&DU(pe.key,k,y,D)){Sh(pe.key,le())||Cs(pe),I.setOpen(!1,qe(fy,pe.nativeEvent)),pn(z)&&(v?X?.events.emit("virtualfocus",z):z.focus());return}const Ce=q.current,Ne=sh(a,N),be=ry(a,N);if(L||(pe.key==="Home"&&(Cs(pe),q.current=Ne,J(pe)),pe.key==="End"&&(Cs(pe),q.current=be,J(pe))),E!=null){const De=E(pe,q.current,a,k,h,y,N,Ne,be);if(De!=null&&(q.current=De,J(pe)),k==="both")return}if(Sh(pe.key,k)){if(Cs(pe),O&&!v&&ir(pe.currentTarget.ownerDocument)===pe.currentTarget){q.current=$y(pe.key,k,y)?Ne:be,J(pe);return}$y(pe.key,k,y)?h?Ce>=be?p&&Ce!==a.current.length?q.current=-1:(M.current=!1,q.current=Ne):q.current=_s(a.current,{startingIndex:Ce,disabledIndices:N}):q.current=Math.min(be,_s(a.current,{startingIndex:Ce,disabledIndices:N})):h?Ce<=Ne?p&&Ce!==-1?q.current=a.current.length:(M.current=!1,q.current=be):q.current=_s(a.current,{startingIndex:Ce,decrement:!0,disabledIndices:N}):q.current=Math.max(Ne,_s(a.current,{startingIndex:Ce,decrement:!0,disabledIndices:N})),mo(a.current,q.current)&&(q.current=-1),J(pe)}}),Te=x.useMemo(()=>({onFocus(Ce){M.current=!0,ke(Ce)},onClick:({currentTarget:Ce})=>Ce.focus({preventScroll:!0}),onMouseMove(Ce){YT(Ce)||(M.current=!0,U.current=!1,w&&ke(Ce))},onPointerLeave(Ce){if(!ce.current||!G.current||Ce.pointerType==="touch")return;M.current=!0;const Ne=Ce.relatedTarget;if(!(!w||a.current.includes(Ne))&&ue.current&&(Z.current?.(),Z.current=null,q.current=-1,J(Ce),!v)){const be=F.current,De=ir(Gt(be));be&&Ze(be,De)&&be.focus({preventScroll:!0})}}}),[ke,ce,F,w,a,J,ue,v]),_e=x.useMemo(()=>v&&O&&te&&{"aria-activedescendant":`${P}-${o}`},[v,O,te,P,o]),Ae=x.useMemo(()=>({...L?{}:_e,onKeyDown(pe){if(pe.key==="Tab"&&pe.shiftKey&&O&&!v){const Ce=fs(pe.nativeEvent);if(Ce&&!Ze(F.current,Ce))return;Cs(pe),I.setOpen(!1,qe(xo,pe.nativeEvent)),pn(z)&&z.focus();return}Se(pe)},onPointerMove(pe){YT(pe)||(G.current=!0)}}),[_e,Se,F,L,I,O,v,z]),oe=x.useMemo(()=>{function pe(be){I.setOpen(!0,qe(fy,be.nativeEvent,be.currentTarget))}function Ce(be){j==="auto"&&Jm(be.nativeEvent)&&(K.current=!v)}function Ne(be){K.current=j,j==="auto"&&Jv(be.nativeEvent)&&(K.current=!0)}return{onKeyDown(be){const De=I.select("open");G.current=!1;const Ge=be.key.startsWith("Arrow"),Ct=MU(be.key,le(),y),Tt=Sh(be.key,k),Mt=(b?Ct:Tt)||be.key==="Enter"||be.key.trim()==="";if(v&&De)return Se(be);if(!(!De&&!S&&Ge)){if(Mt){const ot=Sh(be.key,le());Q.current=b&&ot?null:be.key}if(b){Ct&&(Cs(be),De?(q.current=de(),J(be)):pe(be));return}Tt&&(W.current!=null&&(q.current=W.current),Cs(be),!De&&S?pe(be):Se(be),De&&J(be))}},onFocus(be){I.select("open")&&!v&&(q.current=-1,J(be))},onPointerDown:Ne,onPointerEnter:Ne,onMouseDown:Ce,onClick:Ce}},[Se,j,de,b,J,I,S,k,le,y,W,v]),me=x.useMemo(()=>({..._e,...oe}),[_e,oe]);return x.useMemo(()=>d?{reference:me,floating:Ae,item:Te,trigger:oe}:{},[d,me,Ae,oe,Te])}function QT(e,t){const{listRef:a,elementsRef:o,activeIndex:c,onMatch:d,disabledIndices:f,onTyping:p,enabled:h=!0,resetMs:b=750,selectedIndex:y=null}=t,v="rootStore"in e?e.rootStore:e,j=v.useState("open"),w=er(),S=x.useRef(""),N=x.useRef(y??c??-1),k=x.useRef(null),A=Ie(C=>{function E(F){return o?.current[F]}function D(F){const $=E(F);return $&&!rh($)||$?.matches(":disabled")?!1:f==null||!ho(Ir,F,f)}function I(F,$,X=0){if(F.length===0)return-1;const K=(X%F.length+F.length)%F.length,q=$.toLowerCase();for(let Q=0;Q0&&C.key===" "&&(Cs(C),p?.(!0)),S.current.length>0&&S.current[0]!==" "&&I(O,S.current)===-1&&C.key!==" "&&p?.(!1),O==null||C.key.length!==1||C.ctrlKey||C.metaKey||C.altKey)return;j&&C.key!==" "&&(Cs(C),p?.(!0));const _=S.current==="";_&&(N.current=y??c??-1),O.every((F,$)=>F&&D($)?F[0]?.toLowerCase()!==F[1]?.toLowerCase():!0)&&S.current===C.key&&(S.current="",N.current=k.current),S.current+=C.key,w.start(b,()=>{S.current="",N.current=k.current,p?.(!1)});const B=((_?y??c??-1:N.current)??0)+1,L=I(O,S.current,B);L!==-1?(d?.(L),k.current=L):C.key!==" "&&(S.current="",p?.(!1))}),P=Ie(C=>{const E=C.relatedTarget,D=v.select("domReferenceElement"),I=v.select("floatingElement");Ze(D,E)||Ze(I,E)||(w.clear(),S.current="",N.current=k.current,p?.(!1))});Me(()=>{!j&&y!==null||(w.clear(),k.current=null,S.current!==""&&(S.current=""))},[j,y,w]);const R=x.useMemo(()=>({onKeyDown:A,onBlur:P}),[A,P]);return x.useMemo(()=>h?{reference:R,floating:R}:{},[h,R])}const ZT=.1,IU=ZT*ZT,yn=.5;function Nh(e,t,a,o,c,d){return o>=t!=d>=t&&e<=(c-a)*(t-o)/(d-o)+a}function kh(e,t,a,o,c,d,f,p,h,b){let y=!1;return Nh(e,t,a,o,c,d)&&(y=!y),Nh(e,t,c,d,f,p)&&(y=!y),Nh(e,t,f,p,h,b)&&(y=!y),Nh(e,t,h,b,a,o)&&(y=!y),y}function PU(e,t,a){return e>=a.x&&e<=a.x+a.width&&t>=a.y&&t<=a.y+a.height}function Ch(e,t,a,o,c,d){const f=Math.min(a,c),p=Math.max(a,c),h=Math.min(o,d),b=Math.max(o,d);return e>=f&&e<=p&&t>=h&&t<=b}function WT(e={}){const{blockPointerEvents:t=!1}=e,a=new la,o=({x:c,y:d,placement:f,elements:p,onClose:h,nodeId:b,tree:y})=>{const v=f?.split("-")[0];let j=!1,w=null,S=null,N=typeof performance<"u"?performance.now():0;function k(P,R){const C=performance.now(),E=C-N;if(w===null||S===null||E===0)return w=P,S=R,N=C,!1;const D=P-w,I=R-S,O=D*D+I*I,_=E*E*IU;return w=P,S=R,N=C,O<_}function A(){a.clear(),h()}return function(R){a.clear();const C=p.domReference,E=p.floating;if(!C||!E||v==null||c==null||d==null)return;const{clientX:D,clientY:I}=R,O=fs(R),_=R.type==="mouseleave",z=Ze(E,O),H=Ze(C,O);if(z&&(j=!0,!_))return;if(H&&(j=!1,!_)){j=!0;return}if(_&&Rt(R.relatedTarget)&&Ze(E,R.relatedTarget))return;function B(){return!!(y&&uo(y.nodesRef.current,b).length>0)}function L(){B()||A()}if(B())return;const F=C.getBoundingClientRect(),$=E.getBoundingClientRect(),X=c>$.right-$.width/2,K=d>$.bottom-$.height/2,q=$.width>F.width,Q=$.height>F.height,G=(q?F:$).left,J=(q?F:$).right,Y=(Q?F:$).top,re=(Q?F:$).bottom;if(v==="top"&&d>=F.bottom-1||v==="bottom"&&d<=F.top+1||v==="left"&&c>=F.right-1||v==="right"&&c<=F.left+1){L();return}let M=!1;switch(v){case"top":M=Ch(D,I,G,F.top+1,J,$.bottom-1);break;case"bottom":M=Ch(D,I,G,$.top+1,J,F.bottom-1);break;case"left":M=Ch(D,I,$.right-1,re,F.left+1,Y);break;case"right":M=Ch(D,I,F.right-1,re,$.left+1,Y);break}if(M)return;if(j&&!PU(D,I,F)){L();return}if(!_&&k(D,I)){L();return}let U=!1;switch(v){case"top":{const Z=q?yn/2:yn*4,ae=q||X?c+Z:c-Z,ce=q?c-Z:X?c+Z:c-Z,W=d+yn+1,ue=X||q?$.bottom-yn:$.top,ve=X?q?$.bottom-yn:$.top:$.bottom-yn;U=kh(D,I,ae,W,ce,W,$.left,ue,$.right,ve);break}case"bottom":{const Z=q?yn/2:yn*4,ae=q||X?c+Z:c-Z,ce=q?c-Z:X?c+Z:c-Z,W=d-yn,ue=X||q?$.top+yn:$.bottom,ve=X?q?$.top+yn:$.bottom:$.top+yn;U=kh(D,I,ae,W,ce,W,$.left,ue,$.right,ve);break}case"left":{const Z=Q?yn/2:yn*4,ae=Q||K?d+Z:d-Z,ce=Q?d-Z:K?d+Z:d-Z,W=c+yn+1,ue=K||Q?$.right-yn:$.left,ve=K?Q?$.right-yn:$.left:$.right-yn;U=kh(D,I,ue,$.top,ve,$.bottom,W,ae,W,ce);break}case"right":{const Z=Q?yn/2:yn*4,ae=Q||K?d+Z:d-Z,ce=Q?d-Z:K?d+Z:d-Z,W=c-yn,ue=K||Q?$.left+yn:$.right,ve=K?Q?$.left+yn:$.right:$.left+yn;U=kh(D,I,W,ae,W,ce,ue,$.top,ve,$.bottom);break}}U?j||a.start(40,L):L()}};return o.__options={...e,blockPointerEvents:t},o}const _U={...Hy,disabled:e=>e.disabled,instantType:e=>e.instantType,isInstantPhase:e=>e.isInstantPhase,trackCursorAxis:e=>e.trackCursorAxis,disableHoverablePopup:e=>e.disableHoverablePopup,lastOpenChangeReason:e=>e.openChangeReason,closeOnClick:e=>e.closeOnClick,closeDelay:e=>e.closeDelay,adaptiveOrigin:e=>e.adaptiveOrigin};class LU extends ou{constructor(a,o,c){const d=new vh;super(zU(a,d,o,c),BU(d),_U);cn(this,"setOpen",(a,o)=>{kU(this,a,o,{extraState:{openChangeReason:o.reason}})})}cancelPendingOpen(a){this.state.floatingRootContext.dispatchOpenChange(!1,qe(go,a))}}function zU(e,t,a,o=!1){return{...zy(t,a,o),disabled:!1,instantType:void 0,isInstantPhase:!1,trackCursorAxis:"none",disableHoverablePopup:!1,openChangeReason:null,closeOnClick:!0,closeDelay:0,adaptiveOrigin:void 0,...e}}function BU(e){return{popupRef:x.createRef(),onOpenChange:void 0,onOpenChangeComplete:void 0,triggerElements:e}}const HU=uh(function(t){const{disabled:a=!1,defaultOpen:o=!1,open:c,disableHoverablePopup:d=!1,trackCursorAxis:f="none",actionsRef:p,onOpenChange:h,onOpenChangeComplete:b,handle:y,triggerId:v,defaultTriggerId:j=null,children:w}=t,S=My((H,B)=>new LU({open:o,openProp:c,activeTriggerId:j,triggerIdProp:v},H,B));S.useControlledProp("openProp",c),S.useControlledProp("triggerIdProp",v),S.useContextCallback("onOpenChange",h),S.useContextCallback("onOpenChangeComplete",b);const N=S.useState("open"),k=!a&&N,A=S.useState("activeTriggerId"),P=S.useState("mounted"),R=S.useState("payload");S.useSyncedValues({trackCursorAxis:f,disableHoverablePopup:d,disabled:a}),Py(S,{closeOnActiveTriggerUnmount:!0});const{forceUnmount:C,transitionStatus:E}=_y(k,S),D=S.useState("isInstantPhase"),I=S.useState("instantType"),O=S.useState("lastOpenChangeReason"),_=x.useRef(null);Me(()=>{N&&a&&S.setOpen(!1,qe(N4))},[N,a,S]),Me(()=>{E==="ending"&&O===Qn||E!=="ending"&&D?(I!=="delay"&&(_.current=I),S.set("instantType","delay")):_.current!==null&&(S.set("instantType",_.current),_.current=null)},[E,D,O,I,S]),Me(()=>{k&&A==null&&S.set("payload",void 0)},[S,A,k]),x.useImperativeHandle(p,()=>({unmount:C,close:()=>S.setOpen(!1,qe(py))}),[C,S]);const z=k||P||!a&&f!=="none";return s.jsxs(K1.Provider,{value:S,children:[y&&s.jsx(Dy,{handle:y,store:S}),z&&s.jsx(UU,{store:S,disabled:a,trackCursorAxis:f}),typeof w=="function"?w({payload:R}):w]})});function UU({store:e,disabled:t,trackCursorAxis:a}){const o=e.useState("floatingRootContext"),c=pf(o,{enabled:!t,referencePress:()=>e.select("closeOnClick")}),d=CH(o,{enabled:!t&&a!=="none",axis:a==="none"?void 0:a}),f=x.useMemo(()=>ta(d.reference,c.reference),[d.reference,c.reference]);return Ly(e,{activeTriggerProps:f,inactiveTriggerProps:f,popupProps:c.floating??mn}),null}const JT=x.createContext(void 0);function VU(){return x.useContext(JT)}const FU=600,eE="data-base-ui-tooltip-trigger";function tE(e){if("composedPath"in e){const a=e.composedPath();for(let o=0;ok.select("transitionStatus")==="ending",shouldOpen(){return!G.current}}),ae=AU(C,{enabled:!X}).reference,ce=he=>{const te=G.current,ke=tE(he),le=U(ke),de=E.current,Se=de&&ke&&Ze(de,ke);if(le&&k.select("open")&&k.select("lastOpenChangeReason")===qs){k.setOpen(!1,qe(qs,he));return}if(te&&!le&&Se&&!K.current&&!k.select("open")&&de&&fo(Y.current)){const Te=()=>{!G.current&&!K.current&&!k.select("open")&&k.setOpen(!0,qe(qs,he,de))},_e=re();_e===0?(J.clear(),Te()):J.start(_e,Te)}},W=k.useState("triggerProps",O);return yt("button",t,{state:{open:R},ref:[a,I,E],props:[Z,ae,O||q!=="none"?W:void 0,{onMouseOver(he){ce(he.nativeEvent)},onFocus(he){M(tE(he.nativeEvent))&&he.preventBaseUIHandler()},onMouseLeave(){G.current=!1,J.clear(),Y.current=void 0},onPointerEnter(he){Y.current=he.pointerType},onPointerDown(he){Y.current=he.pointerType,k.set("closeOnClick",y),y&&!k.select("open")&&k.cancelPendingOpen(he.nativeEvent)},onClick(he){y&&!k.select("open")&&k.cancelPendingOpen(he.nativeEvent)},id:A,[Qv]:X?"":void 0,[eE]:X?void 0:""},w],stateAttributesMapping:Kv})}),nE=x.createContext(void 0);function GU(){const e=x.useContext(nE);if(e===void 0)throw new Error(un(70));return e}const KU=x.forwardRef(function(t,a){const{children:o,container:c,className:d,render:f,style:p,...h}=t,{node:b,subtree:y}=iT({container:c,ref:a,componentProps:t,elementProps:h});return!y&&!b?null:s.jsxs(x.Fragment,{children:[y,b&&Ts.createPortal(o,b)]})}),YU=x.forwardRef(function(t,a){const{keepMounted:o=!1,...c}=t;return uf().useState("mounted")||o?s.jsx(nE.Provider,{value:o,children:s.jsx(KU,{ref:a,...c})}):null}),sE=x.createContext(void 0);function rE(){const e=x.useContext(sE);if(e===void 0)throw new Error(un(71));return e}const XU=x.createContext(void 0);function gf(){return x.useContext(XU)?.direction??"ltr"}const QU=e=>({name:"arrow",options:e,async fn(t){const{x:a,y:o,placement:c,rects:d,platform:f,elements:p,middlewareData:h}=t,{element:b,padding:y=0,offsetParent:v="real"}=po(e,t)||{};if(b==null)return{};const j=x1(y),w={x:a,y:o},S=ny(c),N=ty(S),k=await f.getDimensions(b),A=S==="y",P=A?"top":"left",R=A?"bottom":"right",C=A?"clientHeight":"clientWidth",E=d.reference[N]+d.reference[S]-w[S]-d.floating[N],D=w[S]-d.reference[S],I=v==="real"?await f.getOffsetParent?.(b):p.floating;let O=p.floating[C]||d.floating[N];(!O||!await f.isElement?.(I))&&(O=p.floating[C]||d.floating[N]);const _=E/2-D/2,z=O/2-k[N]/2-1,H=Math.min(j[P],z),B=Math.min(j[R],z),L=H,F=O-k[N]-B,$=O/2-k[N]/2+_,X=m1(L,$,F),K=!h.arrow&&Nl(c)!=null&&$!==X&&d.reference[N]/2-(${const{name:a,fn:o}=QU(e);return{name:a,fn:o,options:[e,t]}},WU={name:"hide",async fn(e){const{width:t,height:a,x:o,y:c}=e.rects.reference,d=t===0&&a===0&&o===0&&c===0,f=await e.platform.detectOverflow(e,{elementContext:"reference"});return{data:{referenceHidden:f.top-a>=0||f.right-t>=0||f.bottom-a>=0||f.left-t>=0||d}}}},JU={sideX:"left",sideY:"top"},eV="--available-width",tV="--available-height",nV="--anchor-width",sV="--anchor-height",rV="--transform-origin",aE=eV,lE=tV;function oE(e,t,a){const o=e==="inline-start"||e==="inline-end";return{top:"top",right:o?a?"inline-start":"inline-end":"right",bottom:"bottom",left:o?a?"inline-end":"inline-start":"left"}[t]}function iE(e,t,a){const{rects:o,placement:c}=e;return{side:oE(t,ra(c),a),align:Nl(c)||"center",anchor:{width:o.reference.width,height:o.reference.height},positioner:{width:o.floating.width,height:o.floating.height}}}function Th(e){return aV(e,TU)}function aV(e,t){const{anchor:a,positionMethod:o="absolute",side:c="bottom",sideOffset:d=0,align:f="center",alignOffset:p=0,collisionBoundary:h,collisionPadding:b=5,sticky:y=!1,arrowPadding:v=5,disableAnchorTracking:j=!1,inline:w,keepMounted:S=!1,floatingRootContext:N,mounted:k,collisionAvoidance:A,shift:P,nodeId:R,adaptiveOrigin:C,lazyFlip:E=!1,externalTree:D}=e,[I,O]=x.useState(null);!k&&I!==null&&O(null);const _=A.side||"flip",z=A.align||"flip",H=A.fallbackAxisSide||"end",B=P?.crossAxis??!1,L=P?.rootBoundary,F=typeof a=="function"?a:void 0,$=Ie(F),X=F?$:a,K=Zn(a),q=Zn(k),G=gf()==="rtl",J=I||{top:"top",right:"right",bottom:"bottom",left:"left","inline-end":G?"left":"right","inline-start":G?"right":"left"}[c],Y=f==="center"?J:`${J}-${f}`;let re=b;typeof re=="number"?re={top:re,right:re,bottom:re,left:re}:re&&(re={top:re.top||0,right:re.right||0,bottom:re.bottom||0,left:re.left||0});const M=1,U=c==="bottom"?M:0,Z=c==="top"?M:0,ae=c==="right"?M:0,ce=c==="left"?M:0,W={boundary:h==="clipping-ancestors"?"clippingAncestors":h,padding:re},ue=x.useRef(null),ve=Zn(d),ee=Zn(p),he=typeof d!="function"?d:0,te=typeof p!="function"?p:0,ke=[];w&&ke.push(w),ke.push(iU(nt=>{const Dt=iE(nt,c,G),qt=typeof ve.current=="function"?ve.current(Dt):ve.current,es=typeof ee.current=="function"?ee.current(Dt):ee.current;return{mainAxis:qt,crossAxis:es,alignmentAxis:es}},[he,te,G,c]));const le=z==="none"&&_!=="shift",de=!le&&(y||B||_==="shift"),Se=_==="none"?null:dU({...W,padding:{top:re.top+M+U,right:re.right+M+ce,bottom:re.bottom+M+Z,left:re.left+M+ae},mainAxis:!B&&_==="flip",crossAxis:z==="flip"?"alignment":!1,fallbackAxisSideDirection:H}),Te=le?null:cU({...W,rootBoundary:L,mainAxis:z!=="none",crossAxis:de,limiter:y||B?void 0:uU(nt=>{if(!ue.current)return{};const{width:Dt,height:qt}=ue.current.getBoundingClientRect(),es=aa(ra(nt.placement)),Fn=es==="y"?Dt:qt,$n=es==="y"?re.left+re.right:re.top+re.bottom;return{offset:Fn/2+$n/2}})},[W,y,B,L,re,z]);_==="shift"||z==="shift"||f==="center"?ke.push(Te,Se):ke.push(Se,Te),ke.push(fU({...W,apply({elements:{floating:nt},availableWidth:Dt,availableHeight:qt,rects:es}){if(!q.current)return;const Fn=nt.style;Fn.setProperty(aE,`${Dt}px`),Fn.setProperty(lE,`${qt}px`);const $n=Cn(nt).devicePixelRatio||1,{x:Dn,y:en,width:cs,height:Et}=es.reference,xt=(Math.round((Dn+cs)*$n)-Math.round(Dn*$n))/$n,jt=(Math.round((en+Et)*$n)-Math.round(en*$n))/$n;Fn.setProperty(nV,`${xt}px`),Fn.setProperty(sV,`${jt}px`)}}),ZU(nt=>({element:ue.current||Gt(nt.elements.floating).createElement("div"),padding:ue.current?v:0,offsetParent:"floating"}),[v]),{name:"transformOrigin",fn(nt){const{elements:{floating:Dt},middlewareData:qt,placement:es,platform:Fn,rects:$n,y:Dn}=nt,en=ra(es),cs=Nl(es),Et=aa(en)==="y",xt=ue.current,jt=typeof d=="function"?d(iE(nt,c,G)):d;let wt;if(!xt&&cs&&Math.abs(Et?qt.shift?.x||0:qt.shift?.y||0)<=1)wt=cs==="start"===(Et&&Fn.isRTL?.(Dt)===!0)?"100%":"0%";else{const ar=Et?qt.arrow?.x||0:qt.arrow?.y||0,Fr=Et?xt?.clientWidth||0:xt?.clientHeight||0;wt=`${ar+Fr/2}px`}let Tr=en==="top"||en==="left"?`calc(100% + ${jt}px)`:`${-jt}px`;return de&&Et&&Math.abs(qt.shift?.y||0)>jt&&(Tr=`${$n.reference.y+$n.reference.height/2-Dn}px`),Dt.style.setProperty(rV,Et?`${wt} ${Tr}`:`${Tr} ${wt}`),{}}},WU,C),Me(()=>{!k&&N&&N.update({referenceElement:null,floatingElement:null,domReferenceElement:null,positionReference:null})},[k,N]);const _e=x.useMemo(()=>({ancestorScroll:!j,elementResize:!j&&typeof ResizeObserver<"u",layoutShift:!j&&typeof IntersectionObserver<"u"}),[j]),{refs:Ae,elements:oe,x:me,y:pe,middlewareData:Ce,update:Ne,placement:be,context:De,isPositioned:Ge,floatingStyles:Ct}=t({rootContext:N,open:S?k:void 0,placement:Y,middleware:ke,strategy:o,whileElementsMounted:S?void 0:(...nt)=>TT(...nt,_e),nodeId:R,externalTree:D}),{sideX:Tt,sideY:Mt}=Ce.adaptiveOrigin||JU,ot=Ge?o:"fixed",Kn=x.useMemo(()=>{let nt;return Ge?C?nt={position:ot,[Tt]:me,[Mt]:pe}:nt={...Ct,position:ot}:nt={position:ot,top:0,left:0},nt[aE]="100vw",nt[lE]="100vh",Ge||(nt.opacity=0),nt},[C,ot,Tt,me,Mt,pe,Ct,Ge]),ms=x.useRef(null);Me(()=>{if(!k)return;const nt=K.current,Dt=typeof nt=="function"?nt():nt,es=(cE(Dt)?Dt.current:Dt)||null||null;es!==ms.current&&(Ae.setPositionReference(es),ms.current=es)},[k,Ae,X,K]),x.useEffect(()=>{if(!k)return;const nt=K.current;typeof nt!="function"&&cE(nt)&&nt.current!==ms.current&&(Ae.setPositionReference(nt.current),ms.current=nt.current)},[k,Ae,X,K]),x.useEffect(()=>{if(S&&k&&oe.reference&&oe.floating)return TT(oe.reference,oe.floating,Ne,_e)},[S,k,oe,Ne,_e]);const Yn=ra(be),vs=oE(c,Yn,G),it=Nl(be)||"center",$t=!!Ce.hide?.referenceHidden;Me(()=>{E&&k&&Ge&&Yn!==J&&O(Yn)},[E,k,Ge,Yn,J]);const Vn=x.useMemo(()=>({position:"absolute",top:Ce.arrow?.y,left:Ce.arrow?.x}),[Ce.arrow]),rn=Ce.arrow?.centerOffset!==0;return x.useMemo(()=>({positionerStyles:Kn,arrowStyles:Vn,arrowRef:ue,arrowUncentered:rn,side:vs,align:it,physicalSide:Yn,anchorHidden:$t,refs:Ae,context:De,isPositioned:Ge,update:Ne}),[Kn,Vn,ue,rn,vs,it,Yn,$t,Ae,De,Ge,Ne])}function cE(e){return e!=null&&"current"in e}function xf(e){return e==="starting"?gH:mn}function Eh(e,t,{styles:a,transitionStatus:o,props:c,refs:d,hidden:f,inert:p=!1}){const h={...a};return p&&(h.pointerEvents="none"),yt("div",e,{state:t,ref:d,props:[{role:"presentation",hidden:f,style:h},xf(o),c],stateAttributesMapping:Zc})}const lV=x.forwardRef(function(t,a){const{render:o,className:c,anchor:d,positionMethod:f="absolute",side:p="top",align:h="center",sideOffset:b=0,alignOffset:y=0,collisionBoundary:v="clipping-ancestors",collisionPadding:j=5,arrowPadding:w=5,sticky:S=!1,disableAnchorTracking:N=!1,collisionAvoidance:k=aT,style:A,...P}=t,R=uf(),C=GU(),E=R.useState("open"),D=R.useState("mounted"),I=R.useState("trackCursorAxis"),O=R.useState("disableHoverablePopup"),_=R.useState("floatingRootContext"),z=R.useState("instantType"),H=R.useState("transitionStatus"),B=R.useState("adaptiveOrigin"),L=Th({anchor:d,positionMethod:f,floatingRootContext:_,mounted:D,side:p,sideOffset:b,align:h,alignOffset:y,collisionBoundary:v,collisionPadding:j,sticky:S,arrowPadding:w,disableAnchorTracking:N,keepMounted:C,collisionAvoidance:k,adaptiveOrigin:B}),F=x.useMemo(()=>({open:E,side:L.side,align:L.align,anchorHidden:L.anchorHidden,instant:I!=="none"?"tracking-cursor":z}),[E,L.side,L.align,L.anchorHidden,I,z]),$=Eh(t,F,{styles:L.positionerStyles,transitionStatus:H,props:P,refs:[a,R.useStateSetter("positionerElement")],hidden:!D,inert:!E||I==="both"||O});return s.jsx(sE.Provider,{value:L,children:$})}),oV=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,p=uf(),{side:h,align:b}=rE(),y=p.useState("open"),v=p.useState("instantType"),j=p.useState("transitionStatus"),w=p.useState("popupProps"),S=p.useState("floatingRootContext"),N=p.useState("disabled"),k=p.useState("closeDelay");oa({open:y,ref:p.context.popupRef,onComplete(){y&&p.context.onOpenChangeComplete?.(!0)}}),GT(S,{enabled:!N,closeDelay:k});const A=p.useStateSetter("popupElement");return yt("div",t,{state:{open:y,side:h,align:b,instant:v,transitionStatus:j},ref:[a,p.context.popupRef,A],props:[mf,w,xf(j),f],stateAttributesMapping:Xv})}),iV=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,p=uf(),{arrowRef:h,side:b,align:y,arrowUncentered:v,arrowStyles:j}=rE(),w=p.useState("open"),S=p.useState("instantType");return yt("div",t,{state:{open:w,side:b,align:y,uncentered:v,instant:S},ref:[a,h],props:[{style:j,"aria-hidden":!0},f],stateAttributesMapping:Zc})}),cV=function(t){const{delay:a,closeDelay:o,timeout:c=400}=t,d=x.useMemo(()=>({open:a,close:o}),[a,o]);return s.jsx(JT.Provider,{value:a,children:s.jsx(uH,{delay:d,timeoutMs:c,children:t.children})})};function Ah(e){return zv(19)?e:e?"true":void 0}function uV(e){const[t,a]=x.useState({current:e,previous:null});return Object.is(e,t.current)||a({current:e,previous:t.current}),t.previous}function dV(e){return s.jsx(cV,{"data-slot":"tooltip-provider",...e})}function Ui(e){return s.jsx(HU,{"data-slot":"tooltip",...e})}function Vi(e){return s.jsx(qU,{"data-slot":"tooltip-trigger",...e})}function Fi({className:e,sideOffset:t=8,side:a="top",children:o,...c}){return s.jsx(YU,{children:s.jsx(lV,{sideOffset:t,side:a,className:"z-[35]",children:s.jsx(oV,{"data-slot":"tooltip-content",className:Ue("max-w-[288px] rounded-md bg-primary px-2.5 py-2 text-[11.5px] leading-[1.55] text-primary-on shadow-3","break-words outline-none","transition-[opacity,transform] duration-150 ease-out","data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95","data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",e),...c,children:o})})})}function fV({className:e,...t}){return s.jsx(iV,{className:Ue("size-2 rotate-45 rounded-[1px] bg-primary","data-[side=top]:-bottom-1 data-[side=bottom]:-top-1",e),...t})}const uE=x.createContext(void 0);function iu(e){const t=x.useContext(uE);if(!e&&t===void 0)throw new Error(un(27));return t}const dE=x.forwardRef(function(t,a){const{render:o,className:c,style:d,forceRender:f=!1,...p}=t,h=iu(),b=h.useState("open"),y=h.useState("nested"),v=h.useState("mounted"),j=h.useState("transitionStatus");return yt("div",t,{state:{open:b,transitionStatus:j},ref:[h.context.backdropRef,a],stateAttributesMapping:Xv,props:[{role:"presentation",hidden:!v,style:{userSelect:"none",WebkitUserSelect:"none"}},p],enabled:f||!y})}),fE=x.forwardRef(function(t,a){const{render:o,className:c,style:d,disabled:f=!1,nativeButton:p=!0,...h}=t,b=iu(),y=b.useState("open"),{getButtonProps:v,buttonRef:j}=na({disabled:f,native:p}),w={disabled:f};function S(N){y&&b.setOpen(!1,qe(dy,N.nativeEvent))}return yt("button",t,{state:w,ref:[a,j],props:[{onClick:S},h,v]})}),pE=x.createContext(void 0);function pV(){const e=x.useContext(pE);if(e===void 0)throw new Error(un(26));return e}const qy="ArrowUp",Gy="ArrowDown",Ky="ArrowLeft",Yy="ArrowRight",Xy="Home",Qy="End",Rh=new Set([qy,Gy,Ky,Yy,Xy,Qy]),mE="Shift",mV=[mE,"Control","Alt","Meta"];function hV(e){return pn(e)&&e.tagName==="INPUT"}function hE(e){return!!(hV(e)&&e.selectionStart!=null||pn(e)&&e.tagName==="TEXTAREA")}function gE(e,t,a,o){if(!e||!t||!t.scrollTo)return;let c=e.scrollLeft,d=e.scrollTop;const f=e.clientWidthe.scrollLeft+e.clientWidth-b.scrollPaddingRight?c=h+t.offsetWidth+y.scrollMarginRight-e.clientWidth+b.scrollPaddingRight:h-y.scrollMarginLefte.scrollLeft+e.clientWidth-b.scrollPaddingRight&&(c=h+t.offsetWidth+y.scrollMarginRight-e.clientWidth+b.scrollPaddingRight))}if(p&&o!=="horizontal"){const h=xE(e,t,"top"),b=Oh(e),y=Oh(t);h-y.scrollMarginTope.scrollTop+e.clientHeight-b.scrollPaddingBottom&&(d=h+t.offsetHeight+y.scrollMarginBottom-e.clientHeight+b.scrollPaddingBottom)}e.scrollTo({left:c,top:d,behavior:"auto"})}function xE(e,t,a){const o=a==="left"?"offsetLeft":"offsetTop";let c=0;for(;t.offsetParent&&(c+=t[o],t.offsetParent!==e);)t=t.offsetParent;return c}function Oh(e){const t=getComputedStyle(e);return{scrollMarginTop:parseFloat(t.scrollMarginTop)||0,scrollMarginRight:parseFloat(t.scrollMarginRight)||0,scrollMarginBottom:parseFloat(t.scrollMarginBottom)||0,scrollMarginLeft:parseFloat(t.scrollMarginLeft)||0,scrollPaddingTop:parseFloat(t.scrollPaddingTop)||0,scrollPaddingRight:parseFloat(t.scrollPaddingRight)||0,scrollPaddingBottom:parseFloat(t.scrollPaddingBottom)||0,scrollPaddingLeft:parseFloat(t.scrollPaddingLeft)||0}}const gV="--nested-dialogs",xV="data-nested-dialog-open",bV={...Zc,...co,nestedDialogOpen(e){return e?{[xV]:""}:null}},bE=x.forwardRef(function(t,a){const{render:o,className:c,style:d,finalFocus:f,initialFocus:p,...h}=t,b=iu(),y=b.useState("descriptionElementId"),v=b.useState("disablePointerDismissal"),j=b.useState("floatingRootContext"),w=b.useState("popupProps"),S=b.useState("modal"),N=b.useState("mounted"),k=b.useState("nested"),A=b.useState("nestedOpenDialogCount"),P=b.useState("open"),R=b.useState("openMethod"),C=b.useState("titleElementId"),E=b.useState("transitionStatus"),D=b.useState("role"),I=j.useState("floatingId");pV(),oa({open:P,ref:b.context.popupRef,onComplete(){P&&b.context.onOpenChangeComplete?.(!0)}});const O=p===void 0?_T(b.context.popupRef):p,_=A>0,z=b.useStateSetter("popupElement"),B=yt("div",t,{state:{open:P,nested:k,transitionStatus:E,nestedDialogOpen:_},props:[w,{id:I,"aria-labelledby":C,"aria-describedby":y,role:D,...mf,hidden:!N,onKeyDown(L){Rh.has(L.key)&&L.stopPropagation()},style:{[gV]:A}},h],ref:[a,b.context.popupRef,z],stateAttributesMapping:bV});return s.jsx(mh,{context:j,openInteractionType:R,disabled:!N,closeOnFocusOut:!v,initialFocus:O,returnFocus:f,modal:S!==!1,restoreFocus:"popup",children:B})}),Mh=x.forwardRef(function(t,a){const{cutout:o,...c}=t;let d;if(o){const f=o.getBoundingClientRect();d=`polygon(0% 0%,100% 0%,100% 100%,0% 100%,0% 0%,${f.left}px ${f.top}px,${f.left}px ${f.bottom}px,${f.right}px ${f.bottom}px,${f.right}px ${f.top}px,${f.left}px ${f.top}px)`}return s.jsx("div",{ref:a,role:"presentation","data-base-ui-inert":"",...c,style:{position:"fixed",inset:0,userSelect:"none",WebkitUserSelect:"none",clipPath:d}})}),vE=x.forwardRef(function(t,a){const{keepMounted:o=!1,...c}=t,d=iu(),f=d.useState("mounted"),p=d.useState("modal"),h=d.useState("open");return f||o?s.jsx(pE.Provider,{value:o,children:s.jsxs(ph,{ref:a,...c,children:[f&&p===!0&&s.jsx(Mh,{ref:d.context.internalBackdropRef,inert:Ah(!h)}),t.children]})}):null});let yE={},jE={},wE="";function Dh(e,t){return Qd(e)?e:t}function SE(e,t,a){return/hidden|clip/.test(e.getComputedStyle(Dh(t,a)).overflowY)}function vV(e){if(typeof document>"u")return!1;const t=Gt(e);return Cn(t).innerWidth-t.documentElement.clientWidth>0}function yV(e){if(!(typeof CSS<"u"&&CSS.supports&&CSS.supports("scrollbar-gutter","stable"))||typeof document>"u")return!1;const a=Gt(e),o=a.documentElement,c=a.body,d=Dh(o,c),f=d.style.overflowY,p=o.style.scrollbarGutter;o.style.scrollbarGutter="stable",d.style.overflowY="scroll";const h=d.offsetWidth;d.style.overflowY="hidden";const b=d.offsetWidth;return d.style.overflowY=f,o.style.scrollbarGutter=p,h===b}function jV(e){const t=Gt(e),a=t.documentElement,o=t.body,c=Dh(a,o),d={overflowY:c.style.overflowY,overflowX:c.style.overflowX};return Object.assign(c.style,{overflowY:"hidden",overflowX:"hidden"}),()=>{Object.assign(c.style,d)}}function wV(e){const t=Gt(e),a=t.documentElement,o=t.body,c=Cn(a);let d=0,f=0,p=!1;const h=Ga.create();if(jl&&(c.visualViewport?.scale??1)!==1)return()=>{};function b(){const w=c.getComputedStyle(a),S=c.getComputedStyle(o),A=(w.scrollbarGutter||"").includes("both-edges")?"stable both-edges":"stable";d=a.scrollTop,f=a.scrollLeft,yE={scrollbarGutter:a.style.scrollbarGutter,overflowY:a.style.overflowY,overflowX:a.style.overflowX},wE=a.style.scrollBehavior,jE={position:o.style.position,height:o.style.height,width:o.style.width,boxSizing:o.style.boxSizing,overflowY:o.style.overflowY,overflowX:o.style.overflowX,scrollBehavior:o.style.scrollBehavior};const P=a.scrollHeight>a.clientHeight,R=a.scrollWidth>a.clientWidth,C=w.overflowY==="scroll"||S.overflowY==="scroll",E=w.overflowX==="scroll"||S.overflowX==="scroll",D=Math.max(0,c.innerWidth-o.clientWidth),I=Math.max(0,c.innerHeight-o.clientHeight),O=parseFloat(S.marginTop)+parseFloat(S.marginBottom),_=parseFloat(S.marginLeft)+parseFloat(S.marginRight),z=Dh(a,o);if(p=yV(e),p){a.style.scrollbarGutter=A,z.style.overflowY="hidden",z.style.overflowX="hidden";return}Object.assign(a.style,{scrollbarGutter:A,overflowY:"hidden",overflowX:"hidden"}),(P||C)&&(a.style.overflowY="scroll"),(R||E)&&(a.style.overflowX="scroll"),Object.assign(o.style,{position:"relative",height:O||I?`calc(100dvh - ${O+I}px)`:"100dvh",width:_||D?`calc(100vw - ${_+D}px)`:"100vw",boxSizing:"border-box",overflowY:"hidden",overflowX:"hidden",scrollBehavior:"unset"}),o.scrollTop=d,o.scrollLeft=f,a.setAttribute("data-base-ui-scroll-locked",""),a.style.scrollBehavior="unset"}function y(){Object.assign(a.style,yE),Object.assign(o.style,jE),p||(a.scrollTop=d,a.scrollLeft=f,a.removeAttribute("data-base-ui-scroll-locked"),a.style.scrollBehavior=wE)}function v(){y(),h.request(b)}b();const j=St(c,"resize",v);return()=>{h.cancel(),y(),typeof c.removeEventListener=="function"&&j()}}class SV{constructor(){cn(this,"lockCount",0);cn(this,"restore",null);cn(this,"timeoutLock",la.create());cn(this,"timeoutUnlock",la.create());cn(this,"release",()=>{this.lockCount-=1,this.lockCount===0&&this.restore&&this.timeoutUnlock.start(0,this.unlock)});cn(this,"unlock",()=>{this.lockCount===0&&this.restore&&(this.restore?.(),this.restore=null)})}acquire(t){return this.lockCount+=1,this.lockCount===1&&this.restore===null&&this.timeoutLock.start(0,()=>this.lock(t)),this.release}lock(t){if(this.lockCount===0||this.restore!==null)return;const a=Gt(t),o=a.documentElement,c=a.body,d=Cn(o);if(SE(d,o,c)){const p=new d.MutationObserver(()=>{SE(d,o,c)||(p.disconnect(),this.restore=null,this.lock(t))}),h={attributes:!0};p.observe(o,h),p.observe(c,h),this.restore=()=>p.disconnect();return}const f=tf||!vV(t);this.restore=f?jV(t):wV(t)}}const NV=new SV;function NE(e=!0,t=null){Me(()=>{if(e)return NV.acquire(t)},[e,t])}function kV({store:e,parentContext:t,isDrawer:a}){const o=e.useState("open"),c=e.useState("disablePointerDismissal"),d=e.useState("modal"),f=e.useState("popupElement"),p=e.useState("floatingRootContext"),[h,b]=x.useState(0),[y,v]=x.useState(0),j=h===0,w=pf(p,{outsidePressEvent(){return e.context.internalBackdropRef.current||e.context.backdropRef.current?"intentional":{mouse:d==="trap-focus"?"sloppy":"intentional",touch:"sloppy"}},outsidePress(S){if(!e.context.outsidePressEnabledRef.current||"button"in S&&S.button!==0)return!1;if("touches"in S){if(S.type==="touchend"){if(S.changedTouches.length!==1||S.touches.length!==0)return!1}else if(S.touches.length!==1)return!1}const N=fs(S);if(j&&!c){if(d){const k=e.context.internalBackdropRef.current,A=e.context.backdropRef.current;return k||A?k===N||A===N||Ze(N,f)&&!N?.hasAttribute("data-base-ui-portal"):!0}return!0}return!1},escapeKey:j});return NE(o&&d===!0,f),e.useContextCallback("onNestedDialogOpen",(S,N)=>{b(S),v(N)}),Me(()=>(t?.onNestedDialogOpen&&(o?t.onNestedDialogOpen(h+1,y+(a?1:0)):t.onNestedDialogOpen(0,0)),()=>{t?.onNestedDialogOpen&&o&&t.onNestedDialogOpen(0,0)}),[a,o,h,y,t]),Ly(e,{activeTriggerProps:w.reference,inactiveTriggerProps:w.trigger,popupProps:w.floating,nestedOpenDialogCount:h,nestedOpenDrawerCount:y}),null}const CV={...Hy,modal:e=>e.modal,nested:e=>e.nested,nestedOpenDialogCount:e=>e.nestedOpenDialogCount,nestedOpenDrawerCount:e=>e.nestedOpenDrawerCount,disablePointerDismissal:e=>e.disablePointerDismissal,openMethod:e=>e.openMethod,descriptionElementId:e=>e.descriptionElementId,titleElementId:e=>e.titleElementId,viewportElement:e=>e.viewportElement,role:e=>e.role};class TV extends ou{constructor(a,o,c){const d=new vh,f=EV(a,d,o,c);super(f,AV(d),CV);cn(this,"setOpen",(a,o)=>{o.preventUnmountOnClose=()=>{this.set("preventUnmountingOnClose",!0)},!a&&o.trigger==null&&this.state.activeTriggerId!=null&&(o.trigger=this.state.activeTriggerElement??void 0),this.context.onOpenChange?.(a,o),!o.isCanceled&&(this.state.floatingRootContext.dispatchOpenChange(a,o),this.update(Iy(this.state,a,o.trigger)))})}}function EV(e,t,a,o=!1){return{...zy(t,a,o),modal:!0,disablePointerDismissal:!1,viewportElement:null,descriptionElementId:void 0,titleElementId:void 0,openMethod:null,nested:!1,nestedOpenDialogCount:0,nestedOpenDrawerCount:0,role:"dialog",...e}}function AV(e){return{popupRef:x.createRef(),backdropRef:x.createRef(),internalBackdropRef:x.createRef(),outsidePressEnabledRef:{current:!0},triggerElements:e,onOpenChange:void 0,onOpenChangeComplete:void 0}}function kE(e,t){const{children:a,open:o,defaultOpen:c=!1,onOpenChange:d,onOpenChangeComplete:f,disablePointerDismissal:p=!1,modal:h=!0,actionsRef:b,handle:y,triggerId:v,defaultTriggerId:j=null}=t,w=e==="drawer",S=e==="alert-dialog",N=S?!0:h,k=S||p,A=S?"alertdialog":"dialog",P=iu(!0),R=P!=null,C={modal:N,disablePointerDismissal:k,nested:R,role:A},E=My((H,B)=>new TV({open:c,openProp:o,activeTriggerId:j,triggerIdProp:v,...C},H,B),!0);E.useControlledProp("openProp",o),E.useControlledProp("triggerIdProp",v),E.useSyncedValues(C),E.useContextCallback("onOpenChange",d),E.useContextCallback("onOpenChangeComplete",f);const D=E.useState("open"),I=E.useState("mounted"),O=E.useState("payload");HT(E,D),Py(E);const{forceUnmount:_}=_y(D,E);x.useImperativeHandle(b,()=>({unmount:_,close:()=>E.setOpen(!1,qe(py))}),[_,E]);const z=D||I;return s.jsxs(uE.Provider,{value:E,children:[y&&s.jsx(Dy,{handle:y,store:E}),z&&s.jsx(kV,{store:E,parentContext:P?.context,isDrawer:w}),typeof a=="function"?a({payload:O}):a]})}const RV=uh(function(t){return kE("dialog",t)}),CE=x.forwardRef(function(t,a){const{render:o,className:c,style:d,id:f,...p}=t,h=iu(),b=ka(f);return h.useSyncedValueWithCleanup("titleElementId",b),yt("h2",t,{ref:a,props:[{id:b},p]})});function OV(e){const t=x.useRef(""),a=x.useCallback(c=>{c.defaultPrevented||(t.current=c.pointerType,e(c,c.pointerType))},[e]);return{onClick:x.useCallback(c=>{if(c.detail===0){e(c,"keyboard");return}"pointerType"in c?e(c,c.pointerType):e(c,t.current),t.current=""},[e]),onPointerDown:a}}function TE(e,t){const a=Ie((d,f)=>{(typeof e=="function"?e():e)||t(f||(tf?"touch":""))}),{onClick:o,onPointerDown:c}=OV(a);return x.useMemo(()=>({onClick:o,onPointerDown:c}),[o,c])}function EE(e){const[t,a]=x.useState(null),o=TE(e,a);return ia(e,c=>{c&&!e&&a(null)}),x.useMemo(()=>({openMethod:t,triggerProps:o}),[t,o])}function Yt(e){return s.jsx(RV,{"data-slot":"dialog",...e})}function MV(e){return s.jsx(vE,{"data-slot":"dialog-portal",...e})}const Ut=e=>s.jsx(CE,{"data-slot":"dialog-title",...e});function DV({className:e,...t}){return s.jsx(dE,{"data-slot":"dialog-overlay",className:Ue("fixed inset-0 isolate z-30 bg-mask backdrop-blur-[3px]","transition-opacity duration-150","data-open:animate-in data-open:fade-in-0","data-closed:animate-out data-closed:fade-out-0 data-closed:fill-mode-forwards",e),...t})}function Xt({className:e,children:t,showCloseButton:a=!0,keepMounted:o=!1,overlayForceRender:c=!1,...d}){return s.jsxs(MV,{keepMounted:o,children:[s.jsx(DV,{forceRender:c}),s.jsxs(bE,{"data-slot":"dialog-content",className:Ue("fixed top-1/2 left-1/2 z-30 flex max-h-[calc(100vh-48px)] w-[min(620px,calc(100vw-48px))] -translate-x-1/2 -translate-y-1/2 flex-col","overflow-hidden rounded-lg border border-border bg-surface shadow-3 outline-none","transition-[opacity,transform] duration-200 [transition-timing-function:cubic-bezier(.2,.9,.3,1)]","data-open:animate-in data-open:fade-in-0 data-open:zoom-in-[.985] data-open:slide-in-from-bottom-2.5","data-closed:animate-out data-closed:fade-out-0 data-closed:fill-mode-forwards",e),...d,children:[t,a&&s.jsxs(fE,{"data-slot":"dialog-close",render:s.jsx(ne,{variant:"ghost",size:"icon-sm",className:"absolute top-3 right-3"}),children:[s.jsx("svg",{viewBox:"0 0 12 12",className:"size-3","aria-hidden":"true",children:s.jsx("path",{d:"M2.5 2.5l7 7M9.5 2.5l-7 7",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",fill:"none"})}),s.jsx("span",{className:"sr-only",children:bo("关闭")})]})]})]})}function Vt({className:e,...t}){return s.jsx("div",{"data-slot":"dialog-header",className:Ue("flex items-center gap-2.5 border-b border-hairline px-5 py-[15px] pr-10","[&_h2]:flex-1 [&_h2]:text-[14.5px] [&_h2]:font-semibold",e),...t})}function Lt({className:e,...t}){return s.jsx("div",{"data-slot":"dialog-body",className:Ue("flex flex-col gap-4 overflow-y-auto px-5 py-[18px]",e),...t})}function tn({className:e,...t}){return s.jsx("div",{"data-slot":"dialog-footer",className:Ue("flex items-center gap-2 border-t border-hairline bg-surface-2 px-5 py-[13px]",e),...t})}function dn({className:e,...t}){return s.jsx("div",{"data-slot":"dialog-section",className:Ue("flex flex-col gap-2.5 rounded-md border border-border bg-surface-inset p-3.5","[&_h3]:text-[12.5px] [&_h3]:font-semibold","[&_p]:text-xs [&_p]:leading-[1.65] [&_p]:text-subtle",e),...t})}function IV(e){return kE("alert-dialog",e)}const PV=IV,_V=vE,LV=e=>s.jsx(CE,{"data-slot":"alert-dialog-title",...e});function zV({className:e,...t}){return s.jsx(dE,{"data-slot":"alert-dialog-overlay",className:Ue("fixed inset-0 isolate z-[38] bg-mask backdrop-blur-[3px]","transition-opacity duration-150","data-open:animate-in data-open:fade-in-0","data-closed:animate-out data-closed:fade-out-0 data-closed:fill-mode-forwards",e),...t})}function BV({className:e,children:t,showCloseButton:a=!1,...o}){return s.jsxs(_V,{children:[s.jsx(zV,{}),s.jsxs(bE,{"data-slot":"alert-dialog-content",className:Ue("fixed top-1/2 left-1/2 z-[38] flex max-h-[calc(100vh-48px)] w-[min(440px,calc(100vw-48px))] -translate-x-1/2 -translate-y-1/2 flex-col","overflow-hidden rounded-lg border border-border bg-surface shadow-3 outline-none","transition-[opacity,transform] duration-200 [transition-timing-function:cubic-bezier(.2,.9,.3,1)]","data-open:animate-in data-open:fade-in-0 data-open:zoom-in-[.985] data-open:slide-in-from-bottom-2.5","data-closed:animate-out data-closed:fade-out-0 data-closed:fill-mode-forwards",e),...o,children:[t,a&&s.jsxs(fE,{"data-slot":"alert-dialog-close",render:s.jsx(ne,{variant:"ghost",size:"icon-sm",className:"absolute top-3 right-3"}),children:[s.jsx("svg",{viewBox:"0 0 12 12",className:"size-3","aria-hidden":"true",children:s.jsx("path",{d:"M2.5 2.5l7 7M9.5 2.5l-7 7",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",fill:"none"})}),s.jsx("span",{className:"sr-only",children:bo("关闭")})]})]})]})}function HV({className:e,...t}){return s.jsx("div",{"data-slot":"alert-dialog-header",className:Ue("flex items-center gap-2.5 border-b border-hairline px-5 py-[15px]","[&_h2]:flex-1 [&_h2]:text-[14.5px] [&_h2]:font-semibold",e),...t})}function UV({className:e,...t}){return s.jsx("div",{"data-slot":"alert-dialog-body",className:Ue("flex flex-col gap-4 overflow-y-auto px-5 py-[18px]",e),...t})}function VV({className:e,...t}){return s.jsx("div",{"data-slot":"alert-dialog-footer",className:Ue("flex items-center gap-2 border-t border-hairline bg-surface-2 px-5 py-[13px]",e),...t})}function FV({className:e,tone:t="danger",...a}){return s.jsx("div",{"data-slot":"alert-dialog-banner","data-tone":t,className:Ue("rounded-md border px-3.5 py-3 text-xs leading-[1.65] text-subtle","[&_strong]:font-semibold",t==="danger"?"border-destructive-bd bg-destructive-soft [&_strong]:text-destructive":"border-border bg-surface-inset [&_strong]:text-foreground",e),...a})}function Zy({className:e,containerClassName:t,...a}){return s.jsx("div",{"data-slot":"table-container",className:Ue("relative w-full overflow-auto",t),children:s.jsx("table",{"data-slot":"table",className:Ue("w-full caption-bottom border-collapse text-[12.5px]",e),...a})})}function AE({className:e,...t}){return s.jsx("thead",{"data-slot":"table-header",className:Ue(e),...t})}function Wy({className:e,...t}){return s.jsx("tbody",{"data-slot":"table-body",className:Ue(e),...t})}function Cl({className:e,...t}){return s.jsx("tr",{"data-slot":"table-row",className:Ue("transition-colors duration-100 hover:[&>td]:bg-control-hover",e),...t})}function RE({className:e,...t}){return s.jsx("th",{"data-slot":"table-head",className:Ue("sticky top-0 z-[2] whitespace-nowrap border-b border-border bg-surface-2 px-3.5 py-2","text-left text-[10.5px] font-semibold tracking-[.05em] text-muted-foreground",e),...t})}function Tn({className:e,...t}){return s.jsx("td",{"data-slot":"table-cell",className:Ue("border-b border-hairline px-3.5 py-2 align-middle",e),...t})}const $V="data-checked",qV="data-unchecked",Jy={checked(e){return e?{[$V]:""}:{[qV]:""}},...co,...Ti},ej="data-composite-item-active",OE=x.createContext({register:()=>{},unregister:()=>{},subscribeMapChange:()=>()=>{},nextIndexRef:{current:0}});function GV(){return x.useContext(OE)}function tj(e={}){const{guess:t,label:a,metadata:o,textRef:c,index:d}=e,{register:f,unregister:p,subscribeMapChange:h,nextIndexRef:b}=GV(),y=x.useRef(-1),[v,j]=x.useState(d==null&&t?()=>{if(y.current===-1){const k=b.current;b.current+=1,y.current=k}return y.current}:-1),w=d??v,S=x.useRef(null),N=x.useCallback(k=>{const A=S.current;A&&p(A),S.current=k,k&&f(k,{metadata:o??null,index:d??null,label:a,textRef:c})},[d,f,p,o,a,c]);return Me(()=>{if(d==null)return h(k=>{const A=S.current?k.get(S.current)?.index:null;A!=null&&j(A)})},[d,h]),{ref:N,index:w}}function KV(e={}){const{highlightItemOnHover:t,highlightedIndex:a,onHighlightedIndexChange:o}=EC(),{ref:c,index:d}=tj(e),f=a===d,p=x.useRef(null),h=sa(c,p);return{compositeProps:{tabIndex:f?0:-1,onFocus(){o(d)},onMouseMove(){const y=p.current;if(!t||!y)return;const v=y.hasAttribute("disabled")||y.ariaDisabled==="true";!f&&!v&&y.focus()}},compositeRef:h,index:d}}function ME(e){const{render:t,className:a,style:o,state:c=mn,props:d=Ir,refs:f=Ir,metadata:p,stateAttributesMapping:h,tag:b="div",...y}=e,{compositeProps:v,compositeRef:j}=KV({metadata:p});return yt(b,e,{state:c,ref:[j,...f],props:[v,...d,y],stateAttributesMapping:h})}const DE=x.createContext(void 0);function YV(){return x.useContext(DE)}function Ih(e){if(e==null)return"";if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return String(e)}}const IE=x.createContext(void 0);function XV(){const e=x.useContext(IE);if(e===void 0)throw new Error(un(52));return e}const PE=x.forwardRef(function(t,a){const{render:o,className:c,disabled:d=!1,readOnly:f=!1,required:p=!1,"aria-labelledby":h,value:b,inputRef:y,nativeButton:v=!1,id:j,style:w,...S}=t,N=YV(),{disabled:k,readOnly:A,required:P,form:R,checkedValue:C,touched:E=!1,validation:D,name:I,setCheckedValue:O=Kt,setTouched:_=Kt,registerInputRef:z=Kt}=N??{},{setTouched:H,setFilled:B,state:L,disabled:F}=Na(),$=A1(),{labelId:X,getDescriptionProps:K}=yl(),q=F||$.disabled||k||d,Q=A||f,G=P||p,J=R,Y=N?C===b:b==="",re=x.useRef(null),M=x.useRef(null),U=D?.registerInput,Z=x.useCallback(oe=>U?.(oe,{controlRef:re,value:void 0}),[U]),ae=sa(y,M,z,Z);Me(()=>{M.current?.checked&&B(!0)},[B]),Me(()=>{if(M.current){if(q&&Y){z(null);return}z(M.current)}},[Y,q,z]);const ce=ka(),W=io({id:j}),ue=v?void 0:W,ve=Fv(h,X,M,!v,ue),ee={role:"radio","aria-checked":Y,"aria-labelledby":ve,[ej]:Y?"":void 0,id:v?W:ce,onKeyDown(oe){oe.key==="Enter"&&oe.preventDefault()},onClick(oe){if(oe.defaultPrevented||q||Q)return;oe.preventDefault();const me=M.current;me&&Yc(me,oe)},onFocus(oe){oe.defaultPrevented||q||Q||!E||(M.current?.click(),_(!1))}},{getButtonProps:he,buttonRef:te}=na({disabled:q,native:v,composite:!1}),ke={type:"radio",ref:ae,form:J,id:ue,name:I,tabIndex:-1,style:I?su:_i,"aria-hidden":!0,...b!==void 0?{value:Ih(b)}:mn,disabled:q,checked:Y,required:G,readOnly:Q,onChange(oe){if(oe.nativeEvent.defaultPrevented||q||Q||b===void 0)return;const me=qe(Qn,oe.nativeEvent);O(b,me),!me.isCanceled&&H(!0)},onClick(oe){oe.stopPropagation()},onFocus(){re.current?.focus()}},le=x.useMemo(()=>({...L,required:G,disabled:q,readOnly:Q,checked:Y}),[L,q,Q,Y,G]),de=le,Se=N!==void 0,Te=[a,re,te],_e=[ee,S,he,K,D?oe=>D.getValidationProps(q,oe):mn],Ae=yt("span",t,{enabled:!Se,state:le,ref:Te,props:_e,stateAttributesMapping:Jy});return s.jsxs(IE.Provider,{value:de,children:[Se?s.jsx(ME,{tag:"span",render:o,className:c,style:w,state:le,refs:Te,props:_e,stateAttributesMapping:Jy}):Ae,s.jsx("input",{...ke,suppressHydrationWarning:!0})]})}),QV=x.forwardRef(function(t,a){const{render:o,className:c,style:d,keepMounted:f=!1,...p}=t,h=XV(),b=h.checked,{mounted:y,transitionStatus:v,setMounted:j}=Oi(b),w={...h,transitionStatus:v},S=x.useRef(null),N=f||y,k=yt("span",t,{ref:[a,S],state:w,props:p,stateAttributesMapping:Jy});return oa({batch:!0,enabled:!b,open:b,ref:S,onComplete(){b||j(!1)}}),N?k:null});function nj(e){const{children:t,elementsRef:a,labelsRef:o,onMapChange:c}=e,d=Ie(c),[,f]=x.useState(!1),p=Ps(WV).current,h=Ps(ZV).current,b=x.useRef(0),y=x.useRef(!0),v=x.useRef(null),j=x.useRef(null),w=Ie(()=>{y.current||(y.current=!0,f(E=>!E))}),S=Ie((E,D)=>{h.set(E,D),w()}),N=Ie(E=>{h.delete(E),w()}),k=Ie(E=>{const D=new Map;return a.current.length=0,o&&(o.current.length=0),E.forEach(I=>{D.set(I.element,{...I.registration.metadata??{},index:I.index}),a.current[I.index]=I.element,o&&(o.current[I.index]=I.registration.label!==void 0?I.registration.label:I.registration.textRef?.current?.textContent??I.element.textContent)}),b.current=a.current.length,D});function A(E){if(j.current?.disconnect(),j.current=null,typeof MutationObserver!="function"||E.length<2)return;const D=new MutationObserver(O=>{if(!tF(O))return;let _=null;for(const z of E)if(z.isConnected){if(_&&_E(_,z)>0){D.disconnect(),w();return}_=z}});j.current=D;const I=new Set;for(let O=1;OD.observe(O,{childList:!0}))}const P=Ie(()=>{const[E,D]=JV(h),I=k(E),O=v.current,_=!O||O.length!==E.length||E.some((z,H)=>{const B=O[H];return z.index!==B.index||z.element!==B.element||z.registration.index!==B.registration.index||z.registration.metadata!==B.registration.metadata});A(D),v.current=E,y.current=!1,_&&(p.forEach(z=>z(I)),d(I))});Me(()=>(!y.current&&v.current&&k(v.current),()=>{a.current=[],o&&(o.current=[])}),[a,o,k]),Me(()=>{y.current&&P()}),Me(()=>()=>{j.current?.disconnect(),y.current=!0},[]);const R=Ie(E=>(p.add(E),()=>{p.delete(E)})),C=x.useMemo(()=>({register:S,unregister:N,subscribeMapChange:R,nextIndexRef:b}),[S,N,R,b]);return s.jsx(OE.Provider,{value:C,children:t})}function ZV(){return new Map}function WV(){return new Set}function JV(e){const t=new Set,a=[],o=[];e.forEach((d,f)=>{if(!f.isConnected)return;const p=d.index,h={index:p??-1,element:f,registration:d};p===null?o.push(h):p>=0&&(t.add(p),a.push(h))});let c=0;return o.sort((d,f)=>_E(d.element,f.element)),o.forEach(d=>{for(;t.has(c);)c+=1;d.index=c,a.push(d),c+=1}),t.size>0&&a.sort((d,f)=>d.index-f.index),[a,o.map(d=>d.element)]}function eF(e,t){let a=e.parentElement;for(;a&&!a.contains(t);)a=a.parentElement;return a}function tF(e){for(const t of e)for(let a=0;a{if(C.current=P.current[H]??null,(p??S)(H),B){const L=P.current[H];gE(k.current,L,d,a)}}),I=Ie(H=>{if(H.size===0)return;if(R.current){const $=P.current,X=$.indexOf(C.current);if(X===-1){const K=$[E];!K||ho($,E,v)?D(sF($,v)):C.current=K}else X!==E&&D(X);return}R.current=!0;const B=Array.from(H.keys()),L=B.find($=>$?.hasAttribute(ej))??null,F=L?H.get(L)?.index??-1:-1;if(F!==-1)D(F);else if(ho(B,E,v)){const $=_s(B,{disabledIndices:v});mo(B,$)||D($)}gE(k.current,L,d,a)});Me(()=>{if(v==null||f!=null||!R.current)return;const H=P.current;if(ho(H,E,v)){const B=_s(H,{disabledIndices:v});mo(H,B)||D(B)}},[v,f,E,P,D]);const O=Ie((H,B,L)=>c?c(H,B,L,P):L),_=Ie(H=>{const B=H.key===Xy||H.key===Qy;if(!Rh.has(H.key)||!b&&B||rF(H,j)||!k.current)return;const F=d==="rtl",$=F?Ky:Yy,X=F?Yy:Ky,K=a==="vertical"?Gy:$,q=a==="vertical"?qy:X,Q=fs(H.nativeEvent);if(Q!=null&&hE(Q)&&!LE(Q)){const U=Q.selectionStart,Z=Q.selectionEnd,ae=Q.value;if(U==null||H.shiftKey||U!==Z||H.key!==q&&U0)return}let G=E;const J=sh(P,v),Y=ry(P,v);o!=null&&(G=o({disabledIndices:v,elementsRef:P,event:H,highlightedIndex:E,loopFocus:t,maxIndex:Y,minIndex:J,onLoop:O,orientation:a,rtl:F}));const re=a!=="vertical"&&H.key===$||a!=="horizontal"&&H.key===Gy,M=a!=="vertical"&&H.key===X||a!=="horizontal"&&H.key===qy;b&&(H.key===Xy?G=J:H.key===Qy&&(G=Y)),G===E&&(re||M)&&(t&&G===Y&&re?(G=J,c&&(G=c(H,E,G,P))):t&&G===J&&M?(G=Y,c&&(G=c(H,E,G,P))):G=_s(P.current,{startingIndex:G,decrement:M,disabledIndices:v})),G!==E&&!mo(P.current,G)&&(y&&H.stopPropagation(),(N||B||re||M)&&H.preventDefault(),D(G,!0),queueMicrotask(()=>{P.current[G]?.focus()}))});return{props:{ref:A,onFocus(H){const B=k.current,L=fs(H.nativeEvent);!B||L==null||!hE(L)||L.setSelectionRange(0,L.value.length)},onKeyDown:_},highlightedIndex:E,onHighlightedIndexChange:D,elementsRef:P,onMapChange:I,relayKeyboardEvent:_}}function sF(e,t){let a=-1;for(let o=0;o({highlightedIndex:_,onHighlightedIndexChange:z,highlightItemOnHover:C,relayKeyboardEvent:L}),[_,z,C,L]);return s.jsx(TC.Provider,{value:$,children:s.jsx(nj,{elementsRef:H,onMapChange:X=>{N?.(X),B(X)},children:F})})}const lF=[mE],zE=x.forwardRef(function(t,a){const{render:o,className:c,disabled:d,readOnly:f,required:p,onValueChange:h,value:b,defaultValue:y,form:v,name:j,inputRef:w,id:S,style:N,...k}=t,{setTouched:A,setFocused:P,validationMode:R,name:C,disabled:E,state:D,validation:I,setDirty:O,setFilled:_,validityData:z}=Na(),{labelId:H}=yl(),{clearErrors:B,elementRef:L}=Qc(),F=kB(!0),$=E||d,X=C??j,K=ka(S),[q,Q]=Ka({controlled:b,default:y,name:"RadioGroup",state:"value"}),[G,J]=x.useState(!1),Y=Ie((te,ke)=>{h?.(te,ke),!ke.isCanceled&&Q(te)}),re=I.getInputControl,M=x.useMemo(()=>({get current(){return re()}}),[re]),U=x.useRef(null),Z=x.useRef(null);function ae(te){let ke;return w&&(typeof w=="function"?ke=w(te):w.current=te),U.current=te,ke}const ce=Ie(te=>{if(!te||te.disabled)return;Z.current||(Z.current=te);const ke=U.current,le=te.checked||ke==null||ke.disabled?ae(te):void 0;return()=>{Z.current===te&&(Z.current=null),U.current===te?le?(le(),U.current=null):ae(null):le?.()}}),W=Ie(()=>{const te=L.current;if(!te)return q??null;for(const ke of I.registeredInputs.keys())if(ke.checked&&b4(ke,te))return q??null;return null});tu(M,K,q??null,W,!$,j),ia(q,()=>{B(X),O(q!==z.initialValue),_(q!=null),I.change(q);const te=Z.current;q==null&&te&&!te.disabled&&ae(te)});const ue=H??F?.legendId,ve={...D,disabled:$??!1,required:p??!1,readOnly:f??!1},ee=x.useMemo(()=>({checkedValue:q,disabled:$,form:v,validation:I,name:X,readOnly:f,registerInputRef:ce,required:p,setCheckedValue:Y,setTouched:J,touched:G}),[q,$,v,I,X,f,ce,p,Y,J,G]),he={id:S,role:"radiogroup","aria-required":p||void 0,"aria-disabled":$||void 0,"aria-readonly":f||void 0,"aria-labelledby":ue,onFocus(){P(!0)},onBlur(te){Ze(te.currentTarget,te.relatedTarget)||(A(!0),P(!1),R==="onBlur"&&I.commit(q))},onKeyDownCapture(te){te.key.startsWith("Arrow")&&(J(!0),P(!0))}};return s.jsx(DE.Provider,{value:ee,children:s.jsx(aF,{render:o,className:c,style:N,state:ve,props:[he,k,te=>I.getValidationProps($??!1,te)],refs:[a],stateAttributesMapping:Ti,enableHomeAndEndKeys:!1,modifierKeys:lF})})});function Ph({className:e,...t}){return s.jsx(zE,{"data-slot":"radio-group",className:Ue("flex flex-col gap-2",e),...t})}function yo({className:e,...t}){return s.jsx(PE,{"data-slot":"radio-group-item",className:Ue("relative inline-flex size-3.5 flex-none cursor-pointer items-center justify-center rounded-full border border-control-border bg-control","outline-none transition-colors duration-150 ease-out","hover:border-control-border-hover","data-checked:border-primary data-checked:bg-primary","focus-visible:shadow-focus","data-disabled:cursor-not-allowed data-disabled:opacity-45",e),...t,children:s.jsx(QV,{"data-slot":"radio-group-indicator",className:"grid place-content-center data-unchecked:hidden",children:s.jsx("span",{className:"block size-[5px] rounded-full bg-primary-foreground"})})})}function BE(e){const t=x.useRef(!0);t.current&&(t.current=!1,e())}const HE=x.createContext(void 0),UE=x.createContext(void 0),VE=x.createContext(void 0);function jo(){const e=x.useContext(HE);if(e===void 0)throw new Error(un(60));return e}function sj(){const e=x.useContext(UE);if(e===void 0)throw new Error(un(101));return e}function FE(){const e=x.useContext(VE);if(e===void 0)throw new Error(un(61));return e}function oF(e,t,a=Object.is){const{length:o}=e;if(o!==t.length)return!1;for(let c=0;cObject.is(e,t);function ca(e,t,a){return e==null||t==null?Object.is(e,t):a(e,t)}function $E(e,t,a){return Array.isArray(e)&&Array.isArray(t)?!oF(e,t,(o,c)=>ca(o,c,a)):e!==t}function Lh(e,t,a){return e?e.some(o=>o===void 0?!1:ca(t,o,a)):!1}function cu(e,t,a){return e?e.findIndex(o=>o===void 0?!1:ca(o,t,a)):-1}function iF(e,t){if(t!==_h)return o=>Lh(e,o,t);const a=new Set(e);return a.delete(void 0),o=>a.has(o)&&(o!==0||e.some(c=>Object.is(o,c)))}function bf(e,t,a,o){const c=o&&Array.isArray(t)?e.findIndex(iF(t,a)):cu(e,t,a);return c===-1?null:c}function qE(e,t,a,o,c,d){return Lh(o,t,c)?d!=null&&e>d&&Lh(o,a[d],c)?d:e:e===d?bf(a,o,c,!0):d}function GE(e,t,a){return e.filter(o=>!ca(t,o,a))}function cF(e){return typeof e=="object"&&e!=null&&Array.isArray(e.items)}function rj(e){return cF(e?.[0])}function zh(e){return rj(e)?e.flatMap(t=>t.items):e}function KE(e){if(!Array.isArray(e))return e!=null&&"null"in e;const t=e;if(rj(t)){for(const a of t)for(const o of a.items)if(o&&o.value==null&&o.label!=null)return!0;return!1}for(const a of t)if(a&&a.value==null&&a.label!=null)return!0;return!1}function wo(e,t){if(t&&e!=null)return t(e)??"";if(e&&typeof e=="object"){if("label"in e&&e.label!=null)return String(e.label);if("value"in e)return String(e.value)}return Ih(e)}function Ca(e,t){return t&&e!=null?t(e)??"":e&&typeof e=="object"&&"value"in e&&"label"in e?Ih(e.value):Ih(e)}function YE(e,t,a){function o(){return wo(e,a)}if(a&&e!=null)return a(e);if(e&&typeof e=="object"&&"label"in e&&e.label!=null)return e.label;if(t&&!Array.isArray(t))return(Object.hasOwn(t,e)?t[e]:void 0)??o();if(Array.isArray(t)){const d=zh(t);if(e==null||typeof e!="object"){const f=d.find(p=>p.value===e);return f&&f.label!=null?f.label:o()}if("value"in e){const f=d.find(p=>p&&p.value===e.value);if(f&&f.label!=null)return f.label}}return o()}function uF(e,t,a){return e.reduce((o,c,d)=>(d>0&&o.push(", "),o.push(s.jsx(x.Fragment,{children:YE(c,t,a)},d)),o),[])}const dF={id:e=>e.id,labelId:e=>e.labelId,modal:e=>e.modal,items:e=>e.items,itemToStringLabel:e=>e.itemToStringLabel,isItemEqualToValue:e=>e.isItemEqualToValue,value:e=>e.value,hasSelectedValue:e=>{const{value:t,multiple:a,itemToStringValue:o}=e;return t==null?!1:a&&Array.isArray(t)?t.length>0:Ca(t,o)!==""},hasNullItemLabel:(e,t)=>t?KE(e.items):!1,open:e=>e.open,mounted:e=>e.mounted,forceMount:e=>e.forceMount,transitionStatus:e=>e.transitionStatus,openMethod:e=>e.openMethod,activeIndex:e=>e.activeIndex,selectedIndex:e=>e.selectedIndex,isActive:(e,t)=>e.activeIndex===t,isSelected:(e,t)=>{const a=e.isItemEqualToValue,o=e.value;return e.multiple?Array.isArray(o)&&o.some(c=>ca(t,c,a)):ca(t,o,a)},isSelectedByFocus:(e,t)=>e.selectedIndex===t,popupProps:e=>e.popupProps,triggerProps:e=>e.triggerProps,triggerElement:e=>e.triggerElement,positionerElement:e=>e.positionerElement,listElement:e=>e.listElement,popupSide:e=>e.popupSide,scrollUpArrowVisible:e=>e.scrollUpArrowVisible,scrollDownArrowVisible:e=>e.scrollDownArrowVisible,hasScrollArrows:e=>e.hasScrollArrows},Tl=1;function XE(e,t){return Math.max(0,e-t)}function fF(e,t){if(t<=0)return 0;const a=Li(e,0,t),o=a,c=t-a,d=o<=Tl,f=c<=Tl;return d&&f?o<=c?0:t:d?0:f?t:a}function pF(e){const{id:t,value:a,defaultValue:o=null,onValueChange:c,open:d,defaultOpen:f=!1,onOpenChange:p,name:h,form:b,autoComplete:y,disabled:v=!1,readOnly:j=!1,required:w=!1,modal:S=!0,actionsRef:N,inputRef:k,onOpenChangeComplete:A,items:P,multiple:R=!1,itemToStringLabel:C,itemToStringValue:E,isItemEqualToValue:D=_h,highlightItemOnHover:I=!0,children:O}=e,{clearErrors:_}=Qc(),{setDirty:z,setTouched:H,setFocused:B,validityData:L,setFilled:F,name:$,disabled:X,validation:K,validationMode:q}=Na(),Q=io({id:t}),G=X||v,J=$??h,[Y,re]=Ka({controlled:a,default:R?o??Ir:o,name:"Select",state:"value"}),[M,U]=Ka({controlled:d,default:f,name:"Select",state:"open"}),Z=x.useRef([]),ae=x.useRef([]),ce=x.useRef(null),W=x.useRef(null),ue=x.useRef(0),ve=x.useRef(null),ee=x.useRef([]),he=x.useRef(!1),te=x.useRef(null),ke=x.useRef(null),le=x.useRef({allowSelectedMouseUp:!1,allowUnselectedMouseUp:!1,dragY:0}),de=x.useRef(!1),Se=x.useRef(Y),{mounted:Te,setMounted:_e,transitionStatus:Ae}=Oi(M),{openMethod:oe,triggerProps:me}=EE(M),pe=Ps(()=>new ou({id:Q,labelId:void 0,modal:S,multiple:R,itemToStringLabel:C,itemToStringValue:E,isItemEqualToValue:D,value:Y,open:M,mounted:Te,transitionStatus:Ae,items:P,forceMount:!1,openMethod:null,activeIndex:null,selectedIndex:null,popupProps:mn,triggerProps:mn,triggerElement:null,positionerElement:null,listElement:null,popupSide:null,scrollUpArrowVisible:!1,scrollDownArrowVisible:!1,hasScrollArrows:!1},{setValue:Kt,setOpen:Kt,handleScrollArrowVisibility:Kt,onOpenChangeComplete:Kt,listRef:Z,popupRef:ce,scrollHandlerRef:W,scrollArrowsMountedCountRef:ue,valueRef:ve,valuesRef:ee,labelsRef:ae,typingRef:he,selectionRef:le,firstItemTextRef:te,selectedItemTextRef:ke,alignItemWithTriggerActiveRef:de,initialValueRef:Se},dF)).current,Ce=pe.useState("activeIndex"),Ne=pe.useState("selectedIndex"),be=pe.useState("triggerElement"),De=pe.useState("positionerElement"),Ge=uV(oe),Ct=oe??Ge,Tt=x.useMemo(()=>R?"":Ca(Y,E),[R,Y,E]),Mt=x.useMemo(()=>R&&Array.isArray(Y)?Y.map(xt=>Ca(xt,E)):Ca(Y,E),[R,Y,E]),ot=Zn(be),Kn=Ie(()=>Mt);tu(ot,Q,Y,Kn,!G,h);const ms=R?Array.isArray(Y)&&Y.length>0:Y!=null&&Tt!=="";Me(()=>{F(ms)},[ms,F]),Me(function(){const jt=bf(ee.current,Y,D,R);jt===null&&(ke.current=null),!M&&pe.set("selectedIndex",jt)},[R,M,Y,D,pe]),ia(Y,()=>{_(J),z($E(Y,L.initialValue,D)),K.change(Y)});const Yn=Ie((xt,jt)=>{p?.(xt,jt),!jt.isCanceled&&(U(xt),!xt&&(jt.reason===xo||jt.reason===ch)&&(H(!0),B(!1),q==="onBlur"&&K.commit(Y)))}),vs=Ie(()=>{_e(!1),pe.update({activeIndex:null,openMethod:null,scrollUpArrowVisible:!1,scrollDownArrowVisible:!1}),A?.(!1)});oa({enabled:!N,open:M,ref:ce,onComplete(){M||vs()}}),x.useImperativeHandle(N,()=>({unmount:vs}),[vs]);const it=Ie((xt,jt)=>{c?.(xt,jt),!jt.isCanceled&&re(xt)}),$t=Ie(xt=>{const jt=XE(xt.scrollHeight,xt.clientHeight),wt=fF(xt.scrollTop,jt),Tr=wt>0,ar=wtLE(Z.current[xt]),onMatch(xt){M?pe.set("activeIndex",xt):it(ee.current[xt],qe(Qn))},onTyping(xt){he.current=xt}}),es=x.useMemo(()=>ta(qt.reference,Dt.reference,nt.reference,rn.reference,me),[rn.reference,qt.reference,Dt.reference,nt.reference,me]),Fn=x.useMemo(()=>ta(mf,qt.floating,Dt.floating,nt.floating),[qt.floating,Dt.floating,nt.floating]),$n=Dt.item??mn;pe.useContextCallback("setValue",it),pe.useContextCallback("setOpen",Yn),pe.useContextCallback("handleScrollArrowVisibility",$t),pe.useContextCallback("onOpenChangeComplete",A),BE(()=>{pe.update({popupProps:Fn,triggerProps:es})}),pe.useSyncedValues({id:Q,modal:S,multiple:R,value:Y,open:M,mounted:Te,transitionStatus:Ae,popupProps:Fn,triggerProps:es,items:P,itemToStringLabel:C,itemToStringValue:E,isItemEqualToValue:D,openMethod:Ct});const Dn=x.useMemo(()=>({disabled:G,readOnly:j,required:w,multiple:R,highlightItemOnHover:I,itemProps:$n}),[G,j,w,R,I,$n]),en=sa(k,K.inputRef),cs=R?void 0:J,Et=x.useMemo(()=>!R||!Array.isArray(Y)||!J?null:Y.map(xt=>{const jt=Ca(xt,E);return s.jsx("input",{type:"hidden",form:b,name:J,value:jt,disabled:G},jt)}),[R,Y,b,J,E,G]);return s.jsxs(HE.Provider,{value:pe,children:[s.jsx(UE.Provider,{value:Dn,children:s.jsx(VE.Provider,{value:Vn,children:O})}),s.jsx("input",{...K.getValidationProps(G,{onFocus(){pe.state.triggerElement?.focus({focusVisible:!0})},onChange(xt){if(xt.nativeEvent.defaultPrevented||G||j)return;const jt=xt.currentTarget.value,wt=qe(Qn,xt.nativeEvent);function Tr(){if(R)return;const ar=jt.toLowerCase();let Fr=ee.current.findIndex(al=>Ca(al,E).toLowerCase()===ar||wo(al,C).toLowerCase()===ar);Fr===-1&&(Fr=ee.current.findIndex((al,ln)=>{const hc=ae.current[ln];return hc!=null&&hc.toLowerCase()===ar}));const Nn=ee.current[Fr];Nn!=null&&it(Nn,wt)}pe.set("forceMount",!0),queueMicrotask(Tr)}}),id:Q&&cs==null?`${Q}-hidden-input`:void 0,form:b,name:cs,autoComplete:y,value:Tt,disabled:G,required:w&&!(R&&ms),readOnly:j,ref:en,style:J?su:_i,tabIndex:-1,"aria-hidden":!0,suppressHydrationWarning:!0}),Et]})}function QE(e,t){return e??t}const Bh=5;function ZE(e,t){const a=mF(t);return e.clientX>=a.left-Bh&&e.clientX<=a.right+Bh&&e.clientY>=a.top-Bh&&e.clientY<=a.bottom+Bh}function mF(e){const t=e.getBoundingClientRect(),a=Cn(e);if($v)return t;const o=a.getComputedStyle(e,"::before"),c=a.getComputedStyle(e,"::after");if(!(o.content!=="none"||c.content!=="none"))return t;const f=parseFloat(o.width)||0,p=parseFloat(o.height)||0,h=parseFloat(c.width)||0,b=parseFloat(c.height)||0,y=Math.max(t.width,f,h),v=Math.max(t.height,p,b),j=y-t.width,w=v-t.height;return{left:t.left-j/2,right:t.right+j/2,top:t.top-w/2,bottom:t.bottom+w/2}}const hF="data-popup-side",gF=400,xF={...Yv,...Ti,popupSide:e=>e?{[hF]:e}:null,value:()=>null},bF=x.forwardRef(function(t,a){const{render:o,className:c,id:d,disabled:f=!1,nativeButton:p=!0,style:h,...b}=t,{setTouched:y,setFocused:v,validationMode:j,validation:w,state:S,disabled:N}=Na(),{labelId:k}=yl(),A=jo(),{readOnly:P,required:R,disabled:C}=sj(),E=N||C||f,D=A.useState("open"),I=A.useState("mounted"),O=A.useState("value"),_=A.useState("triggerProps"),z=A.useState("positionerElement"),H=A.useState("listElement"),B=A.useState("popupSide"),L=A.useState("id"),F=A.useState("labelId"),$=A.useState("hasSelectedValue"),X=I&&z?B:null,K=d??L,q=QE(k,F);io({id:d});const Q=Zn(z),G=x.useRef(null),{getButtonProps:J,buttonRef:Y}=na({disabled:E,native:p}),re=A.useStateSetter("triggerElement"),M=er(),U=er(),Z=er();x.useEffect(()=>{if(D)return Z.start(gF,()=>{A.context.selectionRef.current.allowUnselectedMouseUp=!0,A.context.selectionRef.current.allowSelectedMouseUp=!0}),()=>{Z.clear()};A.context.selectionRef.current={allowSelectedMouseUp:!1,allowUnselectedMouseUp:!1,dragY:0},U.clear()},[D,A,U,Z]);const ae=ta(_,{id:K,role:"combobox","aria-expanded":D,"aria-haspopup":"listbox","aria-controls":D?H?.id??Wm(z)?.id:void 0,"aria-labelledby":q,"aria-readonly":P||void 0,"aria-required":R||void 0,tabIndex:E?-1:0,onFocus(ue){v(!0),D&&A.context.alignItemWithTriggerActiveRef.current&&A.context.setOpen(!1,qe(Qn,ue.nativeEvent)),M.start(0,()=>{A.set("forceMount",!0)})},onBlur(ue){Ze(z,ue.relatedTarget)||(y(!0),v(!1),j==="onBlur"&&w.commit(O))},onMouseDown(ue){if(D)return;const ve=Gt(ue.currentTarget);function ee(he){if(!G.current)return;const te=he.target;Ze(G.current,te)||Ze(Q.current,te)||ZE(he,G.current)||A.context.setOpen(!1,qe(_1,he))}U.start(0,()=>{ve.addEventListener("mouseup",ee,{once:!0})})}},b,J),ce=w.getValidationProps(E,ae);ce.role="combobox";const W={...S,open:D,disabled:E,value:O,readOnly:P,popupSide:X,placeholder:!$};return yt("button",t,{ref:[a,G,Y,re],state:W,stateAttributesMapping:xF,props:ce})}),vF={value:()=>null},yF=x.forwardRef(function(t,a){const{className:o,render:c,children:d,placeholder:f,style:p,...h}=t,b=jo(),y=b.useState("value"),v=b.useState("items"),j=b.useState("itemToStringLabel"),w=b.useState("hasSelectedValue"),S=!w&&f!=null&&d==null,N=b.useState("hasNullItemLabel",S),k={value:y,placeholder:!w};let A=null;return typeof d=="function"?A=d(y):d!=null?A=d:S&&!N?A=f:Array.isArray(y)?A=uF(y,v,j):A=YE(y,v,j),yt("span",t,{state:k,ref:[a,b.context.valueRef],props:[{children:A},h],stateAttributesMapping:vF})}),jF=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,b={open:jo().useState("open")};return yt("span",t,{state:b,ref:a,props:[{"aria-hidden":!0,children:"▼"},f],stateAttributesMapping:Kv})}),wF=x.forwardRef(function(t,a){const o=jo(),c=o.useState("mounted"),d=o.useState("forceMount");return c||d?s.jsx(ph,{ref:a,...t}):null}),WE=x.createContext(void 0);function SF(){const e=x.useContext(WE);if(!e)throw new Error(un(59));return e}function Hh(e,t){e&&Object.assign(e.style,t)}const NF={position:"relative",maxHeight:"100%",overflowX:"hidden",overflowY:"auto"},kF=20;function aj(e,t,a,o){const[c,d]=x.useState(!1);Me(()=>{if(!e||!t||a==null){d(!1);return}const f=Gt(a).documentElement.clientWidth,p=a.offsetWidth;d(f>0&&p>0&&p>=f-kF)},[e,t,a]),NE(e&&(!t||c),o)}const CF={position:"fixed"},TF=x.forwardRef(function(t,a){const{anchor:o,className:c,render:d,positionMethod:f,side:p,align:h,sideOffset:b,alignOffset:y,collisionBoundary:v="clipping-ancestors",collisionPadding:j,arrowPadding:w,sticky:S,disableAnchorTracking:N,alignItemWithTrigger:k=!0,collisionAvoidance:A=rT,style:P,...R}=t,C=jo(),E=FE(),D=C.useState("open"),I=C.useState("mounted"),O=C.useState("modal"),_=C.useState("value"),z=C.useState("openMethod"),H=C.useState("positionerElement"),B=C.useState("triggerElement"),L=C.useState("isItemEqualToValue"),F=C.useState("transitionStatus"),$=x.useRef(null),X=x.useRef(null),[K,q]=x.useState(k),Q=I&&K&&z!=="touch";!I&&K!==k&&q(k),x.useImperativeHandle(C.context.alignItemWithTriggerActiveRef,()=>Q),aj((Q||O)&&D,z==="touch",H,B);const G=Th({anchor:o,floatingRootContext:E,positionMethod:f,mounted:I,side:p,sideOffset:b,align:h,alignOffset:y,arrowPadding:w,collisionBoundary:v,collisionPadding:j,sticky:S,disableAnchorTracking:N??Q,collisionAvoidance:A,keepMounted:!0}),J=Q?"none":G.side,Y=Q?CF:G.positionerStyles,re={open:D,side:J,align:G.align,anchorHidden:G.anchorHidden};Me(()=>{C.set("popupSide",G.side)},[C,G.side]);const M=C.useStateSetter("positionerElement"),U=Eh(t,re,{styles:Y,transitionStatus:F,props:R,refs:[a,M],hidden:!I,inert:!D}),Z=x.useRef(0),ae=Ie(W=>{if(C.context.valuesRef.current.length===0)return;const ue=Z.current;Z.current=W.size;const ve=qe(Qn);if(ue!==0&&!C.state.multiple&&_!==null&&cu(C.context.valuesRef.current,_,L)===-1){const he=C.context.initialValueRef.current,ke=he!=null&&cu(C.context.valuesRef.current,he,L)!==-1?he:null;C.context.setValue(ke,ve),ke===null&&(C.set("selectedIndex",null),C.context.selectedItemTextRef.current=null)}if(ue!==0&&C.state.multiple&&Array.isArray(_)){const ee=_.filter(he=>cu(C.context.valuesRef.current,he,L)!==-1);ee.length!==_.length&&(C.context.setValue(ee,ve),ee.length===0&&(C.set("selectedIndex",null),C.context.selectedItemTextRef.current=null))}if(D&&Q){C.update({scrollUpArrowVisible:!1,scrollDownArrowVisible:!1});const ee={height:""};Hh(H,ee),Hh(C.context.popupRef.current,ee)}}),ce=x.useMemo(()=>({...G,side:J,alignItemWithTriggerActive:Q,setControlledAlignItemWithTrigger:q,scrollUpArrowRef:$,scrollDownArrowRef:X}),[G,J,Q,q]);return s.jsx(nj,{elementsRef:C.context.listRef,labelsRef:C.context.labelsRef,onMapChange:ae,children:s.jsxs(WE.Provider,{value:ce,children:[I&&O&&s.jsx(Mh,{inert:Ah(!D),cutout:B}),U]})})}),Uh="base-ui-disable-scrollbar",JE={className:Uh,getElement(e){return s.jsx("style",{nonce:e,href:Uh,precedence:"base-ui:low",children:`.${Uh}{scrollbar-width:none}.${Uh}::-webkit-scrollbar{display:none}`})}},EF=x.createContext(void 0);function eA(e){return x.useContext(EF)}const AF=x.createContext(void 0),RF={disableStyleElements:!1};function OF(){return x.useContext(AF)??RF}const tA="--transform-origin",MF={...Zc,...co},DF=x.forwardRef(function(t,a){const{render:o,className:c,style:d,finalFocus:f,...p}=t,h=jo(),{multiple:b,readOnly:y,highlightItemOnHover:v}=sj(),j=FE(),{side:w,align:S,alignItemWithTriggerActive:N,isPositioned:k,setControlledAlignItemWithTrigger:A}=SF(),P=eA()!=null,R=gf(),{nonce:C,disableStyleElements:E}=OF(),D=h.useState("id"),I=h.useState("open"),O=h.useState("openMethod"),_=h.useState("mounted"),z=h.useState("popupProps"),H=h.useState("transitionStatus"),B=h.useState("triggerElement"),L=h.useState("positionerElement"),F=h.useState("listElement"),$=x.useRef(!1),X=x.useRef(!1),K=x.useRef({}),q=eu(),Q=Ie(re=>{if(!L||!h.context.popupRef.current||!X.current)return;const M=L.style.top==="0px",U=L.style.bottom==="0px";if($.current||!N||!M&&!U){h.context.handleScrollArrowVisibility(re);return}const Z=sA(L),ae=vf(L.getBoundingClientRect().height,"y",Z),ce=Gt(L),W=Cn(L),ue=W.getComputedStyle(L),ve=parseFloat(ue.marginTop),ee=parseFloat(ue.marginBottom),he=nA(W.getComputedStyle(h.context.popupRef.current)),te=Math.min(ce.documentElement.clientHeight-ve-ee,he),ke=re.scrollTop,le=Vh(re);let de=null;const Se=oe=>{L.style.height=`${oe}px`},Te=M?le-ke:ke,_e=Math.min(ae+Te,te);if(Te<=Tl){const oe=Li(Te,0,te-ae);oe>0&&Se(ae+oe),re.scrollTop=M?le:0,te-(ae+oe)<=Tl&&($.current=!0),h.context.handleScrollArrowVisibility(re);return}if(te-_e>Tl)de=M?1/0:0;else if(U&&keTl&&(re.scrollTop=oe)}Ae>=te-Tl&&($.current=!0),h.context.handleScrollArrowVisibility(re)});x.useImperativeHandle(h.context.scrollHandlerRef,()=>Q,[Q]),oa({open:I,ref:h.context.popupRef,onComplete(){I&&h.context.onOpenChangeComplete(!0)}});const G={open:I,transitionStatus:H,side:w,align:S};Me(()=>{!L||!h.context.popupRef.current||Object.keys(K.current).length||(K.current={top:L.style.top||"0",left:L.style.left||"0",right:L.style.right,height:L.style.height,bottom:L.style.bottom,minHeight:L.style.minHeight,maxHeight:L.style.maxHeight,marginTop:L.style.marginTop,marginBottom:L.style.marginBottom})},[h,L]),Me(()=>{I||N||(X.current=!1,$.current=!1,Hh(L,K.current))},[I,N,L]),Me(()=>{const re=h.context.popupRef.current;if(!I||!B||!L||!re||N&&!k||h.state.transitionStatus==="ending")return;if(X.current=!0,re.style.removeProperty(tA),!N){q.request(()=>h.context.handleScrollArrowVisibility(F||re));return}const M=IF(re);try{let U=h.context.selectedItemTextRef.current;U?.isConnected||(U=!h.select("hasSelectedValue")&&h.context.firstItemTextRef.current?.isConnected?h.context.firstItemTextRef.current:null);const Z=h.context.valueRef.current,ae=Cn(L),ce=ae.getComputedStyle(L),W=ae.getComputedStyle(re),ue=Gt(B),ve=sA(B),ee=Fh(B.getBoundingClientRect(),ve),he=Fh(L.getBoundingClientRect(),ve),te=ee.height,ke=F||re,le=ke.scrollHeight,de=parseFloat(W.borderBottomWidth),Se=parseFloat(ce.marginTop)||10,Te=parseFloat(ce.marginBottom)||10,_e=parseFloat(ce.minHeight)||100,Ae=nA(W),oe=5,me=5,pe=20,Ce=ue.documentElement.clientHeight-Se-Te,Ne=ue.documentElement.clientWidth,be=Ce-ee.bottom+te;let De,Ge=R==="rtl"?ee.right-he.width:ee.left,Ct=0;if(U&&Z){const rn=Fh(Z.getBoundingClientRect(),ve);De=Fh(U.getBoundingClientRect(),ve),Ge=he.left+(R==="rtl"?rn.right-De.right:rn.left-De.left);const nt=rn.top-ee.top+rn.height/2;Ct=De.top-he.top+De.height/2-nt}const Tt=be+Ct+Te+de;let Mt=Math.min(Ce,Tt);const ot=Ce-Se-Te,Kn=Tt-Mt,ms=Ne-me;L.style.left=`${Li(Ge,oe,ms-he.width)}px`,L.style.height=`${Mt}px`,L.style.maxHeight="none",L.style.marginTop=`${Se}px`,L.style.marginBottom=`${Te}px`,re.style.height="100%";const Yn=Vh(ke),vs=Kn>=Yn-Tl;vs&&(Mt=Math.min(Ce,he.height)-(Kn-Yn));const it=ee.topCe-pe||Math.ceil(Mt)+Tl=ot?"0":`${rn}px`,L.style.height=`${Mt}px`,ke.scrollTop=Vh(ke)}else L.style.bottom="0",ke.scrollTop=Kn;if(De){const rn=he.top,nt=he.height,Dt=De.top+De.height/2,qt=Li(nt>0?(Dt-rn)/nt*100:50,0,100);re.style.setProperty(tA,`50% ${qt}%`)}(Vn===Ce||Mt>=Ae)&&($.current=!0),h.context.handleScrollArrowVisibility(ke),v&&h.state.selectedIndex===null&&h.state.activeIndex===null&&h.context.listRef.current[0]!=null&&h.set("activeIndex",0)}finally{M()}},[h,I,L,B,N,A,q,F,v,R,k]),x.useEffect(()=>{if(!N||!L||!I)return;const re=Cn(L);function M(U){h.context.setOpen(!1,qe(k4,U))}return St(re,"resize",M)},[h,N,L,I]);const J={...F?{role:"presentation"}:{role:"listbox","aria-multiselectable":b||void 0,"aria-readonly":y||void 0,id:`${D}-list`},onKeyDown(re){P&&Rh.has(re.key)&&re.stopPropagation()},onScroll(re){F||Q(re.currentTarget)},...N&&{style:F?{height:"100%"}:NF},className:!F&&N?JE.className:void 0},Y=yt("div",t,{ref:[a,h.context.popupRef],state:G,stateAttributesMapping:MF,props:[z,J,xf(H),p]});return s.jsxs(x.Fragment,{children:[!E&&JE.getElement(C),s.jsx(mh,{context:j,modal:!1,disabled:!_,openInteractionType:O,returnFocus:f,restoreFocus:!0,children:Y})]})});function nA(e){const t=e.maxHeight;return t.endsWith("px")&&parseFloat(t)||1/0}function Vh(e){return XE(e.scrollHeight,e.clientHeight)}function sA(e){return kT.getScale(e)}function vf(e,t,a){return e/a[t]}function Fh(e,t){return nf({x:vf(e.x,"x",t),y:vf(e.y,"y",t),width:vf(e.width,"x",t),height:vf(e.height,"y",t)})}const rA=[["transform","none"],["scale","1"],["translate","0 0"]];function IF(e){const{style:t}=e,a={};for(const[o,c]of rA)a[o]=t.getPropertyValue(o),t.setProperty(o,c,"important");return()=>{for(const[o]of rA){const c=a[o];c?t.setProperty(o,c):t.removeProperty(o)}}}const aA=x.createContext(void 0);function lj(){const e=x.useContext(aA);if(!e)throw new Error(un(57));return e}const PF=x.memo(x.forwardRef(function(t,a){const{render:o,className:c,style:d,value:f=null,label:p,disabled:h=!1,nativeButton:b=!1,...y}=t,v=x.useRef(null),j=tj({guess:!0,label:p,textRef:v}),w=jo(),{itemProps:S,multiple:N,disabled:k,readOnly:A}=sj(),P=k||h,R=w.useState("isActive",j.index),C=w.useState("open"),E=w.useState("isSelected",f),D=w.useState("isSelectedByFocus",j.index),I=w.useState("isItemEqualToValue"),O=j.index,_=x.useRef(null);Me(()=>{const G=w.context.valuesRef.current;return G[O]=f,()=>{delete G[O]}},[O,f,w]),Me(()=>{const G=w.state.value,J=w.state.selectedIndex;let Y=J,re;N&&Array.isArray(G)?(Y=qE(O,f,w.context.valuesRef.current,G,I,J),re=Y===O,O===J&&!re&&(w.context.selectedItemTextRef.current=null)):(re=G!==void 0&&ca(f,G,I),re&&(Y=O)),w.set("selectedIndex",Y),re&&v.current&&(w.context.selectedItemTextRef.current=v.current)},[O,N,I,w,f]);const z=x.useRef("mouse"),H=x.useRef(!1),{getButtonProps:B,buttonRef:L}=na({disabled:P,focusableWhenDisabled:!0,native:b,composite:!0}),F={disabled:P,selected:E,highlighted:R};function $(G){if(k||A)return;const J=w.state.value;if(N){const Y=Array.isArray(J)?J:[],re=E?GE(Y,f,I):[...Y,f];w.context.setValue(re,qe(af,G))}else w.context.setValue(f,qe(af,G)),w.context.setOpen(!1,qe(af,G))}function X(){w.context.selectionRef.current.dragY=0}const K={role:"option","aria-selected":E,tabIndex:C&&R?0:-1,onKeyDown(G){w.set("activeIndex",O),G.key===" "&&w.context.typingRef.current&&G.preventDefault()},onClick(G){const J=z.current!=="touch",Y=G.nativeEvent.pointerType,re=J&&Jm(G.nativeEvent)&&(Y!==void 0||R),M=J&&!re&&!H.current;H.current=!1,!(P||M)&&$(G.nativeEvent)},onPointerEnter(G){z.current=G.pointerType},onPointerMove(G){if(G.pointerType==="mouse"&&G.buttons===1){const J=w.context.selectionRef.current;J.dragY+=G.movementY,J.dragY**2>=64&&(J.allowUnselectedMouseUp=!0)}},onPointerDown(G){z.current=G.pointerType,H.current=!0,X()},onMouseUp(){if(X(),P||z.current==="touch"||H.current)return;const G=!w.context.selectionRef.current.allowSelectedMouseUp&&E,J=!w.context.selectionRef.current.allowUnselectedMouseUp&&!E;G||J||(H.current=!0,_.current?.click(),H.current=!1)}},q=yt("div",t,{ref:[L,a,j.ref,_],state:F,props:[S,K,y,B]}),Q=x.useMemo(()=>({selected:E,index:O,textRef:v,selectedByFocus:D}),[E,O,v,D]);return s.jsx(aA.Provider,{value:Q,children:q})})),_F=x.forwardRef(function(t,a){const{selected:o}=lj();return t.keepMounted||o?s.jsx(LF,{...t,ref:a}):null}),LF=x.memo(x.forwardRef((e,t)=>{const{render:a,className:o,style:c,keepMounted:d,...f}=e,{selected:p}=lj(),h=x.useRef(null),{transitionStatus:b,setMounted:y}=Oi(p),j=yt("span",e,{ref:[t,h],state:{selected:p,transitionStatus:b},props:[{"aria-hidden":!0,children:"✔️"},f],stateAttributesMapping:co});return oa({batch:!0,enabled:!p,open:p,ref:h,onComplete(){p||y(!1)}}),j})),zF=x.memo(x.forwardRef(function(t,a){const{index:o,textRef:c,selectedByFocus:d}=lj(),f=jo(),{render:p,className:h,style:b,...y}=t,v=x.useCallback(w=>{w&&(o===0&&(f.context.firstItemTextRef.current=w),d&&(f.context.selectedItemTextRef.current=w))},[f,o,d]);return yt("div",t,{ref:[v,a,c],props:y})})),ut=pF,dt=yF;function ft({className:e,children:t,...a}){return s.jsxs(bF,{"data-slot":"select-trigger",className:Ue("inline-flex h-[30px] min-w-0 cursor-pointer items-center justify-between gap-1.5 rounded-md border border-control-border bg-control px-2.5","[&>span]:min-w-0 [&>span]:truncate","text-[12.5px] font-normal text-foreground","transition-colors duration-150 ease-out","hover:border-control-border-hover hover:bg-control-hover","focus-visible:border-primary focus-visible:shadow-focus focus-visible:outline-none","data-disabled:cursor-not-allowed data-disabled:bg-control data-disabled:text-muted-foreground data-disabled:opacity-60",e),...a,children:[t,s.jsx(jF,{className:"flex flex-none text-muted-foreground transition-transform duration-[180ms] data-popup-open:rotate-180",children:s.jsx("svg",{viewBox:"0 0 10 6",className:"size-2.5","aria-hidden":"true",children:s.jsx("path",{d:"M1 1l4 4 4-4",stroke:"currentColor",strokeWidth:"1.4",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"})})})]})}function pt({className:e,sideOffset:t=4,children:a,...o}){return s.jsx(wF,{children:s.jsx(TF,{sideOffset:t,alignItemWithTrigger:!1,className:"z-[35]",children:s.jsx(DF,{"data-slot":"select-content",className:Ue("max-h-[260px] min-w-[var(--anchor-width)] overflow-y-auto overscroll-contain rounded-lg border border-border-strong bg-raised p-[5px] shadow-3","outline-none","data-open:animate-in data-open:fade-in-0","data-closed:animate-out data-closed:fade-out-0",e),...o,children:a})})})}function $e({className:e,children:t,...a}){return s.jsxs(PF,{"data-slot":"select-item",className:Ue("flex min-h-7 cursor-pointer items-center gap-2 rounded-sm px-[9px] text-[12.5px] leading-[1.4] text-foreground select-none","transition-colors duration-[120ms] ease-out","data-[highlighted]:bg-nav-hover","data-[selected]:bg-primary-soft data-[selected]:font-semibold data-[selected]:text-primary-fg","data-[highlighted]:data-[selected]:bg-primary-tint","data-disabled:pointer-events-none data-disabled:font-normal data-disabled:text-muted-foreground",e),...a,children:[s.jsx(zF,{className:"min-w-0 flex-1 truncate",children:t}),s.jsx(_F,{className:"flex flex-none text-primary",children:s.jsx("svg",{viewBox:"0 0 12 12",className:"size-3","aria-hidden":"true",children:s.jsx("path",{d:"M2.5 6.2 4.8 8.5 9.5 3.8",stroke:"currentColor",strokeWidth:"1.8",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"})})})]})}function En({options:e,value:t,onValueChange:a,disabled:o=!1,className:c,...d}){const f=x.useRef(null),p=x.useRef(new Map),[h,b]=x.useState({left:0,width:0,ready:!1}),[y,v]=x.useState(!1),j=x.useCallback(()=>{const w=f.current,S=p.current.get(t);if(!w||!S){b(R=>R.ready?{...R,ready:!1}:R);return}const N=w.getBoundingClientRect(),k=S.getBoundingClientRect(),A=k.left-N.left-w.clientLeft,P=k.width;b(R=>R.ready&&R.left===A&&R.width===P?R:{left:A,width:P,ready:!0})},[t]);return x.useLayoutEffect(()=>{j();const w=f.current;if(!w||typeof ResizeObserver>"u")return;const S=new ResizeObserver(()=>j());S.observe(w);for(const N of p.current.values())S.observe(N);return()=>S.disconnect()},[j,e]),x.useEffect(()=>{if(!h.ready||y)return;const w=requestAnimationFrame(()=>v(!0));return()=>cancelAnimationFrame(w)},[h.ready,y]),s.jsxs(zE,{ref:f,"data-slot":"segmented-control",className:Ue("relative inline-flex gap-0.5 rounded-md border border-control-border bg-control p-0.5",c),value:t,disabled:o,onValueChange:w=>a(w),...d,children:[s.jsx("span",{"aria-hidden":"true","data-slot":"segmented-thumb","data-ready":h.ready?"true":"false","data-animate":y?"true":"false",className:Ue("pointer-events-none absolute top-0.5 bottom-0.5 left-0 rounded-sm bg-primary-soft","data-[ready=false]:opacity-0","data-[animate=true]:transition-[transform,width] data-[animate=true]:duration-200 data-[animate=true]:ease-in-out"),style:{transform:`translateX(${h.left}px)`,width:h.width}}),e.map(w=>s.jsxs(PE,{value:w.value,"data-slot":"segmented-item",disabled:w.disabled,"data-zero":w.count===0?"true":void 0,className:Ue("group/seg relative z-[1] inline-flex h-6 items-center gap-[5px] rounded-sm border-0 bg-transparent px-2.5","text-xs font-medium whitespace-nowrap text-subtle select-none","transition-[background-color,color] duration-150 ease-out","hover:bg-nav-hover hover:text-foreground","data-checked:bg-transparent data-checked:text-primary-fg data-checked:hover:bg-transparent","data-disabled:cursor-not-allowed data-disabled:opacity-40","data-[zero=true]:data-unchecked:opacity-45"),ref:S=>{S?p.current.set(w.value,S):p.current.delete(w.value)},children:[w.label,w.count!==void 0&&s.jsx("span",{className:Ue("min-w-4 rounded-pill bg-surface-3 px-[5px] text-center text-[10.5px] font-semibold tabular-nums text-muted-foreground","group-data-checked/seg:bg-primary-tint group-data-checked/seg:text-primary-fg"),children:w.count})]},w.value))]})}const BF=x.createContext(void 0);function HF(){return x.useContext(BF)}const UF=x.forwardRef(function(t,a){const{className:o,defaultPressed:c=!1,disabled:d=!1,form:f,onPressedChange:p,pressed:h,render:b,type:y,value:v,nativeButton:j=!0,style:w,...S}=t,N=ka(v||void 0),k=HF(),A=k?.value??[],P=(d||k?.disabled)??!1,[R,C]=Ka({controlled:k?N!==void 0&&A.indexOf(N)>-1:h,default:c,name:"Toggle",state:"pressed"}),{getButtonProps:E,buttonRef:D}=na({disabled:P,native:j}),I={disabled:P,pressed:R},O=[D,a],_=[{"aria-pressed":R,onClick(B){const L=!R,F=qe(Qn,B.nativeEvent);p?.(L,F),!F.isCanceled&&(N&&k?.setGroupValue?.(N,L,F),!F.isCanceled&&C(L))}},S,E],z=yt("button",t,{enabled:!k,state:I,ref:O,props:_}),H=x.useMemo(()=>({disabled:P,focusableWhenDisabled:!1}),[P]);return k?s.jsx(ME,{tag:"button",render:b,className:o,style:w,metadata:H,state:I,refs:O,props:_}):z}),VF=Xc(["inline-flex shrink-0 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap border","font-medium transition-[background-color,border-color,color] duration-150 ease-out","outline-none select-none disabled:pointer-events-none disabled:opacity-45","[&_svg]:pointer-events-none [&_svg]:shrink-0","data-pressed:border-primary-bd data-pressed:bg-primary-soft data-pressed:font-semibold data-pressed:text-primary-fg","data-pressed:hover:bg-primary-tint"],{variants:{variant:{default:"border-transparent bg-transparent text-subtle hover:bg-nav-hover hover:text-foreground",outline:"border-control-border bg-control text-foreground shadow-1 hover:border-control-border-hover hover:bg-control-hover"},size:{default:"h-[30px] rounded-md px-3 text-[12.5px]",xs:"h-6 rounded-sm px-2 text-[11.5px]",sm:"h-[26px] rounded-sm px-2.5 text-[12px]",lg:"h-9 rounded-md px-4 text-[13px]"}},defaultVariants:{variant:"default",size:"default"}});function FF({className:e,variant:t,size:a,...o}){return s.jsx(UF,{"data-slot":"toggle",className:Ue(VF({variant:t,size:a}),e),...o})}function $F(e,t,a,o,c,d,f,p,h,b=2){const y=i4(a.current,{event:e,orientation:o,loopFocus:c,rtl:d,cols:b,disabledIndices:f,minIndex:p,maxIndex:h,prevIndex:t>h?p:t,stopEvent:!0});return mo(a.current,y)?void 0:y}const lA=x.createContext(void 0),oA=x.createContext(void 0),iA=x.createContext(void 0),cA=x.createContext(!1),uA=x.createContext("");function Ta(){const e=x.useContext(lA);if(!e)throw new Error(un(22));return e}function $h(){const e=x.useContext(oA);if(!e)throw new Error(un(23));return e}function yf(){const e=x.useContext(iA);if(!e)throw new Error(un(24));return e}function dA(){return x.useContext(uA)}function qF(){return x.useContext(cA)}const GF={id:e=>e.id,labelId:e=>e.labelId,items:e=>e.items,selectedValue:e=>e.selectedValue,hasSelectionChips:e=>{const t=e.selectedValue;return Array.isArray(t)&&t.length>0},hasSelectedValue:e=>{const{selectedValue:t,selectionMode:a}=e;return t==null?!1:a==="multiple"&&Array.isArray(t)?t.length>0:!0},hasNullItemLabel:(e,t)=>t?KE(e.items):!1,open:e=>e.open,mounted:e=>e.mounted,forceMounted:e=>e.forceMounted,inline:e=>e.inline,activeIndex:e=>e.activeIndex,selectedIndex:e=>e.selectedIndex,isActive:(e,t)=>e.activeIndex===t,isSelected:(e,t)=>{const a=e.isItemEqualToValue,o=e.selectedValue;return Array.isArray(o)?o.some(c=>ca(t,c,a)):ca(t,o,a)},transitionStatus:e=>e.transitionStatus,popupProps:e=>e.popupProps,listProps:e=>e.listProps,inputProps:e=>e.inputProps,triggerProps:e=>e.triggerProps,itemProps:e=>e.itemProps,positionerElement:e=>e.positionerElement,listElement:e=>e.listElement,popupId:e=>e.popupId,triggerElement:e=>e.triggerElement,inputElement:e=>e.inputElement,inputGroupElement:e=>e.inputGroupElement,popupSide:e=>e.popupSide,openMethod:e=>e.openMethod,inputInsidePopup:e=>e.inputInsidePopup,inputOwnsFormValue:e=>e.inputOwnsFormValue,selectionMode:e=>e.selectionMode,name:e=>e.name,form:e=>e.form,disabled:e=>e.disabled,readOnly:e=>e.readOnly,required:e=>e.required,grid:e=>e.grid,virtualized:e=>e.virtualized,itemToStringLabel:e=>e.itemToStringLabel,isItemEqualToValue:e=>e.isItemEqualToValue,modal:e=>e.modal,autoHighlight:e=>e.autoHighlight};function fA(e){return e==null?void 0:`${e}-popup`}function KF(e,t){return(a,o)=>a==null?!1:e.contains(a,o,t)}const pA=new Map;function YF(e={}){const t={usage:"search",sensitivity:"base",ignorePunctuation:!0,...e},a=`${hy(e.locale)}|${JSON.stringify(t)}`,o=pA.get(a);if(o)return o;const c=new Intl.Collator(e.locale,t),d={contains(f,p,h){if(!p)return!0;const b=wo(f,h);for(let y=0;y<=b.length-p.length;y+=1)if(c.compare(b.slice(y,y+p.length),p)===0)return!0;return!1},startsWith(f,p,h){if(!p)return!0;const b=wo(f,h);return c.compare(b.slice(0,p.length),p)===0},endsWith(f,p,h){if(!p)return!0;const b=wo(f,h),y=p.length;return b.length>=y&&c.compare(b.slice(b.length-y),p)===0}};return pA.set(a,d),d}const XF=YF;function QF(e,t=!1){const{overflowY:a}=yr(e);return a!=="auto"&&a!=="scroll"?!1:t?e.clientHeight>0:e.scrollHeight>e.clientHeight}const mA=Symbol("none"),oj={value:mA,index:-1};function ZF(e,t,a){const o=e.get(t);if(o!==void 0||a===_h)return o;for(const[c,d]of e)if(ca(c,t,a))return d}function WF(e){const{id:t,onOpenChangeComplete:a,defaultSelectedValue:o=null,selectedValue:c,onSelectedValueChange:d,defaultInputValue:f,inputValue:p,open:h,defaultOpen:b=!1,selectionMode:y,onItemHighlighted:v,name:j,form:w,disabled:S=!1,readOnly:N=!1,required:k=!1,inputRef:A,grid:P=!1,items:R,filteredItems:C,filter:E,filterQuery:D,openOnInputClick:I=!0,autoHighlight:O=!1,keepHighlight:_=!1,highlightItemOnHover:z=!0,loopFocus:H=!0,itemToStringLabel:B,itemToStringValue:L,isItemEqualToValue:F=_h,virtualized:$=!1,inline:X=!1,fillInputOnItemPress:K=!0,modal:q=!1,limit:Q=-1,autoComplete:G="list",formAutoComplete:J,locale:Y,submitOnItemClick:re=!1}=e,{clearErrors:M}=Qc(),{setDirty:U,validityData:Z,setFilled:ae,name:ce,disabled:W,setTouched:ue,setFocused:ve,validationMode:ee,validation:he}=Na(),te=gf(),ke=io({id:t}),le=XF({locale:Y}),de=Array.isArray(R)?null:R;if(de&&typeof de.label!="function")throw new Error(un(100));const Se=de?de.data:R,Te=de?.value,_e=Te?void 0:Se,Ae=x.useMemo(()=>{if(!C||!Te)return;const Oe=zh(C),Be=Oe.map(Te);let lt;return{values:Be,findItem(Qt,In){if(!lt){lt=new Map;for(let gn=0;gnde?Oe=>de.label(Oe,F,Be=>{const lt=Ae?.findItem(Be,F);return lt!=null?de.itemLabel(lt):wo(Be,B)}):B,[de,B,Ae,F]),me=x.useMemo(()=>de?Object.assign(Oe=>de.itemLabel(Oe),{selected:Oe=>wo(Oe,oe)}):B,[de,oe,B]);function pe(Oe){return wo(Oe,oe)}const[Ce,Ne]=x.useState(!1),[be,De]=x.useState(null),Ge=x.useRef(be),Ct=x.useRef([]),Tt=x.useRef([]),Mt=x.useRef(null),ot=x.useRef(null),Kn=x.useRef(null),ms=x.useRef(null),Yn=x.useRef(null),vs=x.useRef(!0),it=x.useRef(!1),$t=x.useRef(null),Vn=x.useRef(null),rn=x.useRef(null),nt=x.useRef(oj),Dt=x.useRef(null),qt=x.useRef([]),es=x.useRef(null),Fn=W||S,$n=ce??j,Dn=y==="multiple",en=y==="single",cs=p!==void 0||f!==void 0,Et=Se!==void 0,xt=C!==void 0;let jt;O==="always"?jt="always":jt=O?"input-change":!1;const[wt,Tr]=Ka({controlled:c,default:Dn?o??Ir:o,name:"Combobox",state:"selectedValue"}),ar=x.useMemo(()=>E===null?()=>!0:E!==void 0?E:KF(le,me),[E,le,me]),Fr=Ps(()=>cs?f??"":en?pe(wt):"").current,[Nn,al]=Ka({controlled:p,default:Fr,name:"Combobox",state:"inputValue"}),[ln,hc]=Ka({controlled:h,default:b,name:"Combobox",state:"open"}),sb=rj(Se),mr=!ln&&be!==null?be:String(Nn).trim(),Pa=en?pe(wt):"",Go=en&&!Ce&&mr!==""&&Pa.length===mr.length&&le.contains(Pa,mr),Ko=Go?"":D??mr,Fp=Et&&xt&&Go&&(!de||de.hasValue(wt,F)),gc=x.useMemo(()=>Se?zh(Se):Ir,[Se]),Yo=x.useMemo(()=>{if(C&&!Fp)return C;if(!Se)return Ir;if(sb){const Be=Se,lt=[];let Qt=0;for(const In of Be){if(Q>-1&&Qt>=Q)break;const gn=Q>-1?Q-Qt:1/0,Pn=Ko===""?In.items.slice(0,gn):[];if(Ko!=="")for(const hs of In.items){if(Pn.length>=gn)break;ar(hs,Ko,me)&&Pn.push(hs)}if(Pn.length>0){const hs={...In,items:Pn};lt.push(hs),Qt+=Pn.length}}return lt}if(Ko==="")return Q>-1?gc.slice(0,Q):gc;const Oe=[];for(const Be of gc){if(Q>-1&&Oe.length>=Q)break;ar(Be,Ko,me)&&Oe.push(Be)}return Oe},[C,Fp,Se,sb,Ko,Q,ar,me,gc]),Os=x.useMemo(()=>{if(Ae&&Yo===C)return Ae.values;const Oe=zh(Yo);return Te?Oe.map(Be=>Te(Be)):Oe},[Yo,C,Ae,Te]),et=Ps(()=>{let Oe=null;return X&&ln&&Et&&y!=="none"&&(Oe=bf(Os,wt,F,Dn)),new ou({id:ke,labelId:void 0,selectedValue:wt,open:ln,items:_e,selectionMode:y,name:$n,form:w,disabled:Fn,readOnly:N,required:k,grid:P,virtualized:$,openOnInputClick:I,itemToStringLabel:oe,isItemEqualToValue:F,modal:q,autoHighlight:jt,submitOnItemClick:re,hasInputValue:cs,mounted:!1,forceMounted:!1,transitionStatus:"idle",inline:X,activeIndex:null,selectedIndex:Oe,popupProps:{},listProps:{},inputProps:{},triggerProps:{},itemProps:mn,positionerElement:null,listElement:null,popupId:void 0,triggerElement:null,inputElement:null,inputGroupElement:null,popupSide:null,openMethod:null,inputInsidePopup:!0,inputOwnsFormValue:y==="none"},{onOpenChangeComplete:Kt,setOpen:Kt,setInputValue:Kt,setSelectedValue:Kt,setIndices:Kt,handleSelection:Kt,forceMount:Kt,requestSubmit:Kt,listRef:Ct,labelsRef:Tt,popupRef:Mt,emptyRef:Yn,inputRef:ot,startDismissRef:Kn,endDismissRef:ms,keyboardActiveRef:vs,chipsContainerRef:$t,clearRef:Vn,valuesRef:qt,pointerDownItemRef:es,selectionEventRef:rn},GF)}).current,zl=y==="none"?Nn:wt,rb=x.useMemo(()=>y==="none"?zl:Array.isArray(wt)?wt.map(Oe=>Ca(Oe,L)):Ca(wt,L),[zl,L,y,wt]),_a=Ie(v),Ms=Ie(a),Ys=et.useState("activeIndex"),Xo=et.useState("selectedIndex"),xc=et.useState("positionerElement"),ab=et.useState("listElement"),bc=et.useState("triggerElement"),vc=et.useState("inputElement"),yc=et.useState("inputGroupElement"),Ds=et.useState("inline"),lr=et.useState("inputInsidePopup"),Bl=et.useState("inputOwnsFormValue"),Hl=en&&!lr&&Nn===Pa,jc=Zn(bc),{mounted:Qo,setMounted:ys,transitionStatus:$p}=Oi(ln),{openMethod:lb,triggerProps:qp}=EE(ln),Ul=Ie(()=>rb);tu(lr?jc:ot,ke,zl,Ul,!Fn,j);const Vl=Ie(()=>{Se?Tt.current=Os.map(pe):et.set("forceMounted",!0)}),Zo=Ie((Oe,Be,lt)=>{if(Be===-1){if(nt.current===oj)return;nt.current=oj}else nt.current={value:Oe,index:Be};_a(Oe,C4(lt,void 0,{index:Be}))}),$r=Ie(Oe=>{const Be={};Oe.activeIndex!==void 0&&(Be.activeIndex=Oe.activeIndex),Oe.selectedIndex!==void 0&&(Be.selectedIndex=Oe.selectedIndex),et.update(Be);const lt=Oe.activeIndex;if(lt===void 0)return;const Qt=Oe.type||Qn;lt===null?Zo(void 0,-1,Qt):Zo(qt.current[lt],lt,Qt)}),qr=Ie((Oe,Be)=>{if(e.onInputValueChange?.(Oe,Be),!Be.isCanceled){if(it.current=Be.reason===Ya,Be.reason===lf){ln&&be!==null&&De(null);const lt=Be.event,Qt=lt.inputType;if(lt.type==="compositionend"||Qt!=null&&Qt!==""&&Qt!=="insertReplacementText"){const gn=Oe.trim()!=="";gn&&Ne(!0),Dt.current={hasQuery:gn};const Pn=et.state.listElement;if(!et.state.virtualized&&Pn){const hs=Mt.current;for(const Er of Kc(Pn.firstElementChild??Pn)){if(!pn(Er)||(hs?!Ze(hs,Er):Er.getAttribute("role")==="dialog"))break;if(QF(Er)){Er.scrollTop=0;break}}}gn&&jt&&et.state.activeIndex==null&&(ln||Ds)&&et.set("activeIndex",0)}}else Be.reason===Ya&&Oe===""&&et.state.inputInsidePopup&&(Dt.current={hasQuery:!1,selection:!0});al(Oe)}}),ob=Ie(Oe=>{const Be=!Oe&&lr&&!Ds&&Nn!==""&&(String(Nn).trim()===be||Nn===Pa);!Oe&&(Be||Nn===""||Hl)&&Ne(!1),De(null),Be&&qr("",qe(Ya))}),It=Ie((Oe,Be)=>{if(ln!==Oe&&(Be.reason===nu&&Et&&Os.length===0&&!Yn.current&&Be.allowPropagation(),e.onOpenChange?.(Oe,Be),!Be.isCanceled&&(Oe&&be!==null&&ob(Be.reason===lf),!Oe&&Ce&&(en?(Ds||De(mr),mr===""&&Ne(!1)):Dn&&(Ds||De(mr),lr&&$r({activeIndex:null}),(!lr||Ds)&&qr("",qe(Ya,Be.event,void 0,{isItemPress:Be.reason===af})))),hc(Oe),!Oe&&lr&&(Be.reason===xo||Be.reason===ch)&&(ue(!0),ve(!1),ee==="onBlur")))){const lt=y==="none"?Nn:wt;he.commit(lt)}}),wc=Ie((Oe,Be)=>{if(d?.(Oe,Be),Be.isCanceled)return;Tr(Oe),(y==="none"&&Mt.current&&K||en&&!et.state.inputInsidePopup)&&qr(pe(Oe),qe(Be.reason,Be.event))}),od=Ie((Oe,Be)=>{const lt=fs(Oe),Qt=rn.current??Oe;rn.current=null;const In=qe(af,Qt),gn=lt?.closest("a")?.getAttribute("href");if(gn){gn.startsWith("#")&&It(!1,In);return}if(Dn){const Pn=Array.isArray(wt)?wt:[],hs=Lh(Pn,Be,F),Er=hs?GE(Pn,Be,F):[...Pn,Be];if(wc(Er,In),In.isCanceled||!(ot.current?ot.current.value.trim()!=="":!1))return;if(et.state.inputInsidePopup){qr("",qe(Ya,In.event,void 0,{isItemPress:!0}));const Kr=Dt.current;Kr&&!hs&&(Kr.toggledValue=Be)}else It(!1,In)}else{if(wc(Be,In),In.isCanceled)return;It(!1,In)}}),id=Ie(()=>{const Oe=he.inputRef.current?.form??et.state.inputElement?.form;Oe&&typeof Oe.requestSubmit=="function"&&Oe.requestSubmit()}),Gr=Ie(()=>{if(ys(!1),Ms?.(!1),Ne(!1),De(null),$r(y==="none"?{activeIndex:null,selectedIndex:null}:{activeIndex:null}),Dn&&ot.current&&ot.current.value!==""&&!it.current&&qr("",qe(Ya)),en)if(et.state.inputInsidePopup)ot.current&&ot.current.value!==""&&qr("",qe(Ya));else{const Oe=pe(wt);ot.current&&ot.current.value!==Oe&&qr(Oe,qe(Oe===""?Ya:Qn))}}),hr=x.useMemo(()=>Ds&&xc?{current:xc.closest('[role="dialog"]')}:Mt,[Ds,xc]);oa({enabled:!e.actionsRef,open:ln,ref:hr,onComplete(){ln||Gr()}}),x.useImperativeHandle(e.actionsRef,()=>({unmount:Gr}),[Gr]),Me(function(){const Be=Ge.current!==null&&be===null;if(Ge.current=be,ln&&(!Be||!Et)||(ln||(es.current=null),y==="none"))return;const lt=Et?Os:qt.current;$r({selectedIndex:bf(lt,wt,F,Dn)})},[ln,be,wt,y,Dn,Et,Os,F,$r]),Me(()=>{Se&&(qt.current=Os,Ct.current.length=Os.length)},[Se,Os]),Me(()=>{const Oe=Dt.current;if(Oe){const hs=ln||Ds||et.state.positionerElement?.hidden===!1;if(Oe.hasQuery)jt&&hs&&et.set("activeIndex",0),Dt.current=null;else if(String(Nn).trim()===""&&(Dt.current=null,hs)){const Er=Oe.selection;jt==="always"&&!Er&&et.state.selectionMode==="none"&&et.set("activeIndex",0),queueMicrotask(()=>{if(!et.state.open&&!et.state.inline||ot.current&&ot.current.value.trim()!=="")return;const ha=et.state.selectedValue,Kr=et.state.selectionMode==="multiple";if(Kr&&Array.isArray(ha)?ha.length>0:et.state.selectionMode!=="none"&&ha!=null){const Bs=Et||xt?Os:qt.current,za=cu(Bs,Oe.toggledValue,et.state.isItemEqualToValue);et.set("activeIndex",za!==-1?za:bf(Bs,ha,et.state.isItemEqualToValue,Kr))}else Er?et.set("activeIndex",null):jt==="always"&&et.set("activeIndex",0)})}}if(!ln&&!Ds)return;const lt=Et||xt?Os:qt.current,Qt=et.state.activeIndex;if(Qt==null){if(jt==="always"&<.length>0){et.set("activeIndex",0);return}Zo(void 0,-1,Qn);return}if(Qt>=lt.length){Zo(void 0,-1,Qn),et.set("activeIndex",null);return}const In=lt[Qt],gn=nt.current.value,Pn=gn!==mA&&ca(In,gn,et.state.isItemEqualToValue);(nt.current.index!==Qt||!Pn)&&Zo(In,Qt,Qn)},[Ys,jt,Zo,xt,Et,Os,Ds,ln,et,Nn]),Me(()=>{if(y==="none"){ae(String(Nn)!=="");return}ae(Dn?Array.isArray(wt)&&wt.length>0:wt!=null)},[ae,y,Nn,wt,Dn]),x.useEffect(()=>{Et&&jt&&Os.length===0&&$r({activeIndex:null})},[Et,jt,Os.length,$r]);function ib(){ln&&mr!==""&&mr!==String(Fr)&&!Hl&&Ne(!0)}function WS(){ln&&be!==null&&ob(!1)}let cd=!1;function Gp(){!cd&&Nn!==Pa&&(cd=!0,qr(Pa,qe(Qn)))}function JS(){y!=="none"&&(M($n),U($E(wt,Z.initialValue,F)),he.change(wt),en&&!cs&&!lr&&Gp())}function gr(){en&&!cs&&!lr&&!Ce&&Gp()}function Kp(){y==="none"&&(M($n),U(Nn!==Z.initialValue),he.change(Nn))}ia(mr,ib),ia(ln,WS),ia(wt,JS),ia(Pa,gr),ia(Se,gr),ia(Nn,Kp);const Sc=$T({open:Ds?!0:ln,onOpenChange:It,elements:{reference:lr?bc:vc,floating:xc}}),ud=P?"grid":"listbox",La=ln||Ds,Yp=La?"true":"false",Nc=x.useMemo(()=>{const Oe=vc?.tagName==="INPUT",Be=vc==null||Oe,lt=Be||La,Qt=Be?{autoComplete:"off",spellCheck:"false",autoCorrect:"off",autoCapitalize:"none"}:{};return lt&&(Qt.role="combobox",Qt["aria-expanded"]=Yp,Qt["aria-haspopup"]=ud,Qt["aria-controls"]=La?ab?.id:void 0,Qt["aria-autocomplete"]=N?"none":G),{reference:Qt,floating:{role:"presentation"}}},[vc,La,Yp,ud,ab?.id,G,N]),Fl=hh(Sc,{enabled:!Fn&&I,event:"mousedown-only",toggle:!1,touchOpenDelay:lr?0:100,reason:S4}),dd=pf(Sc,{enabled:!Fn&&!Ds,outsidePressEvent:{mouse:"sloppy",touch:"intentional"},bubbles:Ds?!0:void 0,outsidePress(Oe){const Be=fs(Oe);return!Ze(bc,Be)&&!Ze(Vn.current,Be)&&!Ze($t.current,Be)&&!Ze(yc,Be)}}),$l=XT(Sc,{enabled:!Fn,id:ke,listRef:Ct,activeIndex:Ys,selectedIndex:Xo,virtual:!0,loopFocus:H,allowEscape:H&&!jt,focusItemOnOpen:Ce||y==="none"&&!jt?!1:"auto",focusItemOnHover:z,resetOnPointerLeave:!_,orientation:P?"horizontal":void 0,rtl:te==="rtl",disabledIndices:Ir,grid:P?$F:void 0,onNavigate(Oe,Be){!Be&&!ln||$p==="ending"||$r(Be?{activeIndex:Oe,type:vs.current?I1:P1}:{activeIndex:Oe})}}),Xp=x.useMemo(()=>ta($l.reference,{onKeyDown(Oe){P&&et.state.activeIndex==null&&(Oe.key==="ArrowLeft"||Oe.key==="ArrowRight")&&Oe.preventBaseUIHandler()}},dd.reference,Fl.reference,Nc.reference),[$l.reference,dd.reference,Fl.reference,Nc.reference,P,et]),fd=x.useMemo(()=>ta(mf,dd.floating),[dd.floating]),cb=x.useMemo(()=>ta($l.floating,Nc.floating),[$l.floating,Nc.floating]),ub=x.useMemo(()=>{const Oe=$l.item;return Oe?{...Oe,onFocus:void 0}:mn},[$l.item]);et.useContextCallback("setOpen",It),et.useContextCallback("setInputValue",qr),et.useContextCallback("setSelectedValue",wc),et.useContextCallback("setIndices",$r),et.useContextCallback("handleSelection",od),et.useContextCallback("forceMount",Vl),et.useContextCallback("requestSubmit",id),et.useContextCallback("onOpenChangeComplete",a),BE(()=>{et.update({inline:X,popupProps:fd,listProps:cb,inputProps:Xp,triggerProps:qp,itemProps:ub})});const kc={id:ke,selectedValue:wt,open:ln,mounted:Qo,transitionStatus:$p,items:_e,inline:X,popupProps:fd,listProps:cb,inputProps:Xp,triggerProps:qp,itemProps:ub,openMethod:lb,selectionMode:y,name:$n,form:w,disabled:Fn,readOnly:N,required:k,grid:P,virtualized:$,openOnInputClick:I,itemToStringLabel:oe,modal:q,autoHighlight:jt,isItemEqualToValue:F,submitOnItemClick:re,hasInputValue:cs};Me(()=>{et.update({...kc,inputOwnsFormValue:y==="none"&&(X||!et.state.inputInsidePopup)})},[et,...Object.values(kc)]);const ma=sa(A,he.inputRef),Qp=x.useMemo(()=>({query:mr,hasItems:Et,filteredItems:Yo,flatFilteredValues:Os}),[mr,Et,Yo,Os]),Zp=x.useMemo(()=>Array.isArray(zl)?"":Ca(zl,L),[zl,L]),Wo=Dn&&Array.isArray(wt)&&wt.length>0,ll=Dn||y==="none"&&Bl?void 0:$n,db=x.useMemo(()=>!Dn||!Array.isArray(wt)||!$n?null:wt.map(Oe=>{const Be=Ca(Oe,L);return s.jsx("input",{type:"hidden",form:w,name:$n,value:Be,disabled:Fn},Be)}),[Dn,wt,w,$n,L,Fn]),Wp=s.jsxs(x.Fragment,{children:[e.children,s.jsx("input",{...he.getValidationProps(Fn,{onFocus(){if(lr){bc?.focus();return}(ot.current||bc)?.focus()},onChange(Oe){if(Oe.nativeEvent.defaultPrevented||Fn||N)return;const Be=Oe.currentTarget.value,lt=Be.toLowerCase(),Qt=qe(Qn,Oe.nativeEvent),In=()=>qt.current.findIndex(Pn=>Ca(Pn,L).toLowerCase()===lt||pe(Pn).toLowerCase()===lt);function gn(){if(Dn)return;if(y==="none"){qr(Be,Qt);return}let Pn=In();Pn===-1&&(Pn=qt.current.findIndex((Er,ha)=>{const Kr=Tt.current[ha];return Kr!=null&&Kr.toLowerCase()===lt}));const hs=Pn===-1?void 0:qt.current[Pn];hs!=null&&wc?.(hs,Qt)}en&&(Vl(),Se&&In()===-1&&et.set("forceMounted",!0)),queueMicrotask(gn)}}),id:ke&&ll==null?`${ke}-hidden-input`:void 0,form:w,name:ll,autoComplete:J,disabled:Fn,required:k&&!Wo,readOnly:N,value:Zp,ref:ma,style:ll?su:_i,tabIndex:-1,"aria-hidden":!0,suppressHydrationWarning:!0}),db]});return s.jsx(lA.Provider,{value:et,children:s.jsx(oA.Provider,{value:Sc,children:s.jsx(cA.Provider,{value:Et,children:s.jsx(iA.Provider,{value:Qp,children:s.jsx(uA.Provider,{value:Nn,children:Wp})})})})})}function JF(e){const{multiple:t=!1,defaultValue:a,value:o,onValueChange:c,autoComplete:d,...f}=e;return s.jsx(WF,{...f,selectionMode:t?"multiple":"single",selectedValue:o,defaultSelectedValue:a,onSelectedValueChange:c,formAutoComplete:d})}const e6="data-popup-side",t6="data-list-empty",hA={...Yv,...Ti,popupSide:e=>e?{[e6]:e}:null,listEmpty:e=>e?{[t6]:""}:null},n6=x.createContext(void 0);function s6(){return x.useContext(n6)}const gA=x.createContext(void 0);function ij(e){const t=x.useContext(gA);if(t===void 0&&!e)throw new Error(un(21));return t}const xA=x.forwardRef(function(t,a){const o=Ta(),{buttonRef:c,getButtonProps:d}=na({native:!1}),f=sa(a,c);function p(b){o.context.setOpen(!1,qe(dy,b.nativeEvent,b.currentTarget))}const h=d({onClick:p});return s.jsx("span",{ref:f,...h,"aria-label":"Dismiss",tabIndex:void 0,style:su})});function bA(e){const t=e.useState("mounted"),a=e.useState("popupSide"),o=e.useState("positionerElement");return t&&o?a:null}function qh(){return yf().filteredItems.length===0}function r6(e){return e==="rtl"?["ArrowRight","ArrowLeft"]:["ArrowLeft","ArrowRight"]}function a6(e,t){const a=e>=t-1?t-2:e;return a>=0?a:void 0}function vA(e,t,a){const o=e.context.listRef.current[t];o&&(e.context.selectionEventRef.current=a,o.click(),e.context.selectionEventRef.current=null)}const l6=x.forwardRef(function(t,a){const{render:o,className:c,disabled:d=!1,id:f,style:p,...h}=t,{state:b,disabled:y,setTouched:v,setFocused:j,validationMode:w,validation:S}=Na(),{labelId:N}=yl(),k=s6(),P=!!ij(!0),R=Ta(),C=dA(),E=gf(),D=R.useState("required"),I=R.useState("disabled"),O=R.useState("readOnly"),_=R.useState("name"),z=R.useState("form"),H=R.useState("selectionMode"),B=R.useState("autoHighlight"),L=R.useState("inputProps"),F=R.useState("triggerProps"),$=R.useState("open"),X=R.useState("mounted"),K=R.useState("selectedValue"),q=R.useState("id"),Q=R.useState("inline"),G=R.useState("modal"),J=!!B,Y=bA(R),re=y||I||d,M=qh(),U=P||Q,Z=!U||G,ae=ka(f??(U?void 0:q)),ce=P?n1:b,[W,ue]=x.useState(null),ve=x.useRef(!1),ee=x.useRef(null),he=x.useRef(!1),te=H==="none"&&!P,ke=Ie(me=>{const pe=P||R.state.inline;pe&&!R.state.hasInputValue&&R.context.setInputValue("",qe(Qn)),R.update({inputElement:me,inputInsidePopup:pe,inputOwnsFormValue:te})}),le=P?h:S.getValidationProps(re,h);function de(){R.context.setIndices({activeIndex:null,selectedIndex:null,type:R.context.keyboardActiveRef.current?I1:P1})}function Se(){R.context.keyboardActiveRef.current=!1}const Te={...ce,open:$,disabled:re,readOnly:O,popupSide:Y,listEmpty:M};function _e(me){if(!k)return;let pe;const{highlightedChipIndex:Ce}=k,Ne=k.chipsRef.current.length,[be,De]=r6(E);return Ce!==void 0?(me.key===be?(me.preventDefault(),Ce>0?pe=Ce-1:pe=void 0):me.key===De?(me.preventDefault(),Ce0&&(me.preventDefault(),pe=Ne>0?Ne-1:void 0),pe)}const Ae=yt("input",t,{state:Te,ref:[a,R.context.inputRef,ke],props:[L,F,{value:W??C,"aria-readonly":O||void 0,"aria-required":D||void 0,"aria-labelledby":N,disabled:re,readOnly:O,required:H==="none"?D:void 0,form:z,...te&&_&&{name:_},id:ae,onFocus(){if(j(!0),!Q||!he.current)return;he.current=!1;const me=ee.current;me==null||!Object.hasOwn(R.context.valuesRef.current,me)||R.context.setIndices({activeIndex:me})},onBlur(){v(!0),j(!1);const me=R.state.activeIndex;if(Q&&me!==null&&B!=="always"&&(ee.current=me,he.current=!0,R.context.setIndices({activeIndex:null})),w==="onBlur"){const pe=H==="none"?C:K;S.commit(pe)}},onCompositionStart(me){Ym||(ve.current=!0,ue(me.currentTarget.value))},onCompositionEnd(me){ve.current=!1;const pe=me.currentTarget.value;ue(null),R.context.setInputValue(pe,qe(lf,me.nativeEvent))},onChange(me){const pe=me.nativeEvent,Ce=pe.inputType,Ne=!Ce||Ce==="insertReplacementText",be=ve.current||!Ne;function De(Mt){O||re||!Mt||!be||(R.context.setOpen(!0,qe(lf,pe)),J||de())}if(ve.current){const Mt=me.currentTarget.value;ue(Mt),Mt===""&&!R.state.openOnInputClick&&!R.state.inputInsidePopup&&R.context.setOpen(!1,qe(Ya,pe));const ot=Mt.trim(),Kn=J&&ot!=="";De(ot),$&&R.state.activeIndex!==null&&!Kn&&de();return}const Ge=qe(lf,pe);if(R.context.setInputValue(me.currentTarget.value,Ge),Ge.isCanceled)return;const Ct=me.currentTarget.value==="",Tt=qe(Ya,pe);Ct&&!R.state.inputInsidePopup&&(H==="single"&&R.context.setSelectedValue(null,Tt),R.state.openOnInputClick||R.context.setOpen(!1,Tt)),De(me.currentTarget.value.trim()),$&&R.state.activeIndex!==null&&!J&&de()},onKeyDown(me){if(me.ctrlKey||me.shiftKey||me.altKey||me.metaKey)return;if(R.context.keyboardActiveRef.current=!0,re||O){O&&me.key==="Enter"&&$&&R.state.activeIndex!==null&&Cs(me);return}const pe=me.currentTarget,Ce=pe.scrollWidth-pe.clientWidth,Ne=E==="rtl";if(me.key==="Home"){Cs(me);const Ge=c1&&Ne?pe.value.length:0;pe.setSelectionRange(Ge,Ge),pe.scrollLeft=0;return}if(me.key==="End"){Cs(me);const Ge=c1&&Ne?0:pe.value.length;pe.setSelectionRange(Ge,Ge),pe.scrollLeft=Ne?-Ce:Ce;return}if(!X&&me.key==="Escape"){const Ge=H==="multiple"&&Array.isArray(K)?K.length===0:K===null,Ct=qe(nu,me.nativeEvent),Tt=H==="multiple"?[]:null;R.context.setInputValue("",Ct),R.context.setSelectedValue(Tt,Ct),!Ge&&!R.state.inline&&!Ct.isPropagationAllowed&&me.stopPropagation();return}if(k&&me.key==="Backspace"&&pe.value===""&&k.highlightedChipIndex===void 0&&Array.isArray(K)&&K.length>0){const Ge=k.chipsRef.current.length,Ct=Ge>0?Ge-1:K.length-1,Tt=K.filter((Mt,ot)=>ot!==Ct);de(),R.context.setSelectedValue(Tt,qe(Qn,me.nativeEvent));return}const be=k?.highlightedChipIndex!==void 0,De=_e(me);if(k?.setHighlightedChipIndex(De),De!==void 0?k?.chipsRef.current[De]?.focus():be&&R.context.inputRef.current?.focus(),me.which!==229&&me.key==="Enter"&&$){const Ge=R.state.activeIndex,Ct=me.nativeEvent;if(Ge===null){if(Q)return;R.context.setOpen(!1,qe(Qn,Ct));return}Cs(me),vA(R,Ge,Ct)}},onPointerMove:Se,onPointerDown:Se},le],stateAttributesMapping:hA}),oe=P?s.jsx(r1.Provider,{value:s1,children:Ae}):Ae;return s.jsxs(x.Fragment,{children:[$&&Z&&s.jsx(xA,{ref:R.context.startDismissRef}),oe]})}),o6=x.forwardRef(function(t,a){const{render:o,className:c,nativeButton:d=!0,disabled:f=!1,id:p,style:h,...b}=t,{state:y,disabled:v,setTouched:j,setFocused:w,validationMode:S,validation:N}=Na(),{labelId:k}=yl(),A=Ta(),P=A.useState("selectionMode"),R=A.useState("disabled"),C=A.useState("readOnly"),E=A.useState("required"),D=A.useState("positionerElement"),I=A.useState("listElement"),O=A.useState("popupId"),_=A.useState("triggerProps"),z=A.useState("inputInsidePopup"),H=A.useState("id"),B=A.useState("labelId"),L=A.useState("open"),F=A.useState("selectedValue"),$=A.useState("activeIndex"),X=A.useState("selectedIndex"),K=A.useState("hasSelectedValue"),q=$h(),Q=dA(),G=er(),J=v||R||f,Y=qh(),re=bA(A);io({id:z?p:void 0});const M=z?p??H:p,U=QE(k,B);let Z;L&&z?Z=O??fA(H):L&&(Z=I?.id);const ae=x.useRef("");function ce(le){ae.current=le.pointerType}const{reference:W}=QT(q,{enabled:!L&&!C&&!R&&P==="single",listRef:A.context.labelsRef,activeIndex:$,selectedIndex:X,onMatch(le){const de=A.context.valuesRef.current[le];de!==void 0&&A.context.setSelectedValue(de,qe(Qn))}}),{reference:ue}=hh(q,{enabled:!R,event:"mousedown"}),{buttonRef:ve,getButtonProps:ee}=na({native:d,disabled:J}),he={...y,readOnly:C,open:L,disabled:J,popupSide:re,listEmpty:Y,placeholder:P==="none"?!1:!K},te=Ie(le=>{A.set("triggerElement",le)});return yt("button",t,{ref:[a,ve,te],state:he,props:[_,ue,W,{id:M,tabIndex:z?0:-1,role:z?"combobox":void 0,"aria-expanded":L,"aria-haspopup":z?"dialog":"listbox","aria-controls":Z,"aria-required":z&&E||void 0,"aria-readonly":z&&C||void 0,"aria-labelledby":U,onPointerDown:ce,onPointerEnter:ce,onFocus(){w(!0),!J&&G.start(0,A.context.forceMount)},onBlur(le){if(!Ze(D,le.relatedTarget)&&(j(!0),w(!1),S==="onBlur")){const de=P==="none"?Q:F;N.commit(de)}},onMouseDown(le){if(J||(z||q.set("domReferenceElement",le.currentTarget),A.context.forceMount(),ae.current!=="touch"&&(A.context.inputRef.current?.focus(),z||le.preventDefault()),L))return;const de=Gt(le.currentTarget);function Se(Te){const _e=A.state.triggerElement;if(!_e)return;const Ae=fs(Te),oe=A.state.positionerElement,me=A.state.listElement;Ze(_e,Ae)||Ze(oe,Ae)||Ze(me,Ae)||ZE(Te,_e)||A.context.setOpen(!1,qe(_1,Te))}z&&de.addEventListener("mouseup",Se,{once:!0})},onKeyDown(le){(le.key==="ArrowDown"||le.key==="ArrowUp")&&(Cs(le),A.context.setOpen(!0,qe(fy,le.nativeEvent)),A.context.inputRef.current?.focus())}},N.getValidationProps(J,b),ee],stateAttributesMapping:hA})}),i6=x.createContext(null);function c6(){return x.useContext(i6)}function u6(e){const{children:t}=e,{filteredItems:a}=yf(),o=c6(),c=o?o.items:a;return s.jsx(x.Fragment,{children:c.map(t)})}const d6=x.forwardRef(function(t,a){var o;const{render:c,className:d,style:f,children:p,...h}=t,b=Ta(),y=$h(),v=!!ij(!0),{filteredItems:j,hasItems:w}=yf(),S=b.useState("selectionMode"),N=b.useState("grid"),k=b.useState("readOnly"),A=b.useState("listProps"),P=b.useState("virtualized"),R=b.useState("forceMounted"),C=S==="multiple",E=j.length===0,D=Ie(L=>{b.set("positionerElement",L)}),I=Ie(L=>{b.set("listElement",L)}),O=x.useMemo(()=>typeof p=="function"?o||(o=s.jsx(u6,{children:p})):p,[p]),_={empty:E},z=y.useState("floatingId"),H=yt("div",t,{state:_,ref:[a,I,v?null:D],props:[A,{children:O,tabIndex:-1,id:z,role:N?"grid":"listbox","aria-multiselectable":C?"true":void 0,"aria-readonly":!N&&k?!0:void 0,onKeyDown(L){if(!(b.state.disabled||b.state.readOnly)&&L.key==="Enter"){const F=b.state.activeIndex;if(F==null)return;Cs(L),vA(b,F,L.nativeEvent)}},onKeyDownCapture(){b.context.keyboardActiveRef.current=!0},onPointerMoveCapture(){b.context.keyboardActiveRef.current=!1}},h]});if(P)return H;const B=w&&!R?void 0:b.context.labelsRef;return s.jsx(nj,{elementsRef:b.context.listRef,labelsRef:B,children:H})}),f6="⁠",p6=200;function m6(e){const t=e.ownerDocument.createTreeWalker(e,NodeFilter.SHOW_TEXT);let a=null;for(;t.nextNode();){const o=t.currentNode;o.nodeValue!==""&&(a=o)}return a}function h6(){const e=er(),t=x.useRef(null);return x.useEffect(()=>{if(tf)return;const a=t.current;if(a==null)return;const o=m6(a);if(o==null)return;const c=o.data,d=`${c}${f6}`;return o.nodeValue=d,e.start(p6,()=>{o.nodeValue===d&&(o.nodeValue=c)}),()=>{e.clear(),o.nodeValue===d&&(o.nodeValue=c)}},[t,e]),t}const yA=x.createContext(void 0);function g6(){const e=x.useContext(yA);if(e===void 0)throw new Error(un(20));return e}const x6=x.forwardRef(function(t,a){const{keepMounted:o=!1,...c}=t,d=Ta(),f=d.useState("mounted"),p=d.useState("forceMounted");return f||o||p?s.jsx(yA.Provider,{value:o,children:s.jsx(ph,{ref:a,...c})}):null}),b6=x.forwardRef(function(t,a){const{render:o,className:c,anchor:d,positionMethod:f,side:p,align:h,sideOffset:b,alignOffset:y,collisionBoundary:v="clipping-ancestors",collisionPadding:j,arrowPadding:w,sticky:S,disableAnchorTracking:N=!1,collisionAvoidance:k=rT,style:A,...P}=t,R=Ta(),C=$h(),E=g6(),D=R.useState("modal"),I=R.useState("open"),O=R.useState("mounted"),_=R.useState("openMethod"),z=R.useState("positionerElement"),H=R.useState("triggerElement"),B=R.useState("inputElement"),L=R.useState("inputGroupElement"),F=R.useState("inputInsidePopup"),$=R.useState("transitionStatus"),X=qh(),q=Th({anchor:d??(F?H:L??B),floatingRootContext:C,positionMethod:f,mounted:O,side:p,sideOffset:b,align:h,alignOffset:y,arrowPadding:w,collisionBoundary:v,collisionPadding:j,sticky:S,disableAnchorTracking:N,keepMounted:E,collisionAvoidance:k,lazyFlip:!0});aj(I&&D,_==="touch",z,H);const Q={open:I,side:q.side,align:q.align,anchorHidden:q.anchorHidden,empty:X};Me(()=>{R.set("popupSide",q.side)},[R,q.side]);const G=Ie(Y=>{R.set("positionerElement",Y)}),J=Eh(t,Q,{styles:q.positionerStyles,transitionStatus:$,props:P,refs:[a,G],hidden:!O,inert:!I});return s.jsxs(gA.Provider,{value:q,children:[O&&D&&s.jsx(Mh,{inert:Ah(!I),cutout:L??B??H}),J]})}),v6={...Zc,...co},y6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,initialFocus:f,finalFocus:p,...h}=t,b=Ta(),y=ij(),v=$h(),j=b.useState("mounted"),w=b.useState("open"),S=b.useState("openMethod"),N=b.useState("popupProps"),k=b.useState("transitionStatus"),A=b.useState("inputInsidePopup"),P=b.useState("inputElement"),R=b.useState("modal"),C=b.useState("id"),E=qh(),D=h.id??(A?fA(C):void 0);Me(()=>(b.set("popupId",b.context.popupRef.current?.id||D),()=>{b.set("popupId",void 0)}),[b,D]),oa({open:w,ref:b.context.popupRef,onComplete(){w&&b.context.onOpenChangeComplete(!0)}});const I={open:w,side:y.side,align:y.align,anchorHidden:y.anchorHidden,transitionStatus:k,empty:E},O=yt("div",t,{state:I,ref:[a,b.context.popupRef],props:[N,{id:D,role:A?"dialog":"presentation",onFocus(L){const F=fs(L.nativeEvent);S!=="touch"&&(Ze(b.state.listElement,F)||F===L.currentTarget)&&b.context.inputRef.current?.focus()}},xf(k),h],stateAttributesMapping:v6}),z=f===void 0?A?L=>L==="touch"?b.context.popupRef.current:P:!1:f;let H;p!=null?H=p:H=A?void 0:!1;const B=!A||R;return s.jsx(mh,{context:v,disabled:!j,modal:B,openInteractionType:S,initialFocus:z,returnFocus:H,getInsideElements:()=>[b.context.startDismissRef.current,b.context.endDismissRef.current],children:s.jsxs(x.Fragment,{children:[O,B&&s.jsx(xA,{ref:b.context.endDismissRef})]})})}),j6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t;return yt("span",t,{ref:a,props:[{"aria-hidden":!0,children:"▼"},f]})}),jA=x.createContext(void 0);function wA(){const e=x.useContext(jA);if(!e)throw new Error(un(19));return e}const w6=x.createContext(!1);function S6(){return x.useContext(w6)}function SA(e){const{componentProps:t,forwardedRef:a,virtualized:o,indexFromFilter:c}=e,{render:d,className:f,style:p,value:h=null,index:b,disabled:y=!1,nativeButton:v=!1,...j}=t,w=x.useRef(null),S=tj({guess:!0,index:b,textRef:w}),N=Ta(),k=S6(),A=qF(),P=N.useState("selectionMode"),R=N.useState("disabled"),C=N.useState("readOnly"),E=N.useState("isItemEqualToValue"),D=R||y,I=P!=="none",O=b??c??S.index,_=O!==-1,z=N.useState("id"),H=N.useState("isActive",O),B=N.useState("isSelected",h),L=N.useState("itemProps"),F=x.useRef(null),$=z!=null&&_?`${z}-${O}`:void 0,X=B&&I;Me(()=>{if(!(_&&(o||b!=null)))return;const U=N.context.listRef.current;return U[O]=F.current,()=>{delete U[O]}},[_,o,O,b,N]),Me(()=>{if(!_||A)return;const M=N.context.valuesRef.current;return M[O]=h,()=>{delete M[O]}},[_,A,O,h,N]),Me(()=>{if(!_||A)return;const M=N.state.selectedValue;let U=N.state.selectedIndex;N.state.selectionMode==="multiple"&&Array.isArray(M)?U=qE(O,h,N.context.valuesRef.current,M,E,U):ca(h,M,E)&&(U=O),N.set("selectedIndex",U)},[_,A,N,O,h,E]);const{getButtonProps:K,buttonRef:q}=na({disabled:D,focusableWhenDisabled:!0,native:v,composite:!0}),Q={disabled:D,selected:X,highlighted:H};function G(M){function U(){N.context.handleSelection(M,h)}N.state.submitOnItemClick?(Ts.flushSync(U),N.context.requestSubmit()):U()}const J={id:$,role:k?"gridcell":"option","aria-selected":I?X:void 0,tabIndex:void 0,onPointerDownCapture(M){M.isPrimary&&(N.context.pointerDownItemRef.current=M.currentTarget),M.preventDefault()},onMouseDown(M){M.preventDefault()},onClick(M){D||C||G(M.nativeEvent)},onMouseUp(M){const U=N.context.pointerDownItemRef.current===M.currentTarget;N.context.pointerDownItemRef.current=null,!(D||C||M.button!==0||U||!H)&&G(M.nativeEvent)}},Y=yt("div",t,{ref:[q,a,S.ref,F],state:Q,props:[L,J,j,K]}),re=x.useMemo(()=>({selected:X,textRef:w}),[X,w]);return s.jsx(jA.Provider,{value:re,children:Y})}function N6(e){const{componentProps:t,forwardedRef:a}=e,c=Ta().useState("isItemEqualToValue"),{flatFilteredValues:d}=yf(),f=t.value??null,p=cu(d,f,c);return s.jsx(SA,{componentProps:t,forwardedRef:a,virtualized:!0,indexFromFilter:p})}const k6=x.memo(x.forwardRef(function(t,a){const c=Ta().useState("virtualized");return c&&t.index==null?s.jsx(N6,{componentProps:t,forwardedRef:a}):s.jsx(SA,{componentProps:t,forwardedRef:a,virtualized:c,indexFromFilter:void 0})})),C6=x.forwardRef(function(t,a){const{selected:o}=wA();return t.keepMounted||o?s.jsx(T6,{...t,ref:a}):null}),T6=x.memo(x.forwardRef((e,t)=>{const{render:a,className:o,style:c,keepMounted:d,...f}=e,{selected:p}=wA(),h=x.useRef(null),{transitionStatus:b,setMounted:y}=Oi(p),j=yt("span",e,{ref:[t,h],state:{selected:p,transitionStatus:b},props:[{"aria-hidden":!0,children:"✔️"},f],stateAttributesMapping:co});return oa({batch:!0,enabled:!p,open:p,ref:h,onComplete(){p||y(!1)}}),j})),E6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,children:f,...p}=t,{filteredItems:h}=yf(),b=Ta(),y=h6(),v=h.length===0?f:null;return yt("div",t,{ref:[a,b.context.emptyRef,y],props:[{children:v,role:"status","aria-live":"polite","aria-atomic":!0},p]})}),A6="、";function Gh({value:e,onValueChange:t,options:a,placeholder:o="",emptyHint:c=bo("没有匹配的选项"),searchPlaceholder:d=bo("搜索…"),disabled:f=!1,className:p,id:h,title:b,...y}){const v=x.useMemo(()=>a.filter(w=>e.includes(w.value)),[a,e]),j=v.length?v.map(w=>w.label).join(A6):o;return s.jsxs(JF,{items:a,multiple:!0,value:v,onValueChange:w=>t(w.map(S=>S.value)),isItemEqualToValue:(w,S)=>w?.value===S?.value,disabled:f,children:[s.jsxs(o6,{"data-slot":"multi-select-trigger",id:h,title:b,"aria-label":y["aria-label"],className:Ue("inline-flex h-[30px] min-w-0 cursor-pointer items-center justify-between gap-1.5 rounded-md border border-control-border bg-control px-2.5","text-[12.5px] font-normal text-foreground","transition-colors duration-150 ease-out","hover:border-control-border-hover hover:bg-control-hover","focus-visible:border-primary focus-visible:shadow-focus focus-visible:outline-none","data-disabled:cursor-not-allowed data-disabled:bg-control data-disabled:text-muted-foreground data-disabled:opacity-60",p),children:[s.jsx("span",{"data-slot":"multi-select-value",className:"min-w-0 flex-1 truncate text-left data-[placeholder]:text-muted-foreground","data-placeholder":v.length?void 0:"",title:j,children:j}),s.jsx(j6,{className:"flex flex-none text-muted-foreground transition-transform duration-[180ms] data-popup-open:rotate-180",children:s.jsx("svg",{viewBox:"0 0 10 6",className:"size-2.5","aria-hidden":"true",children:s.jsx("path",{d:"M1 1l4 4 4-4",stroke:"currentColor",strokeWidth:"1.4",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),s.jsx(x6,{children:s.jsx(b6,{sideOffset:4,className:"z-[35]",children:s.jsxs(y6,{"data-slot":"multi-select-content",className:Ue("flex max-h-[280px] w-[max(var(--anchor-width),220px)] flex-col overflow-hidden","rounded-lg border border-border-strong bg-raised shadow-3 outline-none","data-open:animate-in data-open:fade-in-0","data-closed:animate-out data-closed:fade-out-0"),children:[s.jsxs("div",{className:"flex flex-none items-center gap-1.5 border-b border-hairline px-2.5 py-1.5",children:[s.jsxs("svg",{viewBox:"0 0 12 12",className:"size-3 flex-none text-muted-foreground","aria-hidden":"true",children:[s.jsx("circle",{cx:"5",cy:"5",r:"3.4",stroke:"currentColor",strokeWidth:"1.3",fill:"none"}),s.jsx("path",{d:"M7.6 7.6 10.5 10.5",stroke:"currentColor",strokeWidth:"1.3",strokeLinecap:"round"})]}),s.jsx(l6,{placeholder:d,className:"min-w-0 flex-1 border-0 bg-transparent p-0 text-[12.5px] text-foreground outline-none placeholder:text-muted-foreground"})]}),s.jsx(E6,{children:s.jsx("div",{className:"px-2.5 py-3 text-[11.5px] leading-[1.5] text-muted-foreground",children:c})}),s.jsx(d6,{className:"min-h-0 flex-1 overflow-y-auto overscroll-contain p-[5px]",children:w=>s.jsxs(k6,{value:w,className:Ue("grid cursor-pointer grid-cols-[14px_minmax(0,1fr)] items-center gap-2 rounded-sm px-[9px] py-[5px]","text-[12.5px] leading-[1.4] text-foreground select-none outline-none","transition-colors duration-[120ms] ease-out","data-[highlighted]:bg-nav-hover","data-[selected]:bg-primary-soft data-[selected]:font-semibold data-[selected]:text-primary-fg","data-[highlighted]:data-[selected]:bg-primary-tint","data-disabled:pointer-events-none data-disabled:text-muted-foreground"),children:[s.jsx(C6,{className:"col-start-1 flex text-primary",children:s.jsx("svg",{viewBox:"0 0 12 12",className:"size-3","aria-hidden":"true",children:s.jsx("path",{d:"M2.5 6.2 4.8 8.5 9.5 3.8",stroke:"currentColor",strokeWidth:"1.8",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"})})}),s.jsx("span",{className:"col-start-2 min-w-0 truncate",children:w.label})]},w.value)})]})})})]})}const NA=x.createContext(void 0);function jf(e){const t=x.useContext(NA);if(t===void 0&&!e)throw new Error(un(47));return t}const R6={...Hy,disabled:e=>e.disabled,instantType:e=>e.instantType,openMethod:e=>e.openMethod,openChangeReason:e=>e.openChangeReason,modal:e=>e.modal,focusManagerModal:e=>e.focusManagerModal,stickIfOpen:e=>e.stickIfOpen,titleElementId:e=>e.titleElementId,descriptionElementId:e=>e.descriptionElementId,openOnHover:e=>e.openOnHover,closeDelay:e=>e.closeDelay,adaptiveOrigin:e=>e.adaptiveOrigin};class O6 extends ou{constructor(a,o,c){const d=new vh;super(M6(a,d,o,c),D6(d),R6);cn(this,"setOpen",(a,o)=>{const c=o.reason===qs,d=o.reason===go&&o.event.detail===0,f=!a&&(o.reason===nu||o.reason==null),p=zT(o),h=this.select("activeTriggerId");if(!a&&o.reason===dy&&o.trigger==null&&h!=null&&(o.trigger=this.context.triggerElements.getById(h)??this.select("activeTriggerElement")??void 0),this.context.onOpenChange?.(a,o),o.isCanceled)return;this.state.floatingRootContext.dispatchOpenChange(a,o);const b=()=>{const v=Iy(this.state,a,o.trigger,p());v.openChangeReason=o.reason,this.update(v)};c?(this.set("stickIfOpen",!0),this.context.stickIfOpenTimeout.start(hH,()=>{this.set("stickIfOpen",!1)}),Ts.flushSync(b)):b();let y;d?y="click":f?y="dismiss":o.reason===xo&&(y="focus"),this.set("instantType",y)})}}function M6(e,t,a,o=!1){const c={...zy(t,a,o),disabled:!1,modal:!1,focusManagerModal:!1,instantType:void 0,openMethod:null,openChangeReason:null,titleElementId:void 0,descriptionElementId:void 0,stickIfOpen:!0,openOnHover:!1,closeDelay:0,adaptiveOrigin:void 0,...e};return c.open&&e?.mounted===void 0&&(c.mounted=!0),c}function D6(e){return{popupRef:x.createRef(),onOpenChange:void 0,onOpenChangeComplete:void 0,triggerFocusTargetRef:x.createRef(),beforeContentFocusGuardRef:x.createRef(),stickIfOpenTimeout:new la,triggerElements:e}}const kA=uh(function({props:t}){const{children:a,open:o,defaultOpen:c=!1,onOpenChange:d,onOpenChangeComplete:f,modal:p=!1,handle:h,triggerId:b,defaultTriggerId:y=null}=t,v=P6(h,{modal:p,open:c,openProp:o,activeTriggerId:y,triggerIdProp:b});v.useControlledProp("openProp",o),v.useControlledProp("triggerIdProp",b);const j=v.useState("open"),w=v.useState("mounted"),S=v.useState("payload");v.useContextCallback("onOpenChange",d),v.useContextCallback("onOpenChangeComplete",f),HT(v,j),Py(v);const{forceUnmount:N}=_y(j,v,()=>{v.update({stickIfOpen:!0,openChangeReason:null})});v.useSyncedValues({modal:p}),x.useEffect(()=>{j||v.context.stickIfOpenTimeout.clear()},[v,j]),x.useImperativeHandle(t.actionsRef,()=>({unmount:N,close:()=>v.setOpen(!1,qe(py))}),[N,v]);const k=j||w;return s.jsxs(NA.Provider,{value:v,children:[h&&s.jsx(Dy,{handle:h,store:v}),k&&s.jsx(_6,{store:v,modal:p}),typeof a=="function"?a({payload:S}):a]})});function I6(e){return jf(!0)?s.jsx(kA,{props:e}):s.jsx(wH,{children:s.jsx(kA,{props:e})})}function P6(e,t){const a=My((o,c)=>new O6(t,o,c));return x.useEffect(()=>a.context.stickIfOpenTimeout.disposeEffect(),[a]),a}function _6({store:e,modal:t}){const a=e.useState("floatingRootContext"),o=pf(a,{outsidePressEvent:{mouse:t==="trap-focus"?"sloppy":"intentional",touch:"sloppy"}}),c=o.reference,d=o.floating;return Ly(e,{activeTriggerProps:c,inactiveTriggerProps:c,popupProps:d}),null}const L6=300;function z6(e,t){const a=x.useRef(null);function o(d){Ts.flushSync(()=>{e.setOpen(!1,qe(xo,d.nativeEvent,d.currentTarget))}),g4(a.current)?.focus()}function c(d){const f=e.select("positionerElement");if(f&&Jc(d,f))e.context.beforeContentFocusGuardRef.current?.focus();else{Ts.flushSync(()=>{e.setOpen(!1,qe(xo,d.nativeEvent,d.currentTarget))});let p=h4(e.context.triggerFocusTargetRef.current||t.current);for(;p!==null&&Ze(f,p);){const h=p;if(p=iy(p),p===h)break}p?.focus()}}return{preFocusGuardRef:a,handlePreFocusGuardFocus:o,handleFocusTargetFocus:c}}const B6=G1(function(t,a){const{render:o,className:c,style:d,disabled:f=!1,nativeButton:p=!0,handle:h,payload:b,openOnHover:y=!1,delay:v=L6,closeDelay:j=0,id:w,...S}=t,N=jf(!0),A=FT(h)??N;if(!A)throw new Error(un(74));const P=ka(w),R=A.useState("isTriggerActive",P),C=A.useState("floatingRootContext"),E=A.useState("isOpenedByTrigger",P),D=A.useState("triggerPopupId",P),I=x.useRef(null),{registerTrigger:O,isMountedByThisTrigger:_}=BT(P,I,A,{payload:b,disabled:f,openOnHover:y,closeDelay:j}),z=A.useState("openChangeReason"),H=A.useState("stickIfOpen"),B=A.useState("openMethod"),L=A.useState("focusManagerModal"),F=KT(C,{enabled:!f&&y&&(B!=="touch"||z!==go),mouseOnly:!0,move:!1,handleClose:WT(),restMs:v,delay:{close:j},triggerElementRef:I,isActiveTrigger:R,isClosing:()=>A.select("transitionStatus")==="ending"}),$=hh(C,{stickIfOpen:H}),X=TE(()=>A.select("open"),ae=>{A.set("openMethod",ae)}),K=A.useState("triggerProps",_),{getButtonProps:q,buttonRef:Q}=na({disabled:f,native:p}),G={open(ae){return ae&&z===go?Yv.open(ae):Kv.open(ae)}},{preFocusGuardRef:J,handlePreFocusGuardFocus:Y,handleFocusTargetFocus:re}=z6(A,I),U=yt("button",t,{state:{disabled:f,open:E},ref:[Q,a,O,I],props:[$.reference,F,K,X,{[sT]:"",id:P,"aria-haspopup":"dialog","aria-expanded":E,"aria-controls":D},S,q],stateAttributesMapping:G}),Z=s.jsx(x.Fragment,{children:U},P);return _&&!L?s.jsxs(x.Fragment,{children:[s.jsx(ru,{ref:J,onFocus:Y}),Z,s.jsx(ru,{ref:A.context.triggerFocusTargetRef,onFocus:re})]}):Z}),CA=x.createContext(void 0);function H6(){const e=x.useContext(CA);if(e===void 0)throw new Error(un(45));return e}const U6=x.forwardRef(function(t,a){const{keepMounted:o=!1,...c}=t;return jf().useState("mounted")||o?s.jsx(CA.Provider,{value:o,children:s.jsx(ph,{ref:a,...c})}):null}),TA=x.createContext(void 0);function V6(){const e=x.useContext(TA);if(!e)throw new Error(un(46));return e}const F6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,anchor:f,positionMethod:p,side:h,align:b,sideOffset:y,alignOffset:v,collisionBoundary:j="clipping-ancestors",collisionPadding:w,arrowPadding:S,sticky:N,disableAnchorTracking:k=!1,collisionAvoidance:A=aT,...P}=t,R=jf(),C=H6(),E=yH(),D=R.useState("floatingRootContext"),I=R.useState("mounted"),O=R.useState("open"),_=R.useState("openChangeReason"),z=R.useState("activeTriggerElement"),H=R.useState("modal"),B=R.useState("openMethod"),L=R.useState("positionerElement"),F=R.useState("instantType"),$=R.useState("transitionStatus"),X=R.useState("adaptiveOrigin"),K=x.useRef(null),q=D1(L),Q=Th({anchor:f,floatingRootContext:D,positionMethod:p,mounted:I,side:h,sideOffset:y,align:b,alignOffset:v,arrowPadding:S,collisionBoundary:j,collisionPadding:w,sticky:N,disableAnchorTracking:k,keepMounted:C,nodeId:E,collisionAvoidance:A,adaptiveOrigin:X}),G=D.useState("domReferenceElement");Me(()=>{const U=G,Z=K.current;if(U&&(K.current=U),Z&&U&&U!==Z){R.set("instantType",void 0);const ae=new AbortController;return q(()=>{R.set("instantType","trigger-change")},ae.signal),()=>{ae.abort()}}},[G,q,R]);const J=H===!0&&_!==qs;aj(O&&J,B==="touch",L,z);const Y=R.useStateSetter("positionerElement"),re={open:O,side:Q.side,align:Q.align,anchorHidden:Q.anchorHidden,instant:F},M=Eh(t,re,{styles:Q.positionerStyles,transitionStatus:$,props:P,refs:[a,Y],hidden:!I,inert:!O});return s.jsxs(TA.Provider,{value:Q,children:[I&&J&&s.jsx(Mh,{inert:Ah(!O),cutout:z}),s.jsx(jH,{id:E,children:M})]})}),$6=x.createContext(void 0);function q6(){const[e,t]=x.useState(0),a=Ie(()=>(t(c=>c+1),()=>{t(c=>Math.max(0,c-1))}));return{context:x.useMemo(()=>({register:a}),[a]),hasClosePart:e>0}}const G6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,initialFocus:f,finalFocus:p,...h}=t,b=jf(),y=V6(),v=eA()!=null,{context:j,hasClosePart:w}=q6(),S=b.useState("open"),N=b.useState("openMethod"),k=b.useState("instantType"),A=b.useState("transitionStatus"),P=b.useState("popupProps"),R=b.useState("titleElementId"),C=b.useState("descriptionElementId"),E=b.useState("modal"),D=b.useState("mounted"),I=b.useState("openChangeReason"),O=b.useState("activeTriggerElement"),_=b.useState("floatingRootContext"),z=_.useState("floatingId"),H=b.useState("disabled"),B=b.useState("openOnHover"),L=b.useState("closeDelay");oa({open:S,ref:b.context.popupRef,onComplete(){S&&b.context.onOpenChangeComplete?.(!0)}}),GT(_,{enabled:B&&!H,closeDelay:L});const F=f===void 0?_T(b.context.popupRef):f,$=E!==!1&&w;b.useSyncedValue("focusManagerModal",$);const X=b.useStateSetter("popupElement"),K={open:S,side:y.side,align:y.align,instant:k,transitionStatus:A},q=yt("div",t,{state:K,ref:[a,b.context.popupRef,X],props:[P,{id:z,role:"dialog",...mf,"aria-labelledby":R,"aria-describedby":C,onKeyDown(Q){v&&Rh.has(Q.key)&&Q.stopPropagation()}},xf(A),h],stateAttributesMapping:Xv});return s.jsx(mh,{context:_,openInteractionType:N,modal:$,disabled:!D||I===qs,initialFocus:F,returnFocus:p,restoreFocus:"popup",previousFocusableElement:pn(O)?O:void 0,nextFocusableElement:b.context.triggerFocusTargetRef,beforeContentFocusGuardRef:b.context.beforeContentFocusGuardRef,children:s.jsx($6.Provider,{value:j,children:q})})});function wf(e){return s.jsx(I6,{"data-slot":"popover",...e})}function Kh(e){return s.jsx(B6,{"data-slot":"popover-trigger",...e})}function Sf({className:e,sideOffset:t=6,align:a="start",side:o,alignOffset:c,collisionPadding:d=8,anchor:f,children:p,...h}){return s.jsx(U6,{children:s.jsx(F6,{className:"z-[35] outline-none",sideOffset:t,align:a,side:o,alignOffset:c,collisionPadding:d,anchor:f,children:s.jsx(G6,{"data-slot":"popover-content",className:Ue("flex max-h-[min(70vh,560px)] flex-col overflow-hidden rounded-lg border border-border-strong bg-raised text-foreground shadow-3","outline-none","data-open:animate-in data-open:fade-in-0 data-open:slide-in-from-top-1","data-closed:animate-out data-closed:fade-out-0",e),...h,children:p})})})}function K6({page:e,pageCount:t,onPageChange:a,disabled:o=!1,className:c,infoFirst:d=!1}){const f=Math.max(1,Number(t)||1),p=Math.min(Math.max(1,Number(e)||1),f),h=s.jsx("span",{"data-slot":"pager-info",className:"text-[11.5px] text-subtle [font-variant-numeric:tabular-nums]",children:bo("第 {current} / {total} 页",{current:p,total:f})});return s.jsxs("div",{"data-slot":"pager",className:Ue("flex items-center gap-2",c),children:[d&&h,s.jsx(ne,{type:"button",variant:"outline",size:"sm",disabled:o||p<=1,onClick:()=>a(p-1),children:bo("上一页")}),s.jsx(ne,{type:"button",variant:"outline",size:"sm",disabled:o||p>=f,onClick:()=>a(p+1),children:bo("下一页")}),!d&&h]})}const Y6=Xc(["relative flex w-full items-center gap-2.5 text-left","border border-transparent rounded-sm","shadow-none","transition-[background-color,border-color,color] duration-150 ease-out","outline-none focus-visible:shadow-focus","disabled:pointer-events-none disabled:opacity-45","[&_svg]:pointer-events-none [&_svg]:shrink-0"],{variants:{variant:{default:["cursor-pointer px-2.5 py-2","text-[12.5px] font-medium text-sidebar-fg","hover:bg-nav-hover hover:text-foreground","data-[active]:border-nav-selected-border data-[active]:bg-nav-selected-bg data-[active]:font-semibold data-[active]:text-nav-selected-fg"],add:["cursor-pointer justify-center px-2 py-1.5","border-dashed border-border-strong bg-transparent","text-[11.5px] text-muted-foreground","hover:border-primary hover:text-primary-fg"]}},defaultVariants:{variant:"default"}});function uu({className:e,variant:t,active:a=!1,count:o,icon:c,trailing:d,children:f,...p}){return s.jsxs("button",{type:"button","data-slot":"nav-item","data-active":a?"":void 0,"aria-current":a?"true":void 0,className:Ue(Y6({variant:t}),e),...p,children:[c,s.jsx("span",{"data-slot":"nav-item-label",className:"min-w-0 flex-1 truncate",children:f}),d,o!=null&&s.jsx("span",{"data-slot":"nav-item-count",className:Ue("flex-none text-[10.5px] text-sidebar-muted [font-variant-numeric:tabular-nums]",a&&"text-inherit"),children:o})]})}function r(e,t){const a=typeof window<"u"?window.wbI18n:void 0;return a&&typeof a.t=="function"?a.t(e,t):e}function Yh(e){if(e.source==="subscription"&&(e.port===null||e.port===void 0))return r("未分配端口");const t=e.resolved;return t?.protocol&&t.host&&t.port?`${String(t.protocol).toUpperCase()} ${t.host}:${t.port}`:t?.label||""}function du(e){const t=e.name||e.id,o=[e.resolveError?r("解析失败"):Yh(e),e.enabled===!1?r("已禁用"):""].filter(Boolean);return o.length?r("{name}({parts})",{name:t,parts:o.join(" · ")}):t}const Qa="pool:";function Pe(){return window}function Le(e,t){Pe().wbApp?.toast?.(e,t)}function Za(e){const t=Pe().wbApp?.esc;return t?t(e):String(e??"").replace(/[&<>"']/g,a=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[a]||a)}function Ls(e){const t=Pe().wbApp?.formatTime;if(t)return t(e);const a=Number(e);return!Number.isFinite(a)||a<=0?"":new Date(a).toLocaleString("zh-CN")}function mt(e){return e instanceof Error?e.message:String(e)}function ss(e){if(e==null||e==="")return"—";const t=Number(e);return Number.isFinite(t)?String(Number(t.toFixed(2))):String(e)}function fu(e){if(e==null||e==="")return null;const t=Number(e);return Number.isFinite(t)?t:null}function cj(e){const t=new Date(e);if(Number.isNaN(t.getTime()))return"";const a=o=>String(o).padStart(2,"0");return`${a(t.getMonth()+1)}-${a(t.getDate())} ${a(t.getHours())}:${a(t.getMinutes())}`}function X6(e){return e==="积分"?r("积分"):e==="额度"?r("额度"):e}function Q6(e){if(!e||typeof e!="object"||Array.isArray(e))return[];const t=e,a=Array.isArray(t.credits)?t.credits:[],o=Date.now();return a.map(c=>{const d=String(c?.name||"").trim()||r("积分包"),f=String(c?.unit||"").trim(),p=fu(c?.total),h=fu(c?.used),b=fu(c?.remain),y=c?.unlimited===!0,v=fu(c?.grantAt),j=fu(c?.startAt),w=fu(c?.expireAt),S=c?.daily===!0,N=String(c?.grantReason||"").trim(),k=w!==null&&w>0&&w<=o,A=p!==null&&p>0,P=y?r("不限"):b!==null?A?r("剩 {remaining} / {total}",{remaining:ss(b),total:ss(p)}):r("剩 {remaining}",{remaining:ss(b)}):h!==null?r("已用 {used}",{used:ss(h)}):"—",R=!y&&f&&P!=="—"?`${P} ${X6(f)}`:P,C=A&&b!==null?Math.max(0,Math.min(100,b/p*100)):null,E=b!==null&&b<=0||b===null&&h!==null&&A&&h>=p,D=!y&&!S&&(E||k),I=[];v!==null&&v>0?I.push(r("{time} 领取",{time:cj(v)})):j!==null&&j>0&&I.push(r("{time} 生效",{time:cj(j)})),S?I.push(r("每日重置")):w!==null&&w>0&&I.push(k?r("已过期"):r("{time} 到期",{time:cj(w)})),N&&I.push(N);const O=k||b===0?"muted":C!==null&&C<20?"warn":b===null&&h===null&&!y?"muted":"ok",_=[d,R,v!==null&&v>0?r("领取 {time}",{time:Ls(v)}):j!==null&&j>0?r("生效 {time}",{time:Ls(j)}):"",w!==null&&w>0?k?r("已过期({time})",{time:Ls(w)}):r("到期 {time}",{time:Ls(w)}):"",S?r("每日重置(额度按周期回满,不是作废)"):"",N,C===null&&b!==null?r("上游未给总量,画不出剩余比例"):"",h!==null&&p!==null?r("已用 {used} / 共 {total}",{used:ss(h),total:ss(p)}):""].filter(Boolean).join(" · ");return{name:d,view:R,tone:O,percent:C,window:I.length?I.join(" · "):null,title:_,spent:D}})}function EA({row:e}){return s.jsxs("div",{className:"usage-pop-row",title:e.title,children:[s.jsxs("div",{className:"usage-pop-line",children:[s.jsx("span",{className:"usage-pop-name",children:e.name}),s.jsx("span",{className:`usage-pop-view ${e.tone}`,children:e.view})]}),e.window?s.jsx("div",{className:"usage-pop-window",children:e.window}):null,e.percent!==null?s.jsx("span",{className:"usage-pop-track",children:s.jsx("i",{style:{width:`${e.percent}%`},"aria-label":r("剩余 {percent}%",{percent:Math.round(e.percent)})})}):null]})}function AA({rows:e,subscriptionLine:t,variant:a,kind:o,title:c,children:d}){const[f,p]=x.useState(!1),[h,b]=x.useState(!1),y=e.filter(k=>!k.spent),v=e.filter(k=>k.spent),j=a==="pool"?`usage-toggle usage-pool-line ${o}`:`usage-toggle ${o}`,w=x.useRef(null),S=x.useCallback(k=>{w.current=k,k&&(k.scrollTop=0)},[]),N=x.useCallback(()=>w.current??null,[]);return x.useLayoutEffect(()=>{if(!h)return;const k=w.current?.querySelector(".usage-pop-spent .usage-pop-row");k instanceof HTMLElement&&k.scrollIntoView({block:"nearest"})},[h]),s.jsxs(wf,{open:f,onOpenChange:p,children:[s.jsxs(Kh,{render:s.jsx("button",{type:"button",className:j,title:c,"aria-label":r("积分明细")}),children:[a==="pool"?d:s.jsx("span",{className:"val",children:d}),s.jsx("span",{className:"caret","aria-hidden":!0,children:"▾"})]}),s.jsx(Sf,{align:"end",sideOffset:6,className:"w-[320px]",initialFocus:N,children:s.jsxs("div",{className:"usage-pop-credit",ref:S,tabIndex:-1,children:[t?s.jsx("div",{className:"usage-pop-sub",children:t}):null,s.jsx("div",{className:"usage-pop-group",children:r("积分明细")}),y.map((k,A)=>s.jsx(EA,{row:k},`${k.name}-${A}`)),v.length>0?s.jsxs("div",{className:"usage-pop-spent",children:[s.jsxs("button",{type:"button",className:"usage-pop-spent-head","aria-expanded":h,title:r("展开或收起(默认收起)"),onClick:()=>b(k=>!k),children:[s.jsx("span",{className:"caret","aria-hidden":!0,children:"▾"}),s.jsx("span",{children:r("已用完 / 已过期")}),s.jsx("span",{className:"n",children:r("{count} 份",{count:v.length})})]}),h?v.map((k,A)=>s.jsx(EA,{row:k},`spent-${k.name}-${A}`)):null]}):null]})})]})}const pu="workbuddy",Z6="raccoon",W6={workbuddy:{usage:!0,creditDetail:!0,edition:!0,identifier:"uid",expiry:"expiresAt"},"workbuddy-intl":{usage:!0,creditDetail:!0,edition:!1,identifier:"uid",expiry:"expiresAt"},raccoon:{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:"tokenExpiresAt"},catpaw:{usage:!0,edition:!1,identifier:"uid",expiry:"tokenExpiresAt"},autoclaw:{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:"tokenExpiresAt"},"autoclaw-intl":{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:"tokenExpiresAt",emailAsName:!0},qoder:{usage:!0,creditDetail:!0,edition:!0,identifier:"userId",expiry:"expiresAt",emailAsName:!0},"qoder-intl":{usage:!0,creditDetail:!0,edition:!0,identifier:"userId",expiry:"expiresAt",emailAsName:!0},"cline-free":{usage:!0,edition:!1,identifier:"account",expiry:"expiresAt"},"cline-pass":{usage:!0,edition:!1,identifier:"account",expiry:"expiresAt"},accio:{usage:!0,edition:!0,identifier:"userId",expiry:"expiresAt",emailAsName:!0},"accio-cn":{usage:!0,edition:!0,identifier:"userId",expiry:"expiresAt",emailAsName:!0},zcode:{usage:!0,creditDetail:!0,claim:!0,planChannel:!0,edition:!0,identifier:"userId",expiry:"expiresAt"},"zcode-intl":{usage:!0,creditDetail:!0,claim:!0,planChannel:!0,edition:!0,identifier:"userId",expiry:"expiresAt"},codearts:{usage:!0,usageDetail:!0,edition:!1,identifier:"userId",expiry:"expiresAt",concurrencyDefault:3},trae:{usage:!0,creditDetail:!0,edition:!1,identifier:"uid",expiry:"expiresAt"},loomy:{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:"expiresAt"},kuku:{usage:!0,edition:!1,identifier:"uid",expiry:""},officeace:{usage:!0,creditDetail:!0,edition:!1,identifier:"id",expiry:"expiresAt"},antigravity:{usage:!0,edition:!1,identifier:"userId",expiry:""},chatglm:{usage:!0,creditDetail:!0,edition:!1,identifier:"uid",expiry:""}},J6={usage:!1,edition:!1,identifier:"userId",expiry:"tokenExpiresAt",emailAsName:!1};function An(e){const t=e?.provider;return typeof t=="string"&&t?t:pu}function cr(e){return e&&W6[e]||J6}const e$="opencode",t$="https://opencode.ai/zen/go/v1";function RA(e,t){if(!e||e.clientEmulation!==e$)return!1;const o=((typeof t=="string"?t.trim():"")||String(e.baseUrl||"")).trim().replace(/\/+$/,"").toLowerCase();return o?o!==t$:!1}function n$(e){const t=e?An(e):"";return t.startsWith("custom-")&&(Pe().wbProviders?.customList?.()||[]).find(o=>o?.id===t)||null}function s$(e){return e?RA(n$(e),e.baseUrl):!1}function OA(e){const t=Array.isArray(e?.providers)?e.providers:[],a=Array.isArray(e?.accounts)?e.accounts:[],o=new Map;a.forEach(d=>{const f=An(d);o.set(f,(o.get(f)||0)+1)});const c=new Map;return t.forEach(d=>{d?.id&&c.set(String(d.id),{id:String(d.id),label:String(d.label||d.id),count:Number(d.count)||0})}),o.forEach((d,f)=>{c.has(f)||c.set(f,{id:f,label:Pe().wbProviders?.labelOf?.(f)||f,count:d})}),c.size||c.set(pu,{id:pu,label:Pe().wbProviders?.labelOf?.(pu)||"WorkBuddy 国内版",count:0}),[...c.values()]}function Xh(e){const t=cr(An(e)).identifier;return String(e?.[t]||"")}function MA(e){const t=Number(e)||0;return t<=0?0:t<1e11?t*1e3:t}function r$(e){const t=cr(An(e)).expiry;return MA(e?.[t])}function Ea(e){const t=An(e);return t.startsWith("custom-")?!!e?.balanceQuery?.scheme:cr(t).usage}const uj=30,DA=86400,IA=60,PA=1800,_A=86400,LA=1,a$=95e5;function l$(e){return e==="codearts"?[{type:"token",action:"skip",threshold:a$,reset:"daily",enabled:!0}]:e==="cline-free"?[]:[{type:"balance",action:"skip",threshold:LA,enabled:!0}]}function zA(e){const t=e?.usageQuery;if(!t||typeof t!="object")return{enabled:!0,interval:IA};const a=t.enabled===void 0?!0:t.enabled===!0,o=Number(t.interval)||0,c=o>=uj&&o<=DA;return{enabled:a,interval:a&&!c?IA:o}}function o$(e){if(!e||typeof e!="object")return!1;const t=e;if(t.type!=="balance"&&t.type!=="token"||t.action!=="skip"&&t.action!=="disable")return!1;const a=Number(t.threshold);if(!Number.isFinite(a)||a<=0)return!1;if(t.type==="token"&&t.reset!=="daily"){const o=Number(t.period);if(!Number.isInteger(o)||o_A)return!1}return!0}function i$(e){const t=e?.lowBalance;if(!t||typeof t!="object"||!t.mode)return l$(An(e));const a=Number(t.threshold),o=Number.isFinite(a)&&a>0?a:LA;return t.mode!=="skip"&&t.mode!=="disable"?[]:[{type:"balance",action:t.mode,threshold:o,enabled:!0}]}function mu(e){const t=e?.limiters;return Array.isArray(t)?t.filter(o$):i$(e)}function c$(e){return mu(e).filter(t=>t.type==="token")}function u$(e,t){const a=t*1e3;return e-e%a}function BA(e){return e.reset==="daily"?0:e.period??0}function dj(e,t=Date.now()){if(e===0){const a=new Date(t);return a.setHours(0,0,0,0),a.getTime()}return u$(t,e)}function Nf(e,t,a=Date.now()){if(e.type!=="token")return null;const o=BA(e),c=(t||[]).find(d=>Number(d.kind)===o);return c&&Number(c.windowStart)===dj(o,a)?c:null}function Qh(e,t){const a=mu(e).filter(f=>f.type==="balance"&&f.action==="skip"&&f.enabled!==!1&&f.threshold>0);if(!a.length||!t||typeof t!="object")return!1;const o=t;if(o.unlimited)return!1;const c=o.totalLeft??o.available;if(c==null||c==="")return!1;const d=Number(c);return Number.isFinite(d)&&a.some(f=>dc.type==="token"&&c.action==="skip"&&c.enabled!==!1);if(!a.length||!t?.length)return!1;const o=Date.now();return a.some(c=>{const d=Nf(c,t,o);return d!==null&&Number(d.used)>=c.threshold})}function d$(e,t){return mu(e).some(a=>{if(a.type!=="token"||a.action!=="disable"||a.enabled===!1)return!1;const o=Nf(a,t);return o!==null&&Number(o.used)>=a.threshold})}function pj(e,t=Date.now()){const a=BA(e),o=dj(a,t),c=a===0?Math.max(0,dj(0,o+864e5+36e5)-t):Math.max(0,o+a*1e3-t);return{kind:a,startMs:o,remainingMs:c,daily:a===0}}function Zh(e,t){if(e<=0)return"";const a=Math.ceil(e/6e4);if(t){const o=Math.ceil(e/36e5);return o>=1?r("今日剩 {n} 小时",{n:o}):r("今日剩 {n} 分钟",{n:a})}return a>=1?r("剩 {n} 分钟",{n:a}):r("剩不到 1 分钟")}function El(e){const t=Number(e);if(!Number.isFinite(t))return"—";const a=window.wbUnits;return a?.formatTokens?a.formatTokens(t):String(Math.round(t))}function HA(e){return e>0&&e%3600===0?r("{n} 小时",{n:e/3600}):e>0&&e%60===0?r("{n} 分钟",{n:e/60}):r("{n} 秒",{n:e})}function kf(e){return e?.desktop===!0}function UA(e){return e?.chatSupported!==!1}function f$(e){return typeof e=="string"&&e.startsWith("custom-")}function p$(e){return r(e==="enterprise"?"企业":e==="ultimate"?"旗舰":"个人")}function Wh(e,t){const a=Number(e?.priority??100)-Number(t?.priority??100);return a!==0?a:(Number(e?.addedAt)||0)-(Number(t?.addedAt)||0)}function ur(e){return e?.enabled!==!1}function Cf(e,t=""){const a=e?.rateLimits||{},o=Date.now();return t?Number(a[t]?.resetAt)>o:Object.values(a).some(c=>Number(c?.resetAt)>o)}function VA(e){return e?.edition==="intl"?"intl":"cn"}function FA(e){return cr(An(e)).claim?e?.canClaim!==!1:!1}const $A="coding-plan",So="start-plan";function Jh(e){return!!cr(An(e)).planChannel}function mj(e){return Jh(e)?String(e?.zcodePlan||"").trim()===So?So:$A:""}function m$(e){return r(e===So?"套餐池(Start Plan)":"编码套餐(Coding Plan)")}function qA(e){switch(String(e??"").trim()){case"pending":return r("待生效");case"active":return r("生效中");case"expired":return r("已过期");case"unknown":return r("状态未知");default:return String(e??"")}}function eg(e){const t=e?.claimPlans;if(!t||typeof t!="object"||Array.isArray(t))return[];const a=gj();return Object.entries(t).filter(([,o])=>Number(o)>0&&gj(Number(o))===a).map(([o])=>o)}function h$(e){return eg(e).length>0}function g$(e){const t=eg(e),a=t.length?r("({plans})",{plans:t.join(r("、"))}):"";return r("今天(北京时间 {day})已领取 {n} 份{names};还有其他可领套餐时,点这里可以继续领;活动按自然日发新套餐,明天可再领",{day:gj(),n:t.length,names:a})}function x$(e){return!!cr(An(e)).usageDetail}function GA(e){return!!cr(An(e)).creditDetail}function hj(e){return/^free$/i.test(String(e??"").trim())}function KA(e){const t=String(e??"").trim();return/^trial$/i.test(t)?r("试用版"):hj(t)?r("免费版"):t}function gj(e=Date.now()){return new Date(e+8*3600*1e3).toISOString().slice(0,10)}function Tf(e,t,a){return Cf(e)||Qh(e,t)||fj(e,a)}function YA(e,t){const a=String(t.q||"").trim().toLowerCase();return a?[hu(e),e?.name,e?.nickname,e?.email,Xh(e),e?.id].some(c=>String(c||"").toLowerCase().includes(a)):!0}function XA(e,t){return t.provider==="all"||An(e)===t.provider}function xj(e,t){return t.enabled==="all"?!0:t.enabled==="enabled"?ur(e):!ur(e)}function QA(e,t,a,o){if(t.limit==="all")return!0;if(!ur(e))return!1;const c=Tf(e,a?.(e),o?.(e));return t.limit==="limited"?c:!c}function ZA(e,t,a,o){return XA(e,t)&&xj(e,t)&&QA(e,t,a,o)&&YA(e,t)}function b$(e,t,a,o){return(e||[]).filter(c=>ZA(c,t,a,o))}function WA(e,t,a,o){const c=e||[],d=h=>c.filter(b=>XA(b,t)&&(h==="enabled"||xj(b,t))&&YA(b,t)),f=d("enabled"),p=d("limit");return{enabledAll:f.length,enabled:f.filter(ur).length,disabled:f.filter(h=>!ur(h)).length,limitAll:p.length,normal:p.filter(h=>ur(h)&&!Tf(h,a?.(h),o?.(h))).length,limited:p.filter(h=>ur(h)&&Tf(h,a?.(h),o?.(h))).length}}function bj(e){const t=e?.rateLimits;if(!t||typeof t!="object")return[];const a=Date.now();return Object.entries(t).map(([o,c])=>({model:o,...c&&typeof c=="object"?c:{}})).filter(o=>Number(o.resetAt)>a).sort((o,c)=>Number(o.resetAt)-Number(c.resetAt))}function vj(e){const t=(e||[]).slice().sort(Wh),a=new Map;return t.forEach((o,c)=>a.set(o.id,{position:c+1,total:t.length})),a}function v$(e,t,a,o){const c=(e||[]).slice().sort(Wh),d=[],f=new Map;for(const p of c){const h=An(p);f.has(h)||(f.set(h,[]),d.push(h)),f.get(h).push(p)}return d.map((p,h)=>{const b=f.get(p)||[];return{provider:p,label:Pe().wbProviders?.labelOf?.(p)||p,rank:h+1,members:b,accounts:t?b.filter(t):b,enabled:b.filter(ur).length,disabled:b.filter(y=>!ur(y)).length,limited:b.filter(y=>ur(y)&&Tf(y,a?.(y),o?.(y))).length}})}function hu(e){if(!e)return"";const t=String(e.name||"").trim();if(e.nameCustom===!0&&t)return t;const a=String(e.email||"").trim();return cr(An(e)).emailAsName&&a?a:e?.nickname||t||Xh(e)||e?.id||""}const yj="已限流",JA=e=>new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime();function jj(e){const t=Number(e);if(!Number.isFinite(t)||t<=0||t<=Date.now())return yj;const a=new Date(t),o=a.toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit",hour12:!1}),c=Math.round((JA(a)-JA(new Date))/864e5);return c===0?r("今天 {clock}",{clock:o}):c===1?r("明天 {clock}",{clock:o}):r("{month}月{day}日 {clock}",{month:a.getMonth()+1,day:a.getDate(),clock:o})}function y$(e){const t=An(e);if(!cr(t).edition)return"";const a=VA(e),o=e?.editionLabel,c=o||(a==="intl"?"国际版":"国内版");return(Pe().wbProviders?.labelOf?.(t)||"").includes(c)?"":o||r(a==="intl"?"国际版":"国内版")}function j$(e){return[UA(e)?null:{text:r("仅账号管理"),kind:"plain",title:r("该提供商的推理转发尚未接入,账号不参与转发")},f$(An(e))&&e.hasCredentials===!1?{text:r("未配置凭证"),kind:"bad",title:r("这条自定义账号既没有 API Key,也没有勾选「无需鉴权」:转发时会被跳过,该提供商下的模型也不会出现在模型列表里。去账号「设置」里补上 Key,或勾选「该上游无需鉴权」")}:null,e.proxy?.error?{text:r("代理异常"),kind:"bad",title:r("{error}(转发时会回退直连)",{error:e.proxy.error})}:null,mj(e)===So?{text:r("套餐池"),kind:"plain",title:r("转发走套餐池(Start Plan)通道(zcode.z.ai 的 Anthropic 端点,用账号里的体验额度 / 活动领取额度);在账号设置里可切回编码套餐")}:null].filter(t=>t!==null)}const eR="workbuddy-desktop-accounts-filters",tR="workbuddy-desktop-accounts-collapsed",nR="workbuddy-desktop-accounts-names-hidden";function w$(){const e={provider:"all",enabled:"all",limit:"all",q:""},t=Pe().wbFilterMemory?.load(eR,e)||e;return{provider:String(t.provider||"all"),enabled:String(t.enabled||"all"),limit:String(t.limit||"all"),q:""}}function S$(){try{const e=JSON.parse(localStorage.getItem(tR)||"[]");return new Set(Array.isArray(e)?e.map(t=>String(t)).filter(Boolean):[])}catch{return new Set}}function N$(){try{return localStorage.getItem(nR)==="1"}catch{return!1}}let hn={version:0,filter:w$(),collapsed:S$(),selected:new Set,panels:new Map,connections:new Map,clash:null,dialog:null,namesHidden:N$(),usageBusy:!1,usageInflight:new Set};const wj=new Set;function sR(e){return wj.add(e),()=>{wj.delete(e)}}function Gs(){return hn}function Rn(e){hn={...hn,...e,version:hn.version+1},wj.forEach(t=>t())}function jr(){Rn({})}function Sj(){return Pe().wbApp?.getState?.()?.accounts}function Al(){const e=Sj()?.accounts;return Array.isArray(e)?e:[]}function Aa(e){return Al().find(t=>t.id===e)||null}function k$(e,t){const a=v$(Al(),c=>ZA(c,hn.filter,e,t),e,t);return{groups:a.filter(c=>c.accounts.length>0),allGroups:a}}function rR(){return OA(Sj())}function C$(e,t){return WA(Al(),hn.filter,e,t)}function T$(){return vj(Al())}function tg(){Pe().wbFilterMemory?.save(eR,{provider:hn.filter.provider,enabled:hn.filter.enabled,limit:hn.filter.limit})}function E$(e){hn.filter.q!==e&&Rn({filter:{...hn.filter,q:e}})}function A$(e){const t=e||"all";hn.filter.provider!==t&&(Rn({filter:{...hn.filter,provider:t}}),tg())}function aR(e,t){const a={...hn.filter,[e]:t};a.enabled==="disabled"&&a.limit!=="all"&&(a.limit="all"),Rn({filter:a}),tg()}function ng(){return hn.filter.provider!=="all"||hn.filter.enabled!=="all"||hn.filter.limit!=="all"||hn.filter.q.trim()!==""}function lR(){Rn({filter:{provider:"all",enabled:"all",limit:"all",q:""}}),tg()}function R$(){const e=hn.filter.provider;e!=="all"&&(rR().some(t=>t.id===e)||(Rn({filter:{...hn.filter,provider:"all"}}),tg()))}function oR(e){try{localStorage.setItem(tR,JSON.stringify([...e]))}catch{}}function iR(e){const t=new Set(hn.collapsed);t.has(e)?t.delete(e):t.add(e),oR(t),Rn({collapsed:t})}function O$(e,t){const a=new Set(hn.collapsed);for(const o of e)t?a.add(o):a.delete(o);oR(a),Rn({collapsed:a})}function M$(e){return hn.selected.has(e)}function D$(e,t){const a=new Set(hn.selected);t?a.add(e):a.delete(e),Rn({selected:a})}function cR(e,t){const a=new Set(hn.selected);for(const o of e)t?a.add(o):a.delete(o);Rn({selected:a})}function I$(){Rn({selected:new Set})}function uR(e,t){return hn.panels.get(e)?.has(t)===!0}function dR(e,t,a){if(!e)return;const o=new Map(hn.panels),c=new Set(o.get(e)||[]);a?c.add(t):c.delete(t),c.size?o.set(e,c):o.delete(e),Rn({panels:o})}function P$(e,t){const a=new Map(hn.panels);for(const o of e){const c=new Set(a.get(o)||[]);c.add(t),a.set(o,c)}Rn({panels:a})}function _$(){const e=!hn.namesHidden;try{localStorage.setItem(nR,e?"1":"0")}catch{}Rn({namesHidden:e})}function L$(e){return"*".repeat(Math.min(Math.max(e.length,4),12))}const fR="usage_not_configured",No=new Map,Ef=new Map;function ua(e,t,a){No.set(e,t),t!=null&&gu(t)?Ef.set(e,a):Ef.delete(e)}function Wa(e){const t=No.get(e.id);if(t===void 0)return;if(!gu(t))return t;const a=Math.max(Number(e.addedAt)||0,Number(e.updatedAt)||0);return(Ef.get(e.id)||0)>=a?t:void 0}const Af=new Map;let pR=0;function Rl(e){return e?Af.get(e.id)||[]:[]}function z$(e){const t=Number(e?.tokenAt)||0;if(!t||t===pR)return!1;const a=e?.tokenUsage;if(!a||typeof a!="object")return!1;pR=t;const o=new Map;for(const[d,f]of Object.entries(a)){if(!Array.isArray(f))continue;const p=[];for(const h of f){if(!h||typeof h!="object")continue;const b=Number(h.kind),y=Number(h.windowStart),v=Number(h.used);!Number.isFinite(b)||b<0||!Number.isFinite(y)||y<=0||!Number.isFinite(v)||v<0||p.push({kind:b,windowStart:y,used:v})}o.set(d,p)}const c=o.size!==Af.size||[...o].some(([d,f])=>{const p=Af.get(d);return!p||p.length!==f.length||f.some((h,b)=>h.used!==p[b]?.used||h.windowStart!==p[b]?.windowStart)});Af.clear();for(const[d,f]of o)Af.set(d,f);return c}let sg=null;async function mR(e={}){const t=Gs().clash;if(!e.force&&t)return t;sg||(sg=(async()=>{try{const o=await Pe().workbuddyDesktop?.getProxies?.();if(!o||typeof o!="object"||!o.clash)throw new Error(r("代理列表响应异常({type})",{type:typeof o}));return o.clash}finally{sg=null}})());const a=await sg;return Rn({clash:a}),a}function B$(){Rn({clash:null})}let Rf=null,rg=null;function H$(){return Rf}async function hR(e={}){if(!e.force&&Rf)return Rf;rg||(rg=(async()=>{try{const a=await Pe().workbuddyDesktop?.getProxyPool?.();if(!a||typeof a!="object"||!Array.isArray(a.items))throw new Error(r("代理池响应异常({type})",{type:typeof a}));return a.items}finally{rg=null}})());const t=await rg;return Rf=t,t}let Nj=null;function U$(){return Nj}let ag=0,gR=!1;function V$(){if(!(Rf||Date.now(){ag=0,Nj=null,jr()}).catch(e=>{Nj=mt(e),jr()})}}function lg(e){if(!Aa(e)){Le(r("账号不存在,请刷新后重试"),"err");return}Rn({dialog:{kind:"settings",id:e}})}function og(){Rn({dialog:null})}function kj(e,t="enable"){const a=(Array.isArray(e)?e:[]).filter(o=>Aa(o));if(!a.length){Le(r("请先勾选要操作的账号"),"err");return}Rn({dialog:{kind:"batch",ids:a,action:t}})}function F$(e){let t=!1;for(const f of[...No.keys()])e.has(f)||(No.delete(f),t=!0);for(const f of[...Ef.keys()])e.has(f)||Ef.delete(f);const a=new Map(Gs().panels);for(const f of[...a.keys()])e.has(f)||(a.delete(f),t=!0);const o=new Map(Gs().connections);for(const f of[...o.keys()])e.has(f)||(o.delete(f),t=!0);const c=new Set(Gs().usageInflight);for(const f of[...c])e.has(f)||(c.delete(f),t=!0);const d=new Set(Gs().selected);for(const f of[...d])e.has(f)||(d.delete(f),t=!0);t&&Rn({panels:a,connections:o,usageInflight:c,selected:d})}const $$=2e3;function xR(e){return Gs().connections.get(e)||0}async function bR(){try{const e=await Pe().workbuddyDesktop?.getAccountConnections?.(),t=e?.counts&&typeof e.counts=="object"?e.counts:{},a=new Map;for(const[o,c]of Object.entries(t)){const d=Number(c)||0;d>0&&a.set(o,d)}return q$(a,Gs().connections)||Rn({connections:a}),!0}catch{return!1}}function q$(e,t){if(e.size!==t.size)return!1;for(const[a,o]of e)if(t.get(a)!==o)return!1;return!0}let vR=null;function G$(){vR||(vR=setInterval(()=>{document.hidden||Pe().wbApp?.currentPage!=="accounts"||bR()},$$))}function Cj(){return Al().filter(e=>Ea(e)&&e.available!==!1)}function gu(e){if(e==null)return null;if(typeof e=="string")return{message:e,notConfigured:!1};if(typeof e!="object")return null;const t=e.error;return t?{message:String(t),notConfigured:e.code===fR}:null}function yR(e){return e.usage?e.usage:{error:e.error?String(e.error):r("余额响应为空"),code:e.code}}function jR(e){const t=Array.isArray(e?.results)?e.results:[],a=Number(e?.at)||Date.now();let o=0;for(const c of t)c?.id&&(ua(String(c.id),yR(c),Number(c.at)||a),o++);return o&&(jr(),Pe().wbApp?.renderTopbarStatus?.()),o}let wR=!1;function K$(e){if(!GA(e))return!1;const t=Wa(e);return!t||typeof t!="object"||Array.isArray(t)||gu(t)?!1:!Array.isArray(t.credits)}async function Y$(){if(!wR){wR=!0;for(const e of Al().filter(K$)){const t=No.get(e.id);try{await Of(e.id)}catch{}const a=No.get(e.id);t!==void 0&&(!a||gu(a))&&ua(e.id,t,Date.now()),jr()}}}let SR=0;async function X$(){try{const e=await Pe().workbuddyDesktop?.getBalancesSnapshot?.(),t=z$(e);t&&(jr(),Pe().wbApp?.renderTopbarStatus?.());const a=Number(e?.at)||0;return!a||a===SR||(SR=a,!jR(e))?t:(Y$(),!0)}catch{return!1}}async function Of(e){const t=await Pe().workbuddyDesktop?.getAllBalances?.(e||void 0),a=Array.isArray(t?.results)?t.results:[],o=Date.now(),c=new Set;for(const d of a){if(!d?.id)continue;const f=String(d.id);e&&f!==e||(c.add(f),ua(f,yR(d),o))}if(e)return c.has(e)||ua(e,r("未返回余额数据"),o),jr(),t;for(const d of Cj())c.has(d.id)||ua(d.id,r("未返回余额数据"),o);return jr(),t}async function NR(){if(Gs().usageBusy)return;const e=Cj();if(!e.length){Le(r("暂无可查询余额的账号"),"err");return}Rn({usageBusy:!0}),e.forEach(t=>ua(t.id,null,Date.now())),jr();try{const t=(await Of(null))?.results||[],a=t.filter(f=>f.usage).length,o=t.filter(f=>f.code===fR).length,c=o?r("({n} 个未配置查询凭证)",{n:o}):"",d=t.length-a-o;Le(a+o===t.length?r("✅ 已更新 {n} 个账号的余额{suffix}",{n:a,suffix:c}):r("已更新 {ok}/{total} 个账号,{failed} 个失败",{ok:a,total:t.length,failed:d}),d?"err":"ok")}catch(t){const a=mt(t);e.forEach(o=>ua(o.id,r("查询失败:{message}",{message:a}),Date.now())),jr(),Le(r("余额查询失败:{message}",{message:a}),"err")}finally{Rn({usageBusy:!1})}}async function kR(e){if(Gs().usageInflight.has(e))return;const t=new Set(Gs().usageInflight);t.add(e),ua(e,null,Date.now()),Rn({usageInflight:t});try{await Of(e)}finally{const a=new Set(Gs().usageInflight);a.delete(e),Rn({usageInflight:a})}}async function Q$(e){if(!Gs().usageInflight.has(e))try{await kR(e);const t=gu(No.get(e));t?.notConfigured?Le(t.message,"ok"):t?Le(r("余额查询失败:{message}",{message:t.message}),"err"):Le(r("✅ 已更新余额"))}catch(t){ua(e,r("查询失败:{message}",{message:mt(t)}),Date.now()),jr(),Le(r("余额查询失败:{message}",{message:mt(t)}),"err")}}async function ig(e){if(e){const a=Aa(e);if(!a||!Ea(a))return;try{await kR(e)}catch(o){ua(e,r("查询失败:{message}",{message:mt(o)}),Date.now()),jr()}return}if(Gs().usageBusy)return;const t=Cj();if(t.length){Rn({usageBusy:!0}),t.forEach(a=>ua(a.id,null,Date.now())),jr();try{await Of(null)}catch(a){const o=mt(a);t.forEach(c=>ua(c.id,r("查询失败:{message}",{message:o}),Date.now())),jr()}finally{Rn({usageBusy:!1})}}}async function CR(e,t){try{await Pe().workbuddyDesktop?.updateAccount?.(e,{enabled:t}),await Pe().wbApp?.refresh?.(),Le(r(t?"✅ 已启用":"✅ 已禁用"))}catch(a){Le(r("操作失败:{message}",{message:mt(a)}),"err"),Pe().wbApp?.refresh?.()}}async function TR(e,t){if(!e.length)return!1;try{return await Pe().workbuddyDesktop?.reorderAccounts?.(e),Le(t?r("✅ 已保存:{note}",{note:t}):r("✅ 顺序已保存")),await Pe().wbApp?.refresh?.(),!0}catch(a){return Le(r("顺序未保存:{message}",{message:mt(a)}),"err"),Pe().wbApp?.refresh?.(),!1}}async function ER(e,t){if(e.length)try{await Pe().workbuddyDesktop?.batchAccounts?.({action:t?"enable":"disable",ids:e}),Le(t?r("✅ 已启用 {n} 个账号",{n:e.length}):r("✅ 已禁用 {n} 个账号",{n:e.length})),await Pe().wbApp?.refresh?.()}catch(a){Le(r("操作失败:{message}",{message:mt(a)}),"err"),Pe().wbApp?.refresh?.()}}async function Z$(e,t){try{await Pe().workbuddyDesktop?.clearRateLimits?.(e,t||null),Le(t?r("✅ 已清除 {model} 的限流标记",{model:t}):r("✅ 已清除该账号全部限流标记")),await Pe().wbApp?.refresh?.()}catch(a){Le(r("清除失败:{message}",{message:mt(a)}),"err")}}async function W$(e,t,a){if(t===AR){lg(e);return}if(t!==cg&&t!==a)try{const o=t===""?null:{source:"pool",proxyId:t.slice(Qa.length)},d=(await Pe().workbuddyDesktop?.updateAccount?.(e,{proxy:o}))?.changes,f=Array.isArray(d)&&d.length?d[0]:r("代理已更新");Le(`✅ ${f}`)}catch(o){Le(r("保存失败:{message}",{message:mt(o)}),"err")}finally{await Pe().wbApp?.refresh?.()}}const cg="__proxy_custom__",AR="__proxy_custom_edit__";function RR(e,t){const a=Aa(e);if(!a){Le(r("账号不存在,请刷新后重试"),"err");return}const o=Pe().wbZcodePlans;if(!o?.open){Le(r("套餐明细弹窗未加载,请重启应用后重试"),"err");return}o.open({id:e,name:t||a.name})}function J$(e,t,a=1){return{seat:t.get(e.id)||{position:1,total:1},rank:a,picked:M$(e.id),usageEntry:No.get(e.id),limitsOpen:uR(e.id,"limits"),connections:xR(e.id)}}const e8={DEFAULT_PROVIDER_ID:pu,RACCOON_PROVIDER_ID:Z6,providerOf:An,providerFeatures:cr,providerSummaries:OA,identifierOf:Xh,tokenExpiryOf:r$,supportsUsage:Ea,isDesktopAccount:kf,supportsChat:UA,byPriorityOrder:Wh,typeLabel:p$,isEnabled:ur,isRateLimited:Cf,isLimited:e=>Tf(e,e?Wa(e):void 0,Rl(e)),accountEdition:VA,supportsClaim:FA,matchEnabled:xj,matchLimit:QA,visibleAccounts:b$,filterCounts:WA,positionMap:vj,activeLimits:bj,editionSuffix:y$,formatResetText:jj};function t8(){window.wbAccountsView={render:()=>jr(),refreshCaches:F$,openPanels:P$,syncConnections:bR,applyBalances:jR,syncBalancesSnapshot:X$,queryUsageFor:Of,queryAllUsage:NR,refreshUsageAfterCheckin:ig,supportsUsage:Ea,isDesktopAccount:kf,isEnabled:ur,isRateLimited:Cf},window.wbAccountsModel=e8,window.wbAccountPanel={open:lg,close:og,openBatch:kj,closeBatch:og,syncAddProvider:()=>Pe().wbAccountAddForms?.syncAddProvider?.(),invalidate:B$}}function n8(e){return e.type==="balance"?r("余额 < {threshold}",{threshold:e.threshold}):e.reset==="daily"?r("每日消耗 ≥ {count} Token(每天 0 点重置)",{count:El(e.threshold)}):r("每 {period}消耗 ≥ {count} Token",{period:HA(e.period??0),count:El(e.threshold)})}function s8(e){return e.action==="disable"?r("禁用该账号(需手动重新启用)"):r("跳过该账号(自动恢复)")}function r8(e){return`${Math.round(e.threshold).toLocaleString("en-US")} Token`}function a8(e,t){if(t.enabled===!1)return{text:r("已停用"),kind:"off"};if(t.type==="balance"){const b=Wa(e),y=Qh(e,b),v=b&&typeof b=="object"?b:null,j=v?v.totalLeft??v.available:void 0,w=j==null||j===""||v?.unlimited?"":r(" · 当前 {n}",{n:ss(j)});return y?{text:r("已跳过{current}",{current:w}),kind:"warn",title:r("余额低于阈值,转发时会跳过该账号(余额回升自动恢复)")}:{text:r("未触发{current}",{current:w}),kind:"ok"}}const a=Rl(e),o=Nf(t,a),c=o?o.used:0,d=El(t.threshold),f=t.reset==="daily"?r(" · 今日 {used} / {quota}",{used:El(c),quota:d}):r(" · 本周期 {used} / {quota}",{used:El(c),quota:d}),p=o?` · ${Zh(pj(t).remainingMs,t.reset==="daily")}`:"";return o!==null&&c>=t.threshold?t.action==="disable"?e.enabled===!1?{text:r("已触发 · 账号已禁用"),kind:"danger",title:r("重置也不恢复,需手动启用")}:{text:r("已达上限{usage}",{usage:f}),kind:"warn",title:r("稍后由后台判定自动禁用")}:{text:r("已跳过{usage}{countdown}",{usage:f,countdown:p}),kind:"warn",title:r("窗口内已用 {used} / {limit} Token,转发时会跳过该账号(重置后自动恢复)",{used:Math.round(c).toLocaleString("en-US"),limit:Math.round(t.threshold).toLocaleString("en-US")})}:{text:r("未触发{usage}{countdown}",{usage:f,countdown:p}),kind:"ok",title:r8(t)}}function l8(e){return e>0&&e%3600===0?{value:String(e/3600),unit:"hours"}:e>0&&e%60===0?{value:String(e/60),unit:"minutes"}:{value:"1",unit:"hours"}}function OR(e){const t={type:"balance",action:"skip",thresholdInput:"",tokenUnit:"wan",reset:"fixed",periodInput:"1",periodUnit:"hours"};if(!e)return t;if(e.type==="balance")return{...t,type:"balance",action:e.action,thresholdInput:String(e.threshold)};if(e.reset==="daily")return{...t,type:"token",action:e.action,reset:"daily",thresholdInput:String(e.threshold%1e4===0?e.threshold/1e4:e.threshold),tokenUnit:e.threshold%1e4===0?"wan":"unit"};const a=l8(e.period??0);return{...t,type:"token",action:e.action,reset:"fixed",thresholdInput:String(e.threshold%1e4===0?e.threshold/1e4:e.threshold),tokenUnit:e.threshold%1e4===0?"wan":"unit",periodInput:a.value,periodUnit:a.unit}}function MR(e){const t=Number(e.thresholdInput);if(!Number.isFinite(t)||t<=0)return{error:r("限制阈值必须是大于 0 的数字")};if(e.type==="balance")return{rule:{type:"balance",action:e.action,threshold:t,enabled:!0}};const a=Math.round(e.tokenUnit==="wan"?t*1e4:t);if(e.reset==="daily")return{rule:{type:"token",action:e.action,threshold:a,reset:"daily",enabled:!0}};const o=Number(e.periodInput)*(e.periodUnit==="hours"?3600:60);if(!Number.isFinite(o)||o<=0)return{error:r("请填写重置周期")};const c=Math.round(o);return c_A?{error:r("重置周期必须是 30 分钟 ~ 24 小时")}:{rule:{type:"token",action:e.action,threshold:a,period:c,reset:"fixed",enabled:!0}}}function o8({account:e,target:t,onClose:a,onSave:o}){const[c,d]=x.useState(""),[f,p]=x.useState(t?.draft??null);if(x.useEffect(()=>{p(t?.draft??null),d("")},[t]),!t||!f)return null;const h=v=>{d(""),p({...f,...v})},b=()=>{const v=MR(f);if("error"in v){d(v.error);return}o(v.rule,t.index)},y=()=>{if(f.type==="balance"){const P=Wa(e);if(P&&typeof P=="object"){const R=P;if(R.unlimited)return r("当前可用 ∞(不参与余额不足判定)");const C=R.totalLeft??R.available;if(C!=null&&C!=="")return r("当前余额 {n};与余额列同一数字口径,严格小于才触发(等于阈值仍可用)",{n:ss(C)})}return r("读数来自自动余额查询;与余额列同一数字口径,严格小于才触发(等于阈值仍可用)")}const v=MR(f);if(!("rule"in v))return"";const j=v.rule,w=Nf(j,Rl(e));if(!w)return j.reset==="daily"?r("窗口 = 今天 0 点起(本地时区),0 点重置即清零恢复;按账号在 requests 表聚合"):r("窗口对齐自然时间(整点 / 整 N 分钟一轮回),重置即清零恢复;按账号在 requests 表聚合");const S=pj(j),N=El(w.used),k=El(j.threshold),A=j.reset==="daily"?r("今日已用"):r("本周期已用");return r("{scope} {used} / {quota} Token,{countdown}重置",{scope:A,used:N,quota:k,countdown:Zh(S.remainingMs,S.daily)})};return s.jsx(Yt,{open:!0,onOpenChange:v=>{v||a()},children:s.jsxs(Xt,{className:"w-[min(580px,calc(100vw-48px))]",showCloseButton:!0,children:[s.jsx(Vt,{children:s.jsx(Ut,{children:t.index>=0?r("编辑限制"):r("添加限制")})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("限制类型")}),s.jsxs(ut,{value:f.type,onValueChange:v=>h({type:v,thresholdInput:""}),children:[s.jsx(ft,{className:"w-[150px]","aria-label":r("限制类型"),children:s.jsx(dt,{children:f.type==="balance"?r("余额"):r("Token 消耗")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"balance",children:r("余额")}),s.jsx($e,{value:"token",children:r("Token 消耗")})]})]}),s.jsx("span",{className:"detail",children:r("余额沿用现有口径;Token 按重置方式内的累计消耗判定(切换类型会清空阈值)")})]}),f.type==="balance"?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("触发条件")}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("余额低于")}),s.jsx(Fe,{type:"number",min:0,step:1,className:"max-w-[120px]",placeholder:r("阈值"),value:f.thresholdInput,onChange:v=>h({thresholdInput:v.currentTarget.value})}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("时")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("触发后")}),s.jsxs(ut,{value:f.action,onValueChange:v=>h({action:v}),children:[s.jsx(ft,{className:"min-w-[280px]","aria-label":r("触发动作"),children:s.jsx(dt,{children:f.action==="disable"?r("禁用该账号(需手动重新启用)"):r("跳过该账号(余额回升自动恢复)")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"skip",children:r("跳过该账号(余额回升自动恢复)")}),s.jsx($e,{value:"disable",children:r("禁用该账号(需手动重新启用)")})]})]})]})]}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("重置方式")}),s.jsxs(ut,{value:f.reset,onValueChange:v=>h({reset:v}),children:[s.jsx(ft,{className:"w-[190px]","aria-label":r("重置方式"),children:s.jsx(dt,{children:f.reset==="daily"?r("自然日(每天 0 点)"):r("固定周期")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"fixed",children:r("固定周期")}),s.jsx($e,{value:"daily",children:r("自然日(每天 0 点)")})]})]}),s.jsx("span",{className:"detail",children:r("有的账号过了 0 点额度就回来 —— 选「自然日」")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("触发条件")}),f.reset==="daily"?s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"detail",style:{fontSize:13},children:r("每日消耗 ≥")}),s.jsx(Fe,{type:"number",min:0,step:1,className:"max-w-[110px]",placeholder:r("阈值"),value:f.thresholdInput,onChange:v=>h({thresholdInput:v.currentTarget.value})}),s.jsxs(ut,{value:f.tokenUnit,onValueChange:v=>h({tokenUnit:v}),children:[s.jsx(ft,{className:"w-[92px]","aria-label":r("Token 单位"),children:s.jsx(dt,{children:f.tokenUnit==="wan"?r("万"):r("个")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"wan",children:r("万")}),s.jsx($e,{value:"unit",children:r("个")})]})]}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("Token 时")})]}):s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"detail",style:{fontSize:13},children:r("每")}),s.jsx(Fe,{type:"number",min:1,step:1,className:"max-w-[90px]",placeholder:r("周期"),value:f.periodInput,onChange:v=>h({periodInput:v.currentTarget.value})}),s.jsxs(ut,{value:f.periodUnit,onValueChange:v=>h({periodUnit:v}),children:[s.jsx(ft,{className:"w-[92px]","aria-label":r("周期单位"),children:s.jsx(dt,{children:f.periodUnit==="hours"?r("小时"):r("分钟")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"minutes",children:r("分钟")}),s.jsx($e,{value:"hours",children:r("小时")})]})]}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("内消耗 ≥")}),s.jsx(Fe,{type:"number",min:0,step:1,className:"max-w-[110px]",placeholder:r("阈值"),value:f.thresholdInput,onChange:v=>h({thresholdInput:v.currentTarget.value})}),s.jsxs(ut,{value:f.tokenUnit,onValueChange:v=>h({tokenUnit:v}),children:[s.jsx(ft,{className:"w-[92px]","aria-label":r("Token 单位"),children:s.jsx(dt,{children:f.tokenUnit==="wan"?r("万"):r("个")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"wan",children:r("万")}),s.jsx($e,{value:"unit",children:r("个")})]})]}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("Token 时")})]})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("触发后")}),s.jsxs(ut,{value:f.action,onValueChange:v=>h({action:v}),children:[s.jsx(ft,{className:"min-w-[280px]","aria-label":r("触发动作"),children:s.jsx(dt,{children:f.action==="disable"?r("禁用该账号(需手动重新启用)"):r("跳过该账号(重置后自动恢复)")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"skip",children:r("跳过该账号(重置后自动恢复)")}),s.jsx($e,{value:"disable",children:r("禁用该账号(需手动重新启用)")})]})]})]})]}),s.jsx("p",{className:"detail limiter-hint",children:y()}),c?s.jsx("p",{className:"detail text-destructive",children:c}):null]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",onClick:a,children:r("取消")}),s.jsx(ne,{variant:"default",onClick:b,children:t.index>=0?r("保存规则"):r("添加规则")})]})]})})}function i8({account:e,draft:t,onChange:a}){const[o,c]=x.useState(null),d=()=>c({index:-1,draft:OR(null)}),f=y=>c({index:y,draft:OR(t[y])}),p=(y,v)=>{const j=[...t];v>=0?j[v]=y:j.push(y),a(j),c(null)},h=y=>{a(t.filter((v,j)=>j!==y)),o&&c(null)},b=(y,v)=>{const j=[...t];j[y]={...j[y],enabled:v},a(j)};return s.jsxs(s.Fragment,{children:[t.length?s.jsx("div",{className:"limiter-rules mt-2.5",children:t.map((y,v)=>{const j=a8(e,y);return s.jsxs("div",{className:"limiter-rule","data-off":y.enabled===!1||void 0,children:[s.jsx(ns,{checked:y.enabled!==!1,"aria-label":r("启用该规则"),onCheckedChange:w=>b(v,w===!0)}),s.jsx("div",{className:"limiter-rule-main",children:s.jsxs("span",{className:"limiter-rule-cond",children:[s.jsx(ze,{variant:"secondary",shape:"tag",children:y.type==="balance"?r("余额"):"Token"})," ",r("{cond} 时 → {action}",{cond:n8(y),action:s8(y)})]})}),s.jsx(ze,{variant:j.kind==="ok"?"success":j.kind==="warn"?"warning":j.kind==="danger"?"destructive":"secondary",shape:"tag",title:j.title,children:j.text}),s.jsxs("div",{className:"limiter-rule-ops",children:[s.jsx(ne,{variant:"ghost",onClick:()=>f(v),children:r("编辑")}),s.jsx(ne,{variant:"ghost",onClick:()=>h(v),children:r("删除")})]})]},v)})}):s.jsx("p",{className:"detail mt-2.5",children:r("还没有限制规则:账号照常参与转发,余额与 Token 消耗都不设上限。")}),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx(ne,{variant:"outline",onClick:d,children:r("+ 添加限制")}),s.jsx("span",{className:"detail",children:r("可添加多条;同类规则也允许并存(例如一条按余额、两条不同重置方式的 Token)")})]}),s.jsx(o8,{account:e,target:o,onClose:()=>c(null),onSave:p})]})}function c8(e,t){const a=mu(e);return JSON.stringify(t)===JSON.stringify(a)?null:{patch:{limiters:t}}}function u8(e){return mu(e).map(t=>({...t}))}const d8={seconds:1,minutes:60,hours:3600};function f8(e){return e>0&&e%3600===0?{value:String(e/3600),unit:"hours"}:e>0&&e%60===0?{value:String(e/60),unit:"minutes"}:e>0?{value:String(e),unit:"seconds"}:{value:"5",unit:"minutes"}}function p8(e){const{enabled:t,interval:a}=zA(e),o=f8(t?a:0);return{enabled:t,intervalInput:o.value,unit:o.unit}}function m8(e,t){const a=Math.round(Number(t.intervalInput)*d8[t.unit]);if(t.enabled){if(!Number.isFinite(Number(t.intervalInput))||Number(t.intervalInput)<=0)return{error:r("请填写查询间隔")};if(aDA)return{error:r("查询间隔必须是 {min} 秒 ~ 24 小时",{min:uj})}}const o={},c=zA(e);return(t.enabled!==c.enabled||t.enabled&&a!==c.interval)&&(o.usageQuery={enabled:t.enabled,interval:t.enabled?a:c.interval}),o.usageQuery?{patch:o}:null}function h8({account:e,draft:t,onChange:a}){const o=c=>a({...t,...c});return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"field-row mt-2.5",children:s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2.5 font-normal",children:[s.jsx(ns,{checked:t.enabled,onCheckedChange:c=>o({enabled:c===!0}),"aria-label":r("自动查询余额")}),s.jsx("span",{className:"text-xs text-subtle",children:r("自动查询余额(按下面的间隔自动刷新余额列的读数)")})]})}),t.enabled?s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-usage-interval",children:r("查询间隔")}),s.jsx(Fe,{id:"account-usage-interval",type:"number",min:1,step:1,className:"max-w-[110px]",value:t.intervalInput,onChange:c=>o({intervalInput:c.currentTarget.value})}),s.jsxs(ut,{value:t.unit,onValueChange:c=>o({unit:c}),children:[s.jsx(ft,{className:"w-[92px]","aria-label":r("间隔单位"),children:s.jsx(dt,{children:t.unit==="hours"?r("小时"):t.unit==="minutes"?r("分钟"):r("秒")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"seconds",children:r("秒")}),s.jsx($e,{value:"minutes",children:r("分钟")}),s.jsx($e,{value:"hours",children:r("小时")})]})]}),s.jsx("span",{className:"detail",children:r("30 秒 ~ 24 小时;手动查询会顺延下一轮")})]}):null]})}const g8={sub2api:{label:"Sub2API",endpoint:"{base}/v1/usage",note:r("用这条账号的 API Key 查询,不需要额外配置。"),fields:[]},new_api:{label:"NewAPI",endpoint:"{base}/api/user/self + /api/status",note:r("用 NewAPI 站点的个人访问令牌查询账户余额(不是这条账号的上游 API Key)。令牌在站点的「个人设置」里生成,只有旧版 / 定制站点才需要额外填用户 ID。"),fields:[{key:"accessToken",label:r("NewAPI 个人访问令牌"),secret:!0,placeholder:r("在 NewAPI 站点「个人设置」里生成的访问令牌"),hint:r("必填;留空 = 不修改,清除用右边的按钮")},{key:"userId",label:r("NewAPI 用户 ID"),placeholder:r("旧版 / 定制站点才需要,新版可留空"),hint:r("可留空:新版请求头只认令牌;旧版会把用户 ID 放进 New-Api-User 头")}]},deepseek:{label:"DeepSeek",endpoint:"{base}/user/balance",note:r("用这条账号的 API Key 查询,不需要额外配置。"),fields:[]},opencode:{label:"OpenCode Go",endpoint:"{base}/v1/usage",note:r("用这条账号的 API Key 查询订阅用量,不需要额外配置;读数展开成 5 小时 / 每周 / 每月三个窗口。"),fields:[]},sensenova:{label:"商汤日日新",endpoint:"platform.sensenova.cn 控制台",note:r("用商汤日日新控制台的账号密码查询(与推理用的 API Key 不是同一套)。网关会自动换取登录票并缓存,过期后自动重登,不需要手动维护。"),fields:[{key:"username",label:r("账号"),placeholder:r("商汤日日新控制台的登录账号"),hint:r("必填")},{key:"password",label:r("密码"),secret:!0,placeholder:r("商汤日日新控制台的登录密码"),hint:r("留空 = 不修改,清除用右边的按钮")}]},zhipu:{label:"智谱",endpoint:"bigmodel.cn 控制台",note:r("用 bigmodel.cn 控制台的访问令牌查询账户余额(人民币元)。令牌是登录后浏览器 Cookie `bigmodel_token_production` 的值:开发者工具 → 应用(Application)→ Cookie 里复制。"),fields:[{key:"token",label:r("访问令牌"),secret:!0,placeholder:r("bigmodel_token_production 的值"),hint:r("必填;留空 = 不修改,清除用右边的按钮")}]},zhipu_zai:{label:"智谱(z.ai 国际)",endpoint:"api.z.ai 控制台",note:r("用这条账号的 API Key 生成签名后查询账户余额(美元),不需要额外配置。要求 API Key 是 z.ai 的「id.secret」形态(控制台生成的 Key 就是)。"),fields:[]}};function Mf(e){return e?g8[e]??null:null}function x8(e,t){return t.secret?t.key==="accessToken"?e?.hasAccessToken===!0:t.key==="password"?e?.hasPassword===!0:t.key==="token"?e?.hasToken===!0:!1:!1}function b8(e){const t=String(e?.scheme||"");return t==="new_api"?e?.hasAccessToken===!0:t==="sensenova"?String(e?.username||"").trim()!==""&&e?.hasPassword===!0:t==="zhipu"?e?.hasToken===!0:!0}function v8(e){return{userId:String(e?.userId||""),username:String(e?.username||""),accessToken:"",password:"",token:""}}function y8(e,t){const a=Mf(e);if(!a||!a.fields.length)return null;const o={};for(const c of a.fields){const d=String(t[c.key]??"").trim();if(c.secret){d&&(o[c.key]=d);continue}o[c.key]=d}return Object.keys(o).length?o:null}function j8({field:e,value:t,configured:a,onValue:o,onClear:c,clearBusy:d,idPrefix:f}){const p=`${f}-${e.key}`;return s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:p,children:e.label}),s.jsx(Fe,{id:p,className:"min-w-[220px]",type:e.secret?"password":"text",autoComplete:e.secret?"new-password":"off",placeholder:a?r("已配置,留空则不修改"):e.placeholder,title:e.hint,value:t,onChange:h=>o(h.currentTarget.value)}),a&&c?s.jsx(ne,{variant:"outline",size:"sm",disabled:d===!0,onClick:c,title:r("清除已配置的 {label}",{label:e.label}),children:r("清除")}):null]})}function w8({spec:e,values:t,configured:a,onValue:o,onClear:c,clearBusy:d,idPrefix:f}){return s.jsxs(s.Fragment,{children:[s.jsxs("p",{className:"detail mt-2.5",children:[r("余额查询方案:{label}",{label:e.label}),s.jsx("span",{className:"ml-1 text-subtle",children:e.endpoint})," — ",e.note]}),e.fields.map(p=>s.jsx(j8,{field:p,idPrefix:f,value:t[p.key]||"",configured:a[p.key]===!0,onValue:h=>o(p.key,h),onClear:c?()=>c(p.key):void 0,clearBusy:d},p.key))]})}const DR=64;function S8(e,t){const a=An(e);return t.filter(o=>o.id!==e.id&&An(o)===a)}const Ol=999,IR=8;function ug(e){return hu(e)||e?.id||""}function PR(e){const t=e?.config?.source||e?.source,a=e?.config||null,o=t==="rotate";return{mode:t==="pool"?"pool":o?"rotate":t==="clash"?"clash":t==="custom"?"custom":"none",proxyId:t==="pool"?String(a?.proxyId||""):"",rotateAll:o?a?.all!==!1:!0,rotateIds:o&&Array.isArray(a?.proxyIds)?a.proxyIds.map(String):[],listenerUid:a?.source==="clash"||t==="clash"?String(a?.listenerUid||""):"",protocol:a?.protocol==="socks5"?"socks5":"http",host:a?.host||"",port:a?.port===void 0||a?.port===null?"":String(a.port),username:a?.username||"",password:a?.password||""}}function Tj(e){if(e.mode==="none")return null;if(e.mode==="pool"){if(!e.proxyId)throw new Error(r("请先选择已保存的代理"));return{source:"pool",proxyId:e.proxyId}}if(e.mode==="rotate"){if(e.rotateAll)return{source:"rotate",all:!0};if(!e.rotateIds.length)throw new Error(r("轮询至少要选择一条代理(或改选「全部」)"));return{source:"rotate",all:!1,proxyIds:[...e.rotateIds]}}if(e.mode==="clash"){if(!e.listenerUid)throw new Error(r("请先选择 Clash Verge 出口"));return{source:"clash",listenerUid:e.listenerUid}}const t=e.host.trim(),a=Number(e.port);if(!t)throw new Error(r("请填写代理主机地址"));if(!Number.isInteger(a)||a<1||a>65535)throw new Error(r("代理端口必须是 1-65535 的整数"));return{source:"custom",protocol:e.protocol==="socks5"?"socks5":"http",host:t,port:a,username:e.username.trim(),password:e.password}}function _R(e){const t=e.profileActive===!1?r("(其他订阅,可能未生效)"):"",a=e.enabled===!1?r("(已在 Clash 中禁用)"):"";return`${e.name} :${e.port}${t}${a}`}function LR({draft:e,onChange:t,idPrefix:a,allowRotate:o=!1}){const d=Gs().clash,f=Array.isArray(d?.options)?d.options:[],p=e.mode==="clash",[h,b]=x.useState(!1),[y,v]=x.useState(null),[j,w]=x.useState(null),[S,N]=x.useState(""),k=C=>t({...e,...C});x.useEffect(()=>{p&&mR().catch(()=>{})},[p]);const A=x.useCallback((C=!1)=>{N(""),hR({force:C}).then(E=>w(E)).catch(E=>{w([]),N(mt(E))})},[]);x.useEffect(()=>{(e.mode==="pool"||e.mode==="rotate")&&j===null&&A()},[e.mode,j,A]);function P(){return e.rotateAll?(j??[]).filter(C=>C.enabled!==!1).map(C=>C.id):[...e.rotateIds]}async function R(){if(h)return;if(e.mode==="rotate"){const E=P();if(!E.length){Le(r("轮询至少要选择一条代理(或改选「全部」)"),"err");return}const D=E.slice(0,IR);b(!0),v(r("正在连接上游…"));let I=0;const O=[];for(const H of D){const B=j?.find(L=>L.id===H)?.name||H;try{const L=await Pe().workbuddyDesktop?.testProxyPoolItem?.(H);L?.success?I+=1:O.push(`${B}(${L?.error||r("连接失败")})`)}catch(L){O.push(`${B}(${mt(L)})`)}}const _=E.length-D.length,z=r("✅ {ok}/{total} 个出口可用",{ok:I,total:D.length})+(_>0?r("(只测了前 {limit} 个,还有 {rest} 个未测)",{limit:IR,rest:_}):"");v(s.jsxs("span",{className:O.length?"text-destructive":"text-success",children:[z,O.length?` ${Za(O.join(r(";")))}`:""]})),b(!1);return}if(e.mode==="pool"){if(!e.proxyId){Le(r("请先选择已保存的代理"),"err");return}b(!0),v(r("正在连接上游…"));try{const E=await Pe().workbuddyDesktop?.testProxyPoolItem?.(e.proxyId);v(E?.success?s.jsxs("span",{className:"text-success",children:[r("✅ 出口可用"),E.ip?r(" 出口 IP {ip}",{ip:Za(E.ip)}):"",E.durationMs!==void 0&&E.durationMs!==""?` ${Za(String(E.durationMs))}ms`:""]}):s.jsxs("span",{className:"text-destructive",children:["❌ ",Za(E?.error||r("连接失败"))]}))}catch(E){v(s.jsxs("span",{className:"text-destructive",children:["❌ ",Za(mt(E))]}))}finally{b(!1)}return}let C;try{C=Tj(e)}catch(E){Le(mt(E),"err");return}b(!0),v(r("正在连接上游…"));try{const E=await Pe().workbuddyDesktop?.testProxy?.({proxy:C});E?.success?v(s.jsxs("span",{className:"text-success",children:[r("✅ 出口可用"),E.status!==void 0&&E.status!==""?` HTTP ${Za(String(E.status))}`:"",E.ip?r(" 出口 IP {ip}",{ip:Za(E.ip)}):"",E.durationMs!==void 0&&E.durationMs!==""?` ${Za(String(E.durationMs))}ms`:""]})):v(s.jsxs("span",{className:"text-destructive",children:["❌ ",Za(E?.error||r("连接失败"))]}))}catch(E){v(s.jsxs("span",{className:"text-destructive",children:["❌ ",Za(mt(E))]}))}finally{b(!1)}}return s.jsxs("div",{className:"flex flex-col",children:[s.jsxs(Ph,{value:e.mode,onValueChange:C=>k({mode:C}),className:"flex-row flex-wrap items-center gap-5","aria-label":r("代理方式"),children:[s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(yo,{value:"none"}),r("无代理(直连)")]}),s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(yo,{value:"pool"}),r("已保存的代理")]}),o?s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",title:r("逐请求轮换出口(换 IP):OpenCode Zen 免费档按 IP 限流,单个 IP 的额度用完会对它一律 429"),children:[s.jsx(yo,{value:"rotate"}),r("轮询(换 IP)")]}):null,p?s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(yo,{value:"clash"}),"Clash Verge"]}):null,s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(yo,{value:"custom"}),r("自定义")]})]}),e.mode==="pool"?s.jsxs("div",{className:"mt-3",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:`${a}-pool-exit`,children:r("代理")}),s.jsxs(ut,{value:e.proxyId,disabled:!j?.length,onValueChange:C=>k({proxyId:String(C)}),children:[s.jsx(ft,{id:`${a}-pool-exit`,className:"min-w-[220px]",children:s.jsx(dt,{children:j?.find(C=>C.id===e.proxyId)?du(j.find(C=>C.id===e.proxyId)):j===null?r("正在读取…"):j.length?r("请选择代理"):r("还没有保存的代理")})}),s.jsx(pt,{children:(j??[]).map(C=>s.jsx($e,{value:C.id,children:du(C)},C.id))})]}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>A(!0),children:r("重新读取")})]}),s.jsx("div",{className:"detail mt-1.5",children:S?r("读取失败:{error}",{error:S}):j===null?r("正在读取代理列表…"):j.length?r("地址与端口由「网络代理」页管理:那边改一次、测一次,所有引用它的账号一起生效"):r("「网络代理」页还没有出口 —— 去那里新增,或在「订阅管理」里点「同步 Clash Verge」把 Clash 的出口导进来")})]}):null,e.mode==="rotate"?s.jsxs("div",{className:"mt-3",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-x-2.5 gap-y-1",children:[s.jsx(Pr,{id:`${a}-rotate-all`,checked:e.rotateAll,"aria-label":r("轮询全部代理节点"),onCheckedChange:C=>k({rotateAll:C===!0})}),s.jsx("label",{htmlFor:`${a}-rotate-all`,className:"cursor-pointer text-xs text-subtle",children:r("全部代理节点(推荐)")}),s.jsx("span",{className:"detail",children:r("「网络代理」页里每个启用的出口轮流使用;之后新加的出口自动加入")})]}),e.rotateAll?null:s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:`${a}-rotate-exits`,children:r("轮询的代理")}),s.jsx(Gh,{id:`${a}-rotate-exits`,value:e.rotateIds,onValueChange:C=>k({rotateIds:C.map(String)}),options:(j??[]).map(C=>({value:C.id,label:du(C)})),placeholder:r("选择要轮询的代理(可多选)"),"aria-label":r("轮询的代理")}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>A(!0),children:r("重新读取")})]}),s.jsx("div",{className:"detail mt-1.5",children:S?r("读取失败:{error}",{error:S}):j===null?r("正在读取代理列表…"):j.length?r("每条请求换一个出口(按顺序轮流),上游看到的 IP 因此是变化的;出口的地址与端口由「网络代理」页管理"):r("「网络代理」页还没有出口 —— 去那里新增,或在「订阅管理」里点「同步 Clash Verge」把 Clash 的出口导进来")})]}):null,e.mode==="clash"?s.jsxs("div",{className:"mt-3",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:`${a}-clash-exit`,children:r("出口")}),s.jsxs(ut,{value:e.listenerUid,disabled:!f.length,onValueChange:C=>k({listenerUid:String(C)}),children:[s.jsx(ft,{id:`${a}-clash-exit`,className:"min-w-[220px]",children:s.jsx(dt,{children:f.find(C=>String(C.uid)===e.listenerUid)?_R(f.find(C=>String(C.uid)===e.listenerUid)):d?.available===!1?r("未检测到 Clash Verge"):f.length?r("请选择出口"):r("没有可用出口")})}),s.jsx(pt,{children:f.map(C=>s.jsx($e,{value:String(C.uid),children:_R(C)},String(C.uid)))})]}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>{mR({force:!0}).then(()=>Le(r("✅ 已重新读取 Clash Verge 配置"))).catch(C=>Le(r("读取失败:{error}",{error:mt(C)}),"err"))},children:r("重新读取")})]}),s.jsx("div",{className:"detail mt-1.5",children:d===null?r("正在读取 Clash Verge 配置…"):d.available===!1?d.error?r("不可用:{error}",{error:d.error}):r("未检测到 Clash Verge 配置"):f.length?r("读取自 {dir};端口由 Clash Verge 管理,这里实时同步",{dir:d.dir||"Clash Verge"}):r("Clash Verge 里还没有配置混合监听器或节点端口")}),s.jsxs("p",{className:"detail mt-1.5",children:[r("这是既有配置(直接引用 Clash 出口,不经过代理池)。推荐改用上面的"),s.jsx("b",{children:r("「已保存的代理」")}),r(":到「网络代理」页的「订阅管理」里点「同步 Clash Verge」把出口导进池后即可选 —— 那样能集中测试、也能被多个账号共用。")]})]}):null,e.mode==="custom"?s.jsxs("div",{className:"mt-3",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:`${a}-protocol`,children:r("协议")}),s.jsxs(ut,{value:e.protocol,onValueChange:C=>k({protocol:C}),children:[s.jsx(ft,{id:`${a}-protocol`,className:"min-w-[110px]",children:s.jsx(dt,{children:e.protocol==="socks5"?"SOCKS5":"HTTP"})}),s.jsxs(pt,{children:[s.jsx($e,{value:"http",children:"HTTP"}),s.jsx($e,{value:"socks5",children:"SOCKS5"})]})]}),s.jsx("label",{htmlFor:`${a}-host`,className:"ml-2",children:r("主机")}),s.jsx(Fe,{id:`${a}-host`,className:"min-w-[140px]",placeholder:"127.0.0.1",value:e.host,onChange:C=>k({host:C.currentTarget.value})}),s.jsx("label",{htmlFor:`${a}-port`,children:r("端口")}),s.jsx(Fe,{id:`${a}-port`,type:"number",min:1,max:65535,className:"max-w-[110px]",placeholder:"7890",value:e.port,onChange:C=>k({port:C.currentTarget.value})})]}),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:`${a}-user`,children:r("用户名")}),s.jsx(Fe,{id:`${a}-user`,placeholder:r("可选"),autoComplete:"off",value:e.username,onChange:C=>k({username:C.currentTarget.value})}),s.jsx("label",{htmlFor:`${a}-pass`,children:r("密码")}),s.jsx(Fe,{id:`${a}-pass`,type:"password",placeholder:r("可选"),autoComplete:"new-password",value:e.password,onChange:C=>k({password:C.currentTarget.value})})]})]}):null,s.jsxs("div",{className:"field-row mt-3",children:[s.jsx(ne,{variant:"outline",size:"sm",disabled:h,onClick:()=>{R()},children:r(h?"测试中…":"测试出口")}),s.jsx("span",{className:"detail",children:y})]})]})}function N8({plan:e,hasJwt:t,onChange:a}){const o=m$(e),[c,d]=x.useState(null);return x.useEffect(()=>{if(e!==So)return()=>{};let f=!0;const p=()=>{Promise.resolve(Pe().workbuddyDesktop?.zcodeCaptchaStats?.()).then(b=>{f&&b&&d({ready:Number(b.ready)||0,target:Number(b.target)||0})}).catch(()=>{})};p();const h=window.setInterval(p,5e3);return()=>{f=!1,window.clearInterval(h)}},[e]),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-plan-channel",children:r("使用套餐")}),s.jsxs(ut,{value:e,onValueChange:f=>a(String(f)),children:[s.jsx(ft,{id:"account-plan-channel",className:"min-w-[220px]",children:s.jsx(dt,{children:o})}),s.jsxs(pt,{children:[s.jsx($e,{value:$A,children:r("编码套餐(Coding Plan)— 走开放平台端点,消耗开放平台的额度(订阅套餐 / 资源包 / 充值余额)")}),s.jsx($e,{value:So,children:r("套餐池(Start Plan)— 走 zcode.z.ai 端点,消耗 ZCode 套餐池的额度(新用户体验额度 / 活动领取)")})]})]}),e===So&&!t?s.jsx("span",{className:"detail text-destructive",children:r("该账号没有套餐登录态(jwt),套餐池通道会失败:请重新登录该账号")}):null,e===So?s.jsxs("span",{className:"detail",title:r("套餐池的推理端点要求每条请求带一个阿里云验证码令牌;令牌由本应用在后台静默铸造,界面关闭时无法铸造"),children:[r("验证码令牌:{counts}",{counts:c?`${c.ready} / ${c.target||3}`:r("读取中…")}),c&&c.ready===0?r("(库存为空,正在补;补不上时转发会失败)"):""]}):null]})}function k8({configured:e,value:t,onChange:a,onClear:o,clearBusy:c}){return s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-balance-token-input",children:r("余额查询凭证")}),s.jsx(Fe,{id:"account-balance-token-input",className:"min-w-[220px]",placeholder:r(e?"已配置,留空则不修改":"一般不用填"),title:r("积分查询已复用转发用的登录凭证,这里通常留空即可。只有旧版本填过、或从旧代理导入过凭证时才有值"),value:t,onChange:d=>a(d.currentTarget.value)}),e?s.jsx(ne,{variant:"outline",size:"sm",disabled:c,onClick:o,title:r("清除已配置的余额查询凭证"),children:r("清除")}):null]})}function C8({hasApiKey:e,noAuth:t,value:a,onValue:o,onToggleNoAuth:c,onClear:d,clearBusy:f}){return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-api-key-input",children:r("API Key")}),s.jsx(Fe,{id:"account-api-key-input",type:"password",autoComplete:"new-password",className:"min-w-[220px]",disabled:t,placeholder:e?r("已配置,留空则不修改"):"sk-…",title:r("上游的 API Key。留空 = 不修改(改凭证不会换账号 id);要清掉已配的凭证用右边的「清除」"),value:a,onChange:p=>o(p.currentTarget.value)}),e&&!t?s.jsx(ne,{variant:"outline",size:"sm",disabled:f,onClick:d,title:r("清除已配置的 API Key(转发时会因缺少凭证被跳过)"),children:r("清除")}):null]}),s.jsx("div",{className:"field-row mt-2.5",children:s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2.5 font-normal",children:[s.jsx(Pr,{checked:t,"aria-label":r("该上游无需鉴权"),onCheckedChange:p=>c(p===!0)}),s.jsx("span",{className:"text-xs text-subtle",children:r("该上游无需鉴权(转发与拉取模型都不发送鉴权头)")})]})}),s.jsxs("p",{className:"detail",children:[r("上游本来不要凭证时(本地 Ollama、OpenCode Zen 的免费档)勾上这一项:账号会被正常选路;只把 Key 留空"),s.jsx("strong",{children:r("又不勾")}),r("会被当成「未配置凭证」而跳过。")]})]})}function T8({provider:e,name:t,protocol:a,baseUrl:o,count:c,emulation:d,onName:f,onProtocol:p,onBaseUrl:h,onEmulation:b,onRemove:y}){const v=Pe().wbProviders?.PROTOCOL_OPTIONS||[{value:"openai",label:r("OpenAI 兼容")},{value:"anthropic",label:"Anthropic"}],j=v.find(w=>w.value===a)?.label||a;return s.jsxs(dn,{children:[s.jsx("h3",{children:r("提供商")}),s.jsxs("p",{children:[r("这一栏改的是"),s.jsx("strong",{children:r("「{name}」本身",{name:e.name||e.id})}),r("(名下 {count} 个账号共用)",{count:c}),r("改协议 / Base URL 会改变它们的转发方式,正在进行的请求可能失败;模型清单与映射在「模型管理」页。")]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"account-provider-name",children:r("名称")}),s.jsx(Fe,{id:"account-provider-name",maxLength:DR,className:"min-w-[220px]",placeholder:r("提供商显示名,1~{max} 个字符",{max:DR}),value:t,onChange:w=>f(w.currentTarget.value)})]}),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-provider-protocol",children:r("协议")}),s.jsxs(ut,{value:a,onValueChange:w=>p(String(w)),children:[s.jsx(ft,{id:"account-provider-protocol",className:"min-w-[180px]",children:s.jsx(dt,{children:j})}),s.jsx(pt,{children:v.map(w=>s.jsx($e,{value:w.value,children:w.label},w.value))})]})]}),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-provider-baseurl",children:r("Base URL")}),s.jsx(Fe,{id:"account-provider-baseurl",className:"min-w-[260px]",placeholder:r("OpenAI 兼容填到 /v1;Anthropic 填根地址"),value:o,onChange:w=>h(w.currentTarget.value)})]}),s.jsx("div",{className:"field-row mt-2.5",children:s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2.5 font-normal",children:[s.jsx(Pr,{checked:d==="opencode","aria-label":r("伪装 OpenCode 官方客户端"),onCheckedChange:w=>b(w===!0?"opencode":"")}),s.jsx("span",{className:"text-xs text-subtle",children:r("伪装 OpenCode 官方客户端(OpenCode Zen 免费档要它才放行)")})]})}),s.jsxs("p",{className:"detail",children:[r("开启后,网关按 OpenCode 官方 CLI 的形状发请求:没填 Key 的账号用匿名凭证"),s.jsx("code",{children:"public"}),r("、补官方会话头、请求体补两个占位工具(上游免费档的三道校验)。"),s.jsx("strong",{children:r("它会改写请求体")}),r(",只对 OpenCode Zen 这类上游有意义,别的家请关掉。")]}),s.jsxs("div",{className:"field-row mt-3",children:[s.jsx(ne,{variant:"destructive",onClick:y,children:r("删除提供商")}),s.jsx("span",{className:"detail",children:r("级联删除名下全部账号,不可恢复")})]})]})}function E8({id:e,onClose:t}){const a=Aa(e),[o,c]=x.useState(a?.enabled!==!1),[d,f]=x.useState(a?.name||""),[p,h]=x.useState(()=>PR(a?.proxy)),[b,y]=x.useState(""),[v,j]=x.useState(()=>mj(a)),[w,S]=x.useState(!1),[N,k]=x.useState(""),[A,P]=x.useState(null),[R,C]=x.useState(""),[E,D]=x.useState("chat_completions"),[I,O]=x.useState(""),[_,z]=x.useState(""),[H,B]=x.useState(""),[L,F]=x.useState(a?.noAuth===!0),[$,X]=x.useState(()=>p8(a)),[K,q]=x.useState(()=>v8(a?.balanceQuery)),[Q,G]=x.useState(()=>u8(a)),[J,Y]=x.useState("basic"),[re,M]=x.useState(()=>String(Number(a?.maxConcurrent)||0));if(x.useEffect(()=>{let Ae=!0;P(null);const oe=Aa(e);return oe?(Promise.resolve(Pe().wbCustomProvidersUi?.find?.(An(oe))).then(me=>{!Ae||!me||(P(me),C(me.name||""),D(me.protocol||"chat_completions"),O(me.baseUrl||""),z(typeof me.clientEmulation=="string"?me.clientEmulation:""))}).catch(()=>{}),()=>{Ae=!1}):()=>{Ae=!1}},[e]),!a)return s.jsx(Yt,{open:!0,onOpenChange:Ae=>{Ae||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("账号设置")})}),s.jsx(Lt,{children:s.jsx("p",{className:"detail",children:r("账号不存在,请刷新后重试。")})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")})]})]})});const U=a,Z=S8(U,Al()),ae=An(U)==="catpaw",ce=An(U).startsWith("custom-"),W=RA(A,U.baseUrl)||p.mode==="rotate",ue=Mf(U.balanceQuery?.scheme),ve={};for(const Ae of ue?.fields??[])ve[Ae.key]=x8(U.balanceQuery,Ae);const ee=!!(ue&&ue.fields.length)&&!b8(U.balanceQuery);async function he(){if(!w){S(!0);try{await Pe().workbuddyDesktop?.updateAccount?.(e,{balanceToken:null}),y(""),Le(r("✅ 已清除余额查询凭证")),await Pe().wbApp?.refresh?.()}catch(Ae){Le(r("清除失败:{error}",{error:mt(Ae)}),"err")}finally{S(!1)}}}async function te(){if(!w){S(!0);try{await Pe().workbuddyDesktop?.updateAccount?.(e,{apiKey:null}),B(""),Le(r("✅ 已清除 API Key(该账号现在没有凭证,转发会被跳过)")),await Pe().wbApp?.refresh?.()}catch(Ae){Le(r("清除失败:{error}",{error:mt(Ae)}),"err")}finally{S(!1)}}}async function ke(Ae){if(!w){S(!0);try{await Pe().workbuddyDesktop?.updateAccount?.(e,{balanceQuery:{[Ae]:null}}),q(oe=>({...oe,[Ae]:""})),Le(r("✅ 已清除查询凭证")),await Pe().wbApp?.refresh?.()}catch(oe){Le(r("清除失败:{error}",{error:mt(oe)}),"err")}finally{S(!1)}}}function le(){if(!ce)return null;const Ae=H.trim(),oe={};return Ae?oe.apiKey=Ae:L!==(U.noAuth===!0)&&(oe.noAuth=L),Object.keys(oe).length?oe:null}function de(){if(!A)return null;const Ae=R.trim(),oe=I.trim();if(!Ae)return{error:r("请填写提供商名称")};if(!oe)return{error:r("请填写提供商的 Base URL")};const me=typeof A.clientEmulation=="string"?A.clientEmulation:"";return A.name===Ae&&A.protocol===E&&A.baseUrl===oe&&me===_?null:{id:A.id,name:Ae,protocol:E,baseUrl:oe,clientEmulation:_}}async function Se(){if(w)return;let Ae;try{Ae=Tj(p)}catch(Tt){Le(mt(Tt),"err");return}const oe=de();if(oe&&"error"in oe){k(s.jsx("span",{className:"text-destructive",children:oe.error}));return}const me=Ea(U)?m8(U,$):null;if(me&&"error"in me){k(s.jsx("span",{className:"text-destructive",children:me.error}));return}const pe=c8(U,Q),Ce=y8(U.balanceQuery?.scheme,K),Ne=le()||{},be=Number(re);if(!Number.isFinite(be)||be<0){Le(r("并发上限必须是 0~{max} 的整数",{max:Ol}),"err");return}const De=Math.min(Ol,Math.round(be)),Ge=Number(U.maxConcurrent)||0,Ct=De!==Ge?{maxConcurrent:De}:{};S(!0);try{const Tt=ae&&b.trim()?{balanceToken:b.trim()}:{},Mt=Jh(U)&&v!==mj(U)?{zcodePlan:v}:{};if(await Pe().workbuddyDesktop?.updateAccount?.(e,{name:d.trim()||U.name,enabled:o,proxy:Ae,...Tt,...Mt,...Ne,...Ct,...Ce?{balanceQuery:Ce}:{},...me&&"patch"in me?me.patch:{},...pe&&"patch"in pe?pe.patch:{}}),oe)try{await Pe().wbCustomProvidersUi?.update?.(oe)}catch(ot){k(s.jsx("span",{className:"text-destructive",children:r("账号已保存,但提供商未更新:{error}",{error:mt(ot)})})),await Pe().wbApp?.refresh?.(),S(!1);return}t(),Le(r("✅ 账号设置已保存"));try{await Pe().wbApp?.refresh?.()}catch{}}catch(Tt){k(s.jsx("span",{className:"text-destructive",children:mt(Tt)})),Le(r("保存失败:{error}",{error:mt(Tt)}),"err")}finally{S(!1)}}const Te=Number(cr(An(U)).concurrencyDefault)||0,_e=ae||ce||Jh(U);return s.jsx(Yt,{open:!0,onOpenChange:Ae=>{Ae||w||t()},children:s.jsxs(Xt,{className:"w-[min(900px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("账号设置 · {name}",{name:ug(a)})})}),s.jsx(Lt,{className:"p-0",children:s.jsxs("div",{className:"acct-dlg",children:[s.jsx("aside",{className:"prov-rail acct-dlg-rail","aria-label":r("账号设置分组"),children:s.jsxs("div",{className:"rail-scroll",children:[s.jsx("div",{className:"rail-label",children:r("账号设置")}),[["basic",r("基本")],..._e?[["credential",r("凭证与套餐")]]:[],...Ea(U)?[["query",r("查询设置")],["limiter",r("限制器")]]:[],["network",r("网络")]].map(([Ae,oe])=>s.jsx(uu,{active:J===Ae,title:oe,className:"shadow-none",onClick:()=>Y(Ae),children:oe},Ae))]})}),s.jsxs("div",{className:"acct-dlg-main",children:[J==="basic"?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("基本")}),s.jsx("p",{children:r("这条账号是谁、排第几、能不能接请求。")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("启用")}),s.jsx(ns,{checked:o,onCheckedChange:c,"aria-label":r("启用该账号")}),s.jsx("span",{className:"detail",children:r("关闭则不参与转发(余额查询照常,见「查询设置」)")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"account-name-input",children:r("备注名")}),s.jsx(Fe,{id:"account-name-input",maxLength:100,placeholder:r("账号显示名称"),className:"max-w-[280px]",value:d,onChange:Ae=>f(Ae.currentTarget.value)})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("转发顺序")}),s.jsx("span",{className:"detail",children:r("在列表里拖:拖分组带调整整组顺位,拖行首把手调整组内先后(顺序由拖拽表达,不再填数字)")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"account-conc-input",children:r("并发上限")}),s.jsx(Fe,{id:"account-conc-input",type:"number",min:0,max:Ol,step:1,className:"max-w-[110px]",value:re,onChange:Ae=>M(Ae.currentTarget.value)}),s.jsx("span",{className:"detail",children:Te>0?r("0 = 按本家默认 {default}",{default:Te}):r("0 = 不限")})]}),s.jsx("p",{className:"detail acct-dlg-hint",children:Te>0?r("并发上限 受上游硬顶约束,达到上限的账号跳过、请求转给其他账号(原列表 ⋯ 菜单的「并发上限」入口已并入这里)"):r("并发上限 0~{max};达到上限的账号跳过、请求转给其他账号(原列表 ⋯ 菜单的「并发上限」入口已并入这里)",{max:Ol})})]}):null,J==="credential"&&_e?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("凭证与套餐")}),s.jsx("p",{children:r("这一段按提供商出现:有什么配什么。")})]}),ae?s.jsx(k8,{configured:a.hasBalanceToken===!0,value:b,onChange:y,clearBusy:w,onClear:()=>{he()}}):null,ce?s.jsx(C8,{hasApiKey:U.hasApiKey===!0,noAuth:L,value:H,onValue:B,onToggleNoAuth:F,onClear:()=>{te()},clearBusy:w}):null,Jh(U)?s.jsx(N8,{plan:v,hasJwt:a.canClaim===!0,onChange:j}):null,A?s.jsx(T8,{provider:A,count:Z.length+1,name:R,protocol:E,baseUrl:I,emulation:_,onName:C,onProtocol:D,onBaseUrl:O,onEmulation:z,onRemove:()=>{w||Promise.resolve(Pe().wbCustomProvidersUi?.remove?.(A.id)).then(Ae=>{Ae&&t()})}}):null]}):null,J==="query"&&Ea(U)?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("查询设置")}),s.jsx("p",{children:r("余额列读数的自动刷新;也是「限制器」余额规则的数据来源。")})]}),ue?s.jsx(w8,{spec:ue,values:K,configured:ve,onValue:(Ae,oe)=>q(me=>({...me,[Ae]:oe})),onClear:Ae=>{ke(Ae)},clearBusy:w,idPrefix:"account-balance-query"}):null,ee?s.jsx("p",{className:"detail mt-2.5 text-subtle",children:r("查询凭证还没配齐:填好后余额列才有读数,在此之前会显示「未配置」。")}):null,s.jsx(h8,{account:U,draft:$,onChange:X})]}):null,J==="limiter"&&Ea(U)?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("限制器")}),s.jsx("p",{children:r("按规则限制该账号参与转发:没有规则(或全部停用)= 不限制;跳过档自动恢复,禁用档需手动启用。")})]}),s.jsx(i8,{account:U,draft:Q,onChange:G})]}):null,J==="network"?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("网络")}),s.jsx("p",{children:r("这条账号访问上游走哪条线路。")})]}),s.jsx(LR,{draft:p,onChange:h,idPrefix:"account-proxy",allowRotate:W}),a.proxy?.error?s.jsx("p",{className:"detail text-destructive",children:r("当前代理不可用:{error}(转发时会回退直连)",{error:a.proxy.error})}):null]}):null]})]})}),s.jsxs(tn,{children:[s.jsx("div",{className:"detail mr-auto",style:{minHeight:18},children:N}),s.jsx(ne,{variant:"outline",disabled:w,onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:w,onClick:()=>{Se()},children:r(w?"保存中…":"保存")})]})]})})}const A8=[{value:"enable",label:r("启用")},{value:"disable",label:r("禁用")},{value:"proxy",label:r("修改代理")},{value:"concurrency",label:r("设置并发上限")},{value:"remove",label:r("删除")}];function R8({ids:e,action:t,onClose:a}){const[o,c]=x.useState(t),[d,f]=x.useState(()=>PR(null)),[p,h]=x.useState(""),[b,y]=x.useState(!1),[v,j]=x.useState(""),w=e.map(R=>Aa(R)).filter(R=>R!==null),S=w.reduce((R,C)=>Math.max(R,Number(cr(An(C)).concurrencyDefault)||0),0),N=w.length>0&&w.every(R=>s$(R));function k(R){return Promise.resolve(Pe().wbConfirm?.ask?.({title:r("删除选中的账号"),html:r("确定删除选中的 {count} 个账号?此操作不可恢复,账号的登录态会一并移除。",{count:R}),okText:r("删除"),okClass:"danger"})??!1)}async function A(){if(b)return;if(!e.length){Le(r("没有选中的账号"),"err");return}let R;if(o==="proxy")try{R=Tj(d)}catch(E){Le(mt(E),"err");return}let C;if(o==="concurrency"){const E=Number(p.trim());if(!p.trim()||!Number.isFinite(E)||E<0){Le(r("并发上限必须是 0~{max} 的整数",{max:Ol}),"err");return}C=Math.min(Ol,Math.round(E))}if(!(o==="remove"&&!await k(e.length))){if(o==="disable"||o==="remove"){const E=new Set(e);if(!Al().filter(I=>I.enabled!==!1&&!E.has(I.id)).length){const I=r(o==="remove"?"删除":"禁用");if(!await Promise.resolve(Pe().wbConfirm?.ask?.({title:r("全部启用中的账号将被{what}",{what:I}),html:r("这会{what}所有启用中的账号,转发将不可用。确定继续?",{what:I}),okText:I,okClass:o==="remove"?"danger":"primary"})??!1))return}}y(!0),j("");try{const E={action:o,ids:e};o==="proxy"&&(E.proxy=R),o==="concurrency"&&(E.maxConcurrent=C);const D=await Pe().workbuddyDesktop?.batchAccounts?.(E),I=(D?.ok||[]).filter(B=>B.changes?.length).length,O=(D?.removed||[]).length,_=D?.failed||[],z=o==="remove"?O:I,H={enable:r("启用"),disable:r("禁用"),proxy:r("修改代理"),concurrency:r("设置并发上限"),remove:r("删除")}[o]||o;if(_.length){const B=_.slice(0,3).map(L=>ug(Aa(String(L.id)))||L.id).join(r("、"));Le(r("{verb}完成:成功 {ok} 个,失败 {fail} 个({detail}{more})",{verb:H,ok:z,fail:_.length,detail:B,more:_.length>3?r(" 等"):""}),"err"),j(s.jsxs("span",{className:"text-destructive",children:[r("失败 {count} 个:",{count:_.length}),_.map(L=>`${ug(Aa(String(L.id)))||L.id}(${L.error})`).join(r(";"))]}))}else Le(r("✅ {verb}完成:共 {count} 个账号",{verb:H,count:z})),a();await Pe().wbApp?.refresh?.()}catch(E){j(s.jsx("span",{className:"text-destructive",children:mt(E)})),Le(r("批量操作失败:{error}",{error:mt(E)}),"err")}finally{y(!1)}}}const P={enable:r("启用"),disable:r("禁用"),proxy:r("修改代理"),concurrency:r("设置并发上限"),remove:r("删除")}[o]||o;return s.jsx(Yt,{open:!0,onOpenChange:R=>{R||b||a()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("批量操作 · 已选 {count} 个账号",{count:e.length})})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("将作用于以下账号")}),s.jsx("p",{style:{maxHeight:84,overflowY:"auto"},children:w.map(R=>ug(R)).join(r("、"))})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("操作")}),s.jsx(Ph,{value:o,onValueChange:c,className:"flex-row flex-wrap items-center gap-5","aria-label":r("批量动作"),children:A8.map(R=>s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(yo,{value:R.value}),R.label]},R.value))}),o==="proxy"?s.jsx("div",{className:"mt-2.5",children:s.jsx(LR,{draft:d,onChange:f,idPrefix:"batch-proxy",allowRotate:N})}):null,o==="concurrency"?s.jsxs("div",{className:"mt-2.5",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"batch-conc-input",children:r("并发上限")}),s.jsx(Fe,{id:"batch-conc-input",type:"number",min:0,max:Ol,step:1,className:"max-w-[110px]",placeholder:r("不限"),value:p,onChange:R=>h(R.currentTarget.value)}),s.jsx("span",{className:"detail",children:r("0 = 不限")})]}),s.jsx("p",{className:"detail acct-dlg-hint",children:S>0?r("并发上限 0~{max};有上游硬顶的家(如 CodeArts)以它的硬顶为准;达到上限的账号会被跳过、请求转给其他账号",{max:Ol}):r("并发上限 0~{max};达到上限的账号会被跳过、请求转给其他账号",{max:Ol})})]}):null]}),s.jsx("div",{className:"detail",style:{minHeight:18},children:v})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:b,onClick:a,children:r("取消")}),s.jsx(ne,{variant:o==="remove"?"destructive":"default",disabled:b,onClick:()=>{A()},children:b?r("执行中…"):r("执行({action})",{action:P})})]})]})})}function O8(){const e=Gs();return e.dialog?e.dialog.kind==="settings"?s.jsx(E8,{id:e.dialog.id,onClose:og},e.dialog.id):s.jsx(R8,{ids:e.dialog.ids,action:e.dialog.action,onClose:og},e.dialog.ids.join(",")):null}var Ej={exports:{}},Df={},Aj={exports:{}},Rj={};var zR;function M8(){return zR||(zR=1,(function(e){function t(X,K){var q=X.length;X.push(K);e:for(;0>>1,G=X[Q];if(0>>1;Qc(re,q))Mc(U,re)?(X[Q]=U,X[M]=q,Q=M):(X[Q]=re,X[Y]=q,Q=Y);else if(Mc(U,q))X[Q]=U,X[M]=q,Q=M;else break e}}return K}function c(X,K){var q=X.sortIndex-K.sortIndex;return q!==0?q:X.id-K.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var d=performance;e.unstable_now=function(){return d.now()}}else{var f=Date,p=f.now();e.unstable_now=function(){return f.now()-p}}var h=[],b=[],y=1,v=null,j=3,w=!1,S=!1,N=!1,k=!1,A=typeof setTimeout=="function"?setTimeout:null,P=typeof clearTimeout=="function"?clearTimeout:null,R=typeof setImmediate<"u"?setImmediate:null;function C(X){for(var K=a(b);K!==null;){if(K.callback===null)o(b);else if(K.startTime<=X)o(b),K.sortIndex=K.expirationTime,t(h,K);else break;K=a(b)}}function E(X){if(N=!1,C(X),!S)if(a(h)!==null)S=!0,D||(D=!0,B());else{var K=a(b);K!==null&&$(E,K.startTime-X)}}var D=!1,I=-1,O=5,_=-1;function z(){return k?!0:!(e.unstable_now()-_X&&z());){var Q=v.callback;if(typeof Q=="function"){v.callback=null,j=v.priorityLevel;var G=Q(v.expirationTime<=X);if(X=e.unstable_now(),typeof G=="function"){v.callback=G,C(X),K=!0;break t}v===a(h)&&o(h),C(X)}else o(h);v=a(h)}if(v!==null)K=!0;else{var J=a(b);J!==null&&$(E,J.startTime-X),K=!1}}break e}finally{v=null,j=q,w=!1}K=void 0}}finally{K?B():D=!1}}}var B;if(typeof R=="function")B=function(){R(H)};else if(typeof MessageChannel<"u"){var L=new MessageChannel,F=L.port2;L.port1.onmessage=H,B=function(){F.postMessage(null)}}else B=function(){A(H,0)};function $(X,K){I=A(function(){X(e.unstable_now())},K)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(X){X.callback=null},e.unstable_forceFrameRate=function(X){0>X||125Q?(X.sortIndex=q,t(b,X),a(h)===null&&X===a(b)&&(N?(P(I),I=-1):N=!0,$(E,q-Q))):(X.sortIndex=G,t(h,X),S||w||(S=!0,D||(D=!0,B()))),X},e.unstable_shouldYield=z,e.unstable_wrapCallback=function(X){var K=j;return function(){var q=j;j=K;try{return X.apply(this,arguments)}finally{j=q}}}})(Rj)),Rj}var BR;function D8(){return BR||(BR=1,Aj.exports=M8()),Aj.exports}var HR;function I8(){if(HR)return Df;HR=1;var e=D8(),t=Xd(),a=M1();function o(n){var l="https://react.dev/errors/"+n;if(1ke||(n.current=te[ke],te[ke]=null,ke--)}function Se(n,l){ke++,te[ke]=n.current,n.current=l}var Te=le(null),_e=le(null),Ae=le(null),oe=le(null);function me(n,l){switch(Se(Ae,l),Se(_e,n),Se(Te,null),l.nodeType){case 9:case 11:n=(n=l.documentElement)&&(n=n.namespaceURI)?l5(n):0;break;default:if(n=l.tagName,l=l.namespaceURI)l=l5(l),n=o5(l,n);else switch(n){case"svg":n=1;break;case"math":n=2;break;default:n=0}}de(Te),Se(Te,n)}function pe(){de(Te),de(_e),de(Ae)}function Ce(n){var l=n.memoizedState;l!==null&&(qd._currentValue=l.memoizedState,Se(oe,n)),l=Te.current;var i=o5(l,n.type);l!==i&&(Se(_e,n),Se(Te,i))}function Ne(n){_e.current===n&&(de(Te),de(_e)),oe.current===n&&(de(oe),qd._currentValue=he)}var be,De;function Ge(n){if(be===void 0)try{throw Error()}catch(i){var l=i.stack.trim().match(/\n( *(at )?)/);be=l&&l[1]||"",De=-1xl in Si?ure(Si,xl,{enumerable:!0,configurable:!0,writable:!0,value:ro}):Si[xl]=ro;var cn=(Si,xl,ro)=>dre(Si,typeof xl!="symbol"?xl+"":xl,ro);(function(){"use strict";function Si(e,t){for(var a=0;ao[c]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}function xl(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var ro={exports:{}},Yd={};var gC;function J5(){if(gC)return Yd;gC=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function a(o,c,d){var f=null;if(d!==void 0&&(f=""+d),c.key!==void 0&&(f=""+c.key),"key"in c){d={};for(var p in c)p!=="key"&&(d[p]=c[p])}else d=c;return c=d.ref,{$$typeof:e,type:o,key:f,ref:c!==void 0?c:null,props:d}}return Yd.Fragment=t,Yd.jsx=a,Yd.jsxs=a,Yd}var xC;function ez(){return xC||(xC=1,ro.exports=J5()),ro.exports}var s=ez(),Cv={exports:{}},ct={};var bC;function tz(){if(bC)return ct;bC=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),c=Symbol.for("react.profiler"),d=Symbol.for("react.consumer"),f=Symbol.for("react.context"),p=Symbol.for("react.forward_ref"),h=Symbol.for("react.suspense"),b=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),v=Symbol.for("react.activity"),j=Symbol.for("react.view_transition"),w=Symbol.iterator;function k(M){return M===null||typeof M!="object"?null:(M=w&&M[w]||M["@@iterator"],typeof M=="function"?M:null)}var S={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},N=Object.assign,R={};function P(M,U,Z){this.props=M,this.context=U,this.refs=R,this.updater=Z||S}P.prototype.isReactComponent={},P.prototype.setState=function(M,U){if(typeof M!="object"&&typeof M!="function"&&M!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,M,U,"setState")},P.prototype.forceUpdate=function(M){this.updater.enqueueForceUpdate(this,M,"forceUpdate")};function T(){}T.prototype=P.prototype;function C(M,U,Z){this.props=M,this.context=U,this.refs=R,this.updater=Z||S}var E=C.prototype=new T;E.constructor=C,N(E,P.prototype),E.isPureReactComponent=!0;var D=Array.isArray;function I(){}var O={H:null,A:null,T:null,S:null},_=Object.prototype.hasOwnProperty;function z(M,U,Z){var ae=Z.ref;return{$$typeof:e,type:M,key:U,ref:ae!==void 0?ae:null,props:Z}}function H(M,U){return z(M.type,U,M.props)}function B(M){return typeof M=="object"&&M!==null&&M.$$typeof===e}function L(M){var U={"=":"=0",":":"=2"};return"$"+M.replace(/[=:]/g,function(Z){return U[Z]})}var F=/\/+/g;function $(M,U){return typeof M=="object"&&M!==null&&M.key!=null?L(""+M.key):U.toString(36)}function X(M){switch(M.status){case"fulfilled":return M.value;case"rejected":throw M.reason;default:switch(typeof M.status=="string"?M.then(I,I):(M.status="pending",M.then(function(U){M.status==="pending"&&(M.status="fulfilled",M.value=U)},function(U){M.status==="pending"&&(M.status="rejected",M.reason=U)})),M.status){case"fulfilled":return M.value;case"rejected":throw M.reason}}throw M}function K(M,U,Z,ae,ce){var W=typeof M;(W==="undefined"||W==="boolean")&&(M=null);var ue=!1;if(M===null)ue=!0;else switch(W){case"bigint":case"string":case"number":ue=!0;break;case"object":switch(M.$$typeof){case e:case t:ue=!0;break;case y:return ue=M._init,K(ue(M._payload),U,Z,ae,ce)}}if(ue)return ce=ce(M),ue=ae===""?"."+$(M,0):ae,D(ce)?(Z="",ue!=null&&(Z=ue.replace(F,"$&/")+"/"),K(ce,U,Z,"",function(he){return he})):ce!=null&&(B(ce)&&(ce=H(ce,Z+(ce.key==null||M&&M.key===ce.key?"":(""+ce.key).replace(F,"$&/")+"/")+ue)),U.push(ce)),1;ue=0;var ve=ae===""?".":ae+":";if(D(M))for(var ee=0;ee"u"?!1:e instanceof ShadowRoot||e instanceof Cn(e).ShadowRoot}function Qd(e){const{overflow:t,overflowX:a,overflowY:o,display:c}=jr(e);return/auto|scroll|overlay|hidden|clip/.test(t+o+a)&&c!=="inline"&&c!=="contents"}function sz(e){return/^(table|td|th)$/.test(Fs(e))}function Um(e){try{if(e.matches(":popover-open"))return!0}catch{}try{return e.matches(":modal")}catch{return!1}}const rz=/transform|translate|scale|rotate|perspective|filter/,az=/paint|layout|strict|content/,Ni=e=>!!e&&e!=="none";let Ev;function Av(e){const t=Rt(e)?jr(e):e;return Ni(t.transform)||Ni(t.translate)||Ni(t.scale)||Ni(t.rotate)||Ni(t.perspective)||!Rv()&&(Ni(t.backdropFilter)||Ni(t.filter))||rz.test(t.willChange||"")||az.test(t.contain||"")}function lz(e){let t=lo(e);for(;pn(t)&&!ao(t);){if(Av(t))return t;if(Um(t))return null;t=lo(t)}return null}function Rv(){return Ev==null&&(Ev=typeof CSS<"u"&&CSS.supports&&CSS.supports("-webkit-backdrop-filter","none")),Ev}function ao(e){return/^(html|body|#document)$/.test(Fs(e))}function jr(e){return Cn(e).getComputedStyle(e)}function Vm(e){return Rt(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function lo(e){if(Fs(e)==="html")return e;const t=e.assignedSlot||e.parentNode||Kc(e)&&e.host||bl(e);return Kc(t)?t.host:t}function yC(e){const t=lo(e);return ao(t)?(e.ownerDocument||e).body:pn(t)&&Qd(t)?t:yC(t)}function Yc(e,t,a){var o;t===void 0&&(t=[]),a===void 0&&(a=!0);const c=yC(e),d=c===((o=e.ownerDocument)==null?void 0:o.body),f=Cn(c);if(d){const p=Ov(f);return t.concat(f,f.visualViewport||[],Qd(c)?c:[],p&&a?Yc(p):[])}else return t.concat(c,Yc(c,[],a))}function Ov(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}const Mv={...nz},jC={};function Ps(e,t){const a=x.useRef(jC);return a.current===jC&&(a.current=e(t)),a}const Dv=Mv.useInsertionEffect,oz=Dv&&Dv!==Mv.useLayoutEffect?Dv:e=>e();function Ie(e){const t=Ps(iz).current;return t.next=e,oz(t.effect),t.trampoline}function iz(){const e={next:void 0,callback:cz,trampoline:(...t)=>e.callback?.(...t),effect:()=>{e.callback=e.next}};return e}function cz(){}const Me=typeof document<"u"?x.useLayoutEffect:()=>{};function Iv(e,t){if(e&&!t)return e;if(!e&&t)return t;if(e||t)return{...e,...t}}const Pv={};function ta(e,t,a,o,c){if(!a&&!o&&!c&&!e)return Fm(t);let d=Fm(e);return t&&(d=Zd(d,t)),a&&(d=Zd(d,a)),o&&(d=Zd(d,o)),c&&(d=Zd(d,c)),d}function uz(e){if(e.length===0)return Pv;if(e.length===1)return Fm(e[0]);let t=Fm(e[0]);for(let a=1;a=65&&c<=90&&(typeof t=="function"||typeof t>"u")}function _v(e){return typeof e=="function"}function SC(e,t){return _v(e)?e(t):e??Pv}function pz(e,t){return t?e?(...a)=>{const o=a[0];if(CC(o)){const d=o;$m(d);const f=t(...a);return d.baseUIHandlerPrevented||e?.(...a),f}const c=t(...a);return e?.(...a),c}:NC(t):e}function NC(e){return e&&((...t)=>{const a=t[0];return CC(a)&&$m(a),e(...t)})}function $m(e){return e.preventBaseUIHandler=()=>{e.baseUIHandlerPrevented=!0},e}function kC(e,t){return t?e?t+" "+e:t:e}function CC(e){return e!=null&&typeof e=="object"&&"nativeEvent"in e}function mz(e,t){return function(o,...c){const d=new URL(e);return d.searchParams.set("code",o.toString()),c.forEach(f=>d.searchParams.append("args[]",f)),`${t} error #${o}; visit ${d} for the full message.`}}const un=mz("https://base-ui.com/production-error","Base UI"),TC=x.createContext(void 0);function EC(e=!1){const t=x.useContext(TC);if(t===void 0&&!e)throw new Error(un(16));return t}function hz(e){const{focusableWhenDisabled:t,disabled:a,composite:o=!1,tabIndex:c=0,isNativeButton:d}=e,f=o&&t!==!1,p=o&&t===!1;return{props:x.useMemo(()=>{const b={onKeyDown(y){a&&t&&y.key!=="Tab"&&y.preventDefault()}};return o||(b.tabIndex=c,!d&&a&&(b.tabIndex=t?c:-1)),(d&&(t||f)||!d&&a)&&(b["aria-disabled"]=a),d&&(!t||p)&&(b.disabled=a),b},[o,a,t,f,p,d,c])}}function Gt(e){return e?.ownerDocument||document}function Xc(e,t,{detail:a=0}={}){e.dispatchEvent(new(Cn(e)).PointerEvent("click",{bubbles:!0,cancelable:!0,composed:!0,detail:a,shiftKey:t.shiftKey,ctrlKey:t.ctrlKey,altKey:t.altKey,metaKey:t.metaKey}))}function na(e={}){const{disabled:t=!1,focusableWhenDisabled:a,tabIndex:o=0,native:c=!0,composite:d}=e,f=x.useRef(null),p=EC(!0),h=d??p!==void 0,{props:b}=hz({focusableWhenDisabled:a,disabled:t,composite:h,tabIndex:o,isNativeButton:c}),y=x.useCallback(()=>{const w=f.current;Lv(w)&&h&&t&&b.disabled===void 0&&w.disabled&&(w.disabled=!1)},[t,b.disabled,h]);Me(y,[y]);const v=x.useCallback((w={})=>{const{onClick:k,onMouseDown:S,onKeyUp:N,onKeyDown:R,onPointerDown:P,...T}=w;return ta({onClick(C){if(t){C.preventDefault();return}k?.(C)},onMouseDown(C){t||S?.(C)},onKeyDown(C){if(t||($m(C),R?.(C),C.baseUIHandlerPrevented))return;const E=C.target===C.currentTarget,D=C.currentTarget,I=Lv(D),O=!c&&gz(D),_=E&&(c?I:!O),z=C.key==="Enter",H=C.key===" ",B=D.getAttribute("role"),L=B?.startsWith("menuitem")||B==="option"||B==="gridcell";if(E&&h&&H){if(C.defaultPrevented&&L)return;C.preventDefault(),(!c||I)&&(C.preventBaseUIHandler(),Xc(D,C));return}if(!_||c||!H&&!z){E&&O&&H&&C.preventDefault();return}C.defaultPrevented||(C.preventDefault(),z&&(C.preventBaseUIHandler(),Xc(D,C)))},onKeyUp(C){if(!t){if($m(C),N?.(C),C.target===C.currentTarget&&c&&h&&Lv(C.currentTarget)&&C.key===" "){C.preventDefault();return}C.baseUIHandlerPrevented||C.target===C.currentTarget&&!c&&!h&&!C.defaultPrevented&&C.key===" "&&(C.preventBaseUIHandler(),Xc(C.currentTarget,C))}},onPointerDown(C){if(t){C.preventDefault();return}P?.(C)}},c?{type:"button"}:{role:"button"},b,T)},[t,b,h,c]),j=Ie(w=>{f.current=w,y()});return{getButtonProps:v,buttonRef:j}}function Lv(e){return pn(e)&&e.tagName==="BUTTON"}function gz(e){return pn(e)&&e.tagName==="A"&&!!e.href}function sa(e,t,a,o){const c=Ps(AC).current;return bz(c,e,t,a,o)&&RC(c,[e,t,a,o]),c.callback}function xz(e){const t=Ps(AC).current;return vz(t,e)&&RC(t,e),t.callback}function AC(){return{callback:null,cleanup:null,refs:[]}}function bz(e,t,a,o,c){return e.refs[0]!==t||e.refs[1]!==a||e.refs[2]!==o||e.refs[3]!==c}function vz(e,t){return e.refs.length!==t.length||e.refs.some((a,o)=>a!==t[o])}function RC(e,t){if(e.refs=t,t.every(a=>a==null)){e.callback=null;return}e.callback=a=>{if(e.cleanup&&(e.cleanup(),e.cleanup=null),a!=null){const o=Array(t.length).fill(null);for(let c=0;c{for(let c=0;c=e}function OC(e){if(!x.isValidElement(e))return null;const t=e,a=t.props;return(zv(19)?a?.ref:t.ref)??null}function Kt(){}const Pr=Object.freeze([]),mn=Object.freeze({});function jz(e,t){const a={};for(const o in e){const c=e[o];if(t?.hasOwnProperty(o)){const d=t[o](c);d!=null&&Object.assign(a,d);continue}c===!0?a[`data-${o.toLowerCase()}`]="":c&&(a[`data-${o.toLowerCase()}`]=c.toString())}return a}function wz(e,t){return typeof e=="function"?e(t):e}function Sz(e,t){return typeof e=="function"?e(t):e}function yt(e,t,a={}){let o=t.render;a.enabled!==!1&&(o=Tz(o));const c=Nz(t,a,o);if(a.enabled===!1)return null;const d=a.state??mn;return Ez(e,o,c,d)}function Nz(e,t,a){const{className:o,style:c}=e,{state:d=mn,ref:f,props:p,stateAttributesMapping:h,enabled:b=!0}=t,y=b?wz(o,d):void 0,v=b?Sz(c,d):void 0,j=b?jz(d,h):mn,w=b&&p?kz(p):void 0,k=b?Iv(j,w)??{}:mn;return typeof document<"u"&&(b?Array.isArray(f)?k.ref=xz([k.ref,OC(a),...f]):k.ref=sa(k.ref,OC(a),f):sa(null,null)),b?(y!==void 0&&(k.className=kC(k.className,y)),v!==void 0&&(k.style=Iv(k.style,v)),k):mn}function kz(e){return Array.isArray(e)?uz(e):ta(void 0,e)}const Cz=Symbol.for("react.lazy");function Tz(e){if(e?.$$typeof!==Cz)return e;const t=x.Children.toArray(e)[0];return x.isValidElement(t)?t:e}function Ez(e,t,a,o){if(t){if(typeof t=="function")return t(a,o);const c=ta(a,t.props);return c.ref=a.ref,x.cloneElement(t,c)}if(e&&typeof e=="string")return Az(e,a);throw new Error(un(8))}function Az(e,t){return e==="button"?x.createElement("button",{type:"button",...t,key:t.key}):e==="img"?x.createElement("img",{alt:"",...t,key:t.key}):x.createElement(e,t)}const Rz=x.forwardRef(function(t,a){const{render:o,className:c,disabled:d=!1,focusableWhenDisabled:f=!1,nativeButton:p=!0,style:h,...b}=t,{getButtonProps:y,buttonRef:v}=na({disabled:d,focusableWhenDisabled:f,native:p});return yt("button",t,{state:{disabled:d},ref:[a,v],props:[b,y]})});function MC(e){var t,a,o="";if(typeof e=="string"||typeof e=="number")o+=e;else if(typeof e=="object")if(Array.isArray(e)){var c=e.length;for(t=0;ttypeof e=="boolean"?`${e}`:e===0?"0":e,PC=DC,Qc=(e,t)=>a=>{var o;if(t?.variants==null)return PC(e,a?.class,a?.className);const{variants:c,defaultVariants:d}=t,f=Object.keys(c).map(b=>{const y=a?.[b],v=d?.[b];if(y===null)return null;const j=IC(y)||IC(v);return c[b][j]}),p=a&&Object.entries(a).reduce((b,y)=>{let[v,j]=y;return j===void 0||(b[v]=j),b},{}),h=t==null||(o=t.compoundVariants)===null||o===void 0?void 0:o.reduce((b,y)=>{let{class:v,className:j,...w}=y;return Object.entries(w).every(k=>{let[S,N]=k;return Array.isArray(N)?N.includes({...d,...p}[S]):{...d,...p}[S]===N})?[...b,v,j]:b},[]);return PC(e,f,h,a?.class,a?.className)},Oz=(e,t)=>{const a=new Array(e.length+t.length);for(let o=0;o({classGroupId:e,validator:t}),_C=(e=new Map,t=null,a)=>({nextPart:e,validators:t,classGroupId:a}),qm="-",LC=[],Dz="arbitrary..",Iz=e=>{const t=_z(e),{conflictingClassGroups:a,conflictingClassGroupModifiers:o}=e;return{getClassGroupId:f=>{if(f.startsWith("[")&&f.endsWith("]"))return Pz(f);const p=f.split(qm),h=p[0]===""&&p.length>1?1:0;return zC(p,h,t)},getConflictingClassGroupIds:(f,p)=>{if(p){const h=o[f],b=a[f];return h?b?Oz(b,h):h:b||LC}return a[f]||LC}}},zC=(e,t,a)=>{if(e.length-t===0)return a.classGroupId;const c=e[t],d=a.nextPart.get(c);if(d){const b=zC(e,t+1,d);if(b)return b}const f=a.validators;if(f===null)return;const p=t===0?e.join(qm):e.slice(t).join(qm),h=f.length;for(let b=0;be.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const t=e.slice(1,-1),a=t.indexOf(":"),o=t.slice(0,a);return o?Dz+o:void 0})(),_z=e=>{const{theme:t,classGroups:a}=e;return Lz(a,t)},Lz=(e,t)=>{const a=_C();for(const o in e){const c=e[o];Bv(c,a,o,t)}return a},Bv=(e,t,a,o)=>{const c=e.length;for(let d=0;d{if(typeof e=="string"){Bz(e,t,a);return}if(typeof e=="function"){Hz(e,t,a,o);return}Uz(e,t,a,o)},Bz=(e,t,a)=>{const o=e===""?t:BC(t,e);o.classGroupId=a},Hz=(e,t,a,o)=>{if(Vz(e)){Bv(e(o),t,a,o);return}t.validators===null&&(t.validators=[]),t.validators.push(Mz(a,e))},Uz=(e,t,a,o)=>{const c=Object.entries(e),d=c.length;for(let f=0;f{let a=e;const o=t.split(qm),c=o.length;for(let d=0;d"isThemeGetter"in e&&e.isThemeGetter===!0,Fz=e=>{if(e<1)return{get:()=>{},set:()=>{}};let t=0,a=Object.create(null),o=Object.create(null);const c=(d,f)=>{a[d]=f,t++,t>e&&(t=0,o=a,a=Object.create(null))};return{get(d){let f=a[d];if(f!==void 0)return f;if((f=o[d])!==void 0)return c(d,f),f},set(d,f){d in a?a[d]=f:c(d,f)}}},Hv="!",HC=":",$z=[],UC=(e,t,a,o,c)=>({modifiers:e,hasImportantModifier:t,baseClassName:a,maybePostfixModifierPosition:o,isExternal:c}),qz=e=>{const{prefix:t,experimentalParseClassName:a}=e;let o=c=>{const d=[];let f=0,p=0,h=0,b;const y=c.length;for(let S=0;Sh?b-h:void 0;return UC(d,w,j,k)};if(t){const c=t+HC,d=o;o=f=>f.startsWith(c)?d(f.slice(c.length)):UC($z,!1,f,void 0,!0)}if(a){const c=o;o=d=>a({className:d,parseClassName:c})}return o},Gz=e=>{const t=new Map;return e.orderSensitiveModifiers.forEach((a,o)=>{t.set(a,1e6+o)}),a=>{const o=[];let c=[];for(let d=0;d0&&(c.sort(),o.push(...c),c=[]),o.push(f)):c.push(f)}return c.length>0&&(c.sort(),o.push(...c)),o}},Kz=e=>({cache:Fz(e.cacheSize),parseClassName:qz(e),sortModifiers:Gz(e),postfixLookupClassGroupIds:Yz(e),...Iz(e)}),Yz=e=>{const t=Object.create(null),a=e.postfixLookupClassGroups;if(a)for(let o=0;o{const{parseClassName:a,getClassGroupId:o,getConflictingClassGroupIds:c,sortModifiers:d,postfixLookupClassGroupIds:f}=t,p=[],h=e.trim().split(Xz);let b="";for(let y=h.length-1;y>=0;y-=1){const v=h[y],{isExternal:j,modifiers:w,hasImportantModifier:k,baseClassName:S,maybePostfixModifierPosition:N}=a(v);if(j){b=v+(b.length>0?" "+b:b);continue}let R=!!N,P;if(R){const I=S.substring(0,N);P=o(I);const O=P&&f[P]?o(S):void 0;O&&O!==P&&(P=O,R=!1)}else P=o(S);if(!P){if(!R){b=v+(b.length>0?" "+b:b);continue}if(P=o(S),!P){b=v+(b.length>0?" "+b:b);continue}R=!1}const T=w.length===0?"":w.length===1?w[0]:d(w).join(":"),C=k?T+Hv:T,E=C+P;if(p.indexOf(E)>-1)continue;p.push(E);const D=c(P,R);for(let I=0;I0?" "+b:b)}return b},Zz=(...e)=>{let t=0,a,o,c="";for(;t{if(typeof e=="string")return e;let t,a="";for(let o=0;o{let a,o,c,d;const f=h=>{const b=t.reduce((y,v)=>v(y),e());return a=Kz(b),o=a.cache.get,c=a.cache.set,d=p,p(h)},p=h=>{const b=o(h);if(b)return b;const y=Qz(h,a);return c(h,y),y};return d=f,(...h)=>d(Zz(...h))},Jz=[],ks=e=>{const t=a=>a[e]||Jz;return t.isThemeGetter=!0,t.themeKey=e,t},FC=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,$C=/^\((?:(\w[\w-]*):)?(.+)\)$/i,eB=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,tB=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,nB=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,sB=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix|color|light-dark)\(.+\)$/,rB=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,aB=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,oo=e=>eB.test(e),Nt=e=>!!e&&!Number.isNaN(Number(e)),qa=e=>!!e&&Number.isInteger(Number(e)),Uv=e=>e.endsWith("%")&&Nt(e.slice(0,-1)),vl=e=>tB.test(e),qC=()=>!0,lB=e=>nB.test(e)&&!sB.test(e),Vv=()=>!1,oB=e=>rB.test(e),iB=e=>aB.test(e),cB=e=>!Ye(e)&&!Qe(e),uB=e=>e.startsWith("@container")&&(e[10]==="/"&&e[11]!==void 0||e[11]==="s"&&e[16]!==void 0&&e.startsWith("-size/",10)||e[11]==="n"&&e[18]!==void 0&&e.startsWith("-normal/",10)),dB=e=>io(e,ZC,Vv),Ye=e=>FC.test(e),ki=e=>io(e,WC,lB),GC=e=>io(e,vB,Nt),fB=e=>io(e,e1,qC),pB=e=>io(e,JC,Vv),KC=e=>io(e,XC,Vv),mB=e=>io(e,QC,iB),Gm=e=>io(e,t1,oB),Qe=e=>$C.test(e),Wd=e=>Ci(e,WC),hB=e=>Ci(e,JC),YC=e=>Ci(e,XC),gB=e=>Ci(e,ZC),xB=e=>Ci(e,QC),Km=e=>Ci(e,t1,!0),bB=e=>Ci(e,e1,!0),io=(e,t,a)=>{const o=FC.exec(e);return o?o[1]?t(o[1]):a(o[2]):!1},Ci=(e,t,a=!1)=>{const o=$C.exec(e);return o?o[1]?t(o[1]):a:!1},XC=e=>e==="position"||e==="percentage",QC=e=>e==="image"||e==="url",ZC=e=>e==="length"||e==="size"||e==="bg-size",WC=e=>e==="length",vB=e=>e==="number",JC=e=>e==="family-name",e1=e=>e==="number"||e==="weight",t1=e=>e==="shadow",yB=Wz(()=>{const e=ks("color"),t=ks("font"),a=ks("text"),o=ks("font-weight"),c=ks("tracking"),d=ks("leading"),f=ks("breakpoint"),p=ks("container"),h=ks("spacing"),b=ks("radius"),y=ks("shadow"),v=ks("inset-shadow"),j=ks("text-shadow"),w=ks("drop-shadow"),k=ks("blur"),S=ks("perspective"),N=ks("aspect"),R=ks("ease"),P=ks("animate"),T=()=>["auto","avoid","all","avoid-page","page","left","right","column"],C=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],E=()=>[...C(),Qe,Ye],D=()=>["auto","hidden","clip","visible","scroll"],I=()=>["auto","contain","none"],O=()=>[Qe,Ye,h],_=()=>[oo,"full","auto",...O()],z=()=>[qa,"none","subgrid",Qe,Ye],H=()=>["auto",{span:["full",qa,Qe,Ye]},qa,Qe,Ye],B=()=>[qa,"auto",Qe,Ye],L=()=>["auto","min","max","fr",Qe,Ye],F=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],$=()=>["start","end","center","stretch","center-safe","end-safe"],X=()=>["auto",...O()],K=()=>[oo,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...O()],q=()=>[p,oo,"screen","full","dvw","lvw","svw","min","max","fit",...O()],Q=()=>[oo,"screen","full","lh","dvh","lvh","svh","min","max","fit",...O()],G=()=>[e,Qe,Ye],J=()=>[...C(),YC,KC,{position:[Qe,Ye]}],Y=()=>["no-repeat",{repeat:["","x","y","space","round"]}],re=()=>["auto","cover","contain",gB,dB,{size:[Qe,Ye]}],M=()=>[Uv,Wd,ki],U=()=>["","none","full",b,Qe,Ye],Z=()=>["",Nt,Wd,ki],ae=()=>["solid","dashed","dotted","double"],ce=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],W=()=>[Nt,Uv,YC,KC],ue=()=>["","none",k,Qe,Ye],ve=()=>["none",Nt,Qe,Ye],ee=()=>["none",Nt,Qe,Ye],he=()=>[Nt,Qe,Ye],te=()=>[oo,"full",...O()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[vl],breakpoint:[vl],color:[qC],container:[vl],"drop-shadow":[vl],ease:["in","out","in-out"],font:[cB],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[vl],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[vl],shadow:[vl],spacing:["px",Nt],text:[vl],"text-shadow":[vl],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",oo,Ye,Qe,N]}],container:["container"],"container-type":[{"@container":["","normal","size",Qe,Ye]}],"container-named":[uB],columns:[{columns:[Nt,"auto",Ye,Qe,p]}],"break-after":[{"break-after":T()}],"break-before":[{"break-before":T()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:E()}],overflow:[{overflow:D()}],"overflow-x":[{"overflow-x":D()}],"overflow-y":[{"overflow-y":D()}],overscroll:[{overscroll:I()}],"overscroll-x":[{"overscroll-x":I()}],"overscroll-y":[{"overscroll-y":I()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:_()}],"inset-x":[{"inset-x":_()}],"inset-y":[{"inset-y":_()}],start:[{"inset-s":_(),start:_()}],end:[{"inset-e":_(),end:_()}],"inset-bs":[{"inset-bs":_()}],"inset-be":[{"inset-be":_()}],top:[{top:_()}],right:[{right:_()}],bottom:[{bottom:_()}],left:[{left:_()}],visibility:["visible","invisible","collapse"],z:[{z:[qa,"auto",Qe,Ye]}],basis:[{basis:[oo,"full","auto",p,...O()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[Nt,oo,"auto","initial","none",Ye]}],grow:[{grow:["",Nt,Qe,Ye]}],shrink:[{shrink:["",Nt,Qe,Ye]}],order:[{order:[qa,"first","last","none",Qe,Ye]}],"grid-cols":[{"grid-cols":z()}],"col-start-end":[{col:H()}],"col-start":[{"col-start":B()}],"col-end":[{"col-end":B()}],"grid-rows":[{"grid-rows":z()}],"row-start-end":[{row:H()}],"row-start":[{"row-start":B()}],"row-end":[{"row-end":B()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":L()}],"auto-rows":[{"auto-rows":L()}],gap:[{gap:O()}],"gap-x":[{"gap-x":O()}],"gap-y":[{"gap-y":O()}],"justify-content":[{justify:[...F(),"normal"]}],"justify-items":[{"justify-items":[...$(),"normal"]}],"justify-self":[{"justify-self":["auto",...$()]}],"align-content":[{content:["normal",...F()]}],"align-items":[{items:[...$(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...$(),{baseline:["","last"]}]}],"place-content":[{"place-content":F()}],"place-items":[{"place-items":[...$(),"baseline"]}],"place-self":[{"place-self":["auto",...$()]}],p:[{p:O()}],px:[{px:O()}],py:[{py:O()}],ps:[{ps:O()}],pe:[{pe:O()}],pbs:[{pbs:O()}],pbe:[{pbe:O()}],pt:[{pt:O()}],pr:[{pr:O()}],pb:[{pb:O()}],pl:[{pl:O()}],m:[{m:X()}],mx:[{mx:X()}],my:[{my:X()}],ms:[{ms:X()}],me:[{me:X()}],mbs:[{mbs:X()}],mbe:[{mbe:X()}],mt:[{mt:X()}],mr:[{mr:X()}],mb:[{mb:X()}],ml:[{ml:X()}],"space-x":[{"space-x":O()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":O()}],"space-y-reverse":["space-y-reverse"],size:[{size:K()}],"inline-size":[{inline:["auto",...q()]}],"min-inline-size":[{"min-inline":["auto",...q()]}],"max-inline-size":[{"max-inline":["none",...q()]}],"block-size":[{block:["auto",...Q()]}],"min-block-size":[{"min-block":["auto",...Q()]}],"max-block-size":[{"max-block":["none",...Q()]}],w:[{w:[p,"screen",...K()]}],"min-w":[{"min-w":[p,"screen","none",...K()]}],"max-w":[{"max-w":[p,"screen","none","prose",{screen:[f]},...K()]}],h:[{h:["screen","lh",...K()]}],"min-h":[{"min-h":["screen","lh","none",...K()]}],"max-h":[{"max-h":["screen","lh","none",...K()]}],"font-size":[{text:["base",a,Wd,ki]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[o,bB,fB]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",Uv,Ye]}],"font-family":[{font:[hB,pB,t]}],"font-features":[{"font-features":[Ye]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[c,Qe,Ye]}],"line-clamp":[{"line-clamp":[Nt,"none",Qe,GC]}],leading:[{leading:["none",d,...O()]}],"list-image":[{"list-image":["none",Qe,Ye]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",Qe,Ye]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:G()}],"text-color":[{text:G()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...ae(),"wavy"]}],"text-decoration-thickness":[{decoration:[Nt,"from-font","auto",Qe,ki]}],"text-decoration-color":[{decoration:G()}],"underline-offset":[{"underline-offset":[Nt,"auto",Qe,Ye]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:O()}],"tab-size":[{tab:[qa,Qe,Ye]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",Qe,Ye]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",Qe,Ye]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:J()}],"bg-repeat":[{bg:Y()}],"bg-size":[{bg:re()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},qa,Qe,Ye],radial:["",Qe,Ye],conic:["",qa,Qe,Ye]},xB,mB]}],"bg-color":[{bg:G()}],"gradient-from-pos":[{from:M()}],"gradient-via-pos":[{via:M()}],"gradient-to-pos":[{to:M()}],"gradient-from":[{from:G()}],"gradient-via":[{via:G()}],"gradient-to":[{to:G()}],rounded:[{rounded:U()}],"rounded-s":[{"rounded-s":U()}],"rounded-e":[{"rounded-e":U()}],"rounded-t":[{"rounded-t":U()}],"rounded-r":[{"rounded-r":U()}],"rounded-b":[{"rounded-b":U()}],"rounded-l":[{"rounded-l":U()}],"rounded-ss":[{"rounded-ss":U()}],"rounded-se":[{"rounded-se":U()}],"rounded-ee":[{"rounded-ee":U()}],"rounded-es":[{"rounded-es":U()}],"rounded-tl":[{"rounded-tl":U()}],"rounded-tr":[{"rounded-tr":U()}],"rounded-br":[{"rounded-br":U()}],"rounded-bl":[{"rounded-bl":U()}],"border-w":[{border:Z()}],"border-w-x":[{"border-x":Z()}],"border-w-y":[{"border-y":Z()}],"border-w-s":[{"border-s":Z()}],"border-w-e":[{"border-e":Z()}],"border-w-bs":[{"border-bs":Z()}],"border-w-be":[{"border-be":Z()}],"border-w-t":[{"border-t":Z()}],"border-w-r":[{"border-r":Z()}],"border-w-b":[{"border-b":Z()}],"border-w-l":[{"border-l":Z()}],"divide-x":[{"divide-x":Z()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":Z()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...ae(),"hidden","none"]}],"divide-style":[{divide:[...ae(),"hidden","none"]}],"border-color":[{border:G()}],"border-color-x":[{"border-x":G()}],"border-color-y":[{"border-y":G()}],"border-color-s":[{"border-s":G()}],"border-color-e":[{"border-e":G()}],"border-color-bs":[{"border-bs":G()}],"border-color-be":[{"border-be":G()}],"border-color-t":[{"border-t":G()}],"border-color-r":[{"border-r":G()}],"border-color-b":[{"border-b":G()}],"border-color-l":[{"border-l":G()}],"divide-color":[{divide:G()}],"outline-style":[{outline:[...ae(),"none","hidden"]}],"outline-offset":[{"outline-offset":[Nt,Qe,Ye]}],"outline-w":[{outline:["",Nt,Wd,ki]}],"outline-color":[{outline:G()}],shadow:[{shadow:["","inner","none",y,Km,Gm]}],"shadow-color":[{shadow:G()}],"inset-shadow":[{"inset-shadow":["none",v,Km,Gm]}],"inset-shadow-color":[{"inset-shadow":G()}],"ring-w":[{ring:Z()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:G()}],"ring-offset-w":[{"ring-offset":[Nt,ki]}],"ring-offset-color":[{"ring-offset":G()}],"inset-ring-w":[{"inset-ring":Z()}],"inset-ring-color":[{"inset-ring":G()}],"text-shadow":[{"text-shadow":["none",j,Km,Gm]}],"text-shadow-color":[{"text-shadow":G()}],opacity:[{opacity:[Nt,Qe,Ye]}],"mix-blend":[{"mix-blend":[...ce(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":ce()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[Nt]}],"mask-image-linear-from-pos":[{"mask-linear-from":W()}],"mask-image-linear-to-pos":[{"mask-linear-to":W()}],"mask-image-linear-from-color":[{"mask-linear-from":G()}],"mask-image-linear-to-color":[{"mask-linear-to":G()}],"mask-image-t-from-pos":[{"mask-t-from":W()}],"mask-image-t-to-pos":[{"mask-t-to":W()}],"mask-image-t-from-color":[{"mask-t-from":G()}],"mask-image-t-to-color":[{"mask-t-to":G()}],"mask-image-r-from-pos":[{"mask-r-from":W()}],"mask-image-r-to-pos":[{"mask-r-to":W()}],"mask-image-r-from-color":[{"mask-r-from":G()}],"mask-image-r-to-color":[{"mask-r-to":G()}],"mask-image-b-from-pos":[{"mask-b-from":W()}],"mask-image-b-to-pos":[{"mask-b-to":W()}],"mask-image-b-from-color":[{"mask-b-from":G()}],"mask-image-b-to-color":[{"mask-b-to":G()}],"mask-image-l-from-pos":[{"mask-l-from":W()}],"mask-image-l-to-pos":[{"mask-l-to":W()}],"mask-image-l-from-color":[{"mask-l-from":G()}],"mask-image-l-to-color":[{"mask-l-to":G()}],"mask-image-x-from-pos":[{"mask-x-from":W()}],"mask-image-x-to-pos":[{"mask-x-to":W()}],"mask-image-x-from-color":[{"mask-x-from":G()}],"mask-image-x-to-color":[{"mask-x-to":G()}],"mask-image-y-from-pos":[{"mask-y-from":W()}],"mask-image-y-to-pos":[{"mask-y-to":W()}],"mask-image-y-from-color":[{"mask-y-from":G()}],"mask-image-y-to-color":[{"mask-y-to":G()}],"mask-image-radial":[{"mask-radial":[Qe,Ye]}],"mask-image-radial-from-pos":[{"mask-radial-from":W()}],"mask-image-radial-to-pos":[{"mask-radial-to":W()}],"mask-image-radial-from-color":[{"mask-radial-from":G()}],"mask-image-radial-to-color":[{"mask-radial-to":G()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":C()}],"mask-image-conic-pos":[{"mask-conic":[Nt]}],"mask-image-conic-from-pos":[{"mask-conic-from":W()}],"mask-image-conic-to-pos":[{"mask-conic-to":W()}],"mask-image-conic-from-color":[{"mask-conic-from":G()}],"mask-image-conic-to-color":[{"mask-conic-to":G()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:J()}],"mask-repeat":[{mask:Y()}],"mask-size":[{mask:re()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",Qe,Ye]}],filter:[{filter:["","none",Qe,Ye]}],blur:[{blur:ue()}],brightness:[{brightness:[Nt,Qe,Ye]}],contrast:[{contrast:[Nt,Qe,Ye]}],"drop-shadow":[{"drop-shadow":["","none",w,Km,Gm]}],"drop-shadow-color":[{"drop-shadow":G()}],grayscale:[{grayscale:["",Nt,Qe,Ye]}],"hue-rotate":[{"hue-rotate":[Nt,Qe,Ye]}],invert:[{invert:["",Nt,Qe,Ye]}],saturate:[{saturate:[Nt,Qe,Ye]}],sepia:[{sepia:["",Nt,Qe,Ye]}],"backdrop-filter":[{"backdrop-filter":["","none",Qe,Ye]}],"backdrop-blur":[{"backdrop-blur":ue()}],"backdrop-brightness":[{"backdrop-brightness":[Nt,Qe,Ye]}],"backdrop-contrast":[{"backdrop-contrast":[Nt,Qe,Ye]}],"backdrop-grayscale":[{"backdrop-grayscale":["",Nt,Qe,Ye]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[Nt,Qe,Ye]}],"backdrop-invert":[{"backdrop-invert":["",Nt,Qe,Ye]}],"backdrop-opacity":[{"backdrop-opacity":[Nt,Qe,Ye]}],"backdrop-saturate":[{"backdrop-saturate":[Nt,Qe,Ye]}],"backdrop-sepia":[{"backdrop-sepia":["",Nt,Qe,Ye]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":O()}],"border-spacing-x":[{"border-spacing-x":O()}],"border-spacing-y":[{"border-spacing-y":O()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",Qe,Ye]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[Nt,"initial",Qe,Ye]}],ease:[{ease:["linear","initial",R,Qe,Ye]}],delay:[{delay:[Nt,Qe,Ye]}],animate:[{animate:["none",P,Qe,Ye]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[S,Qe,Ye]}],"perspective-origin":[{"perspective-origin":E()}],rotate:[{rotate:ve()}],"rotate-x":[{"rotate-x":ve()}],"rotate-y":[{"rotate-y":ve()}],"rotate-z":[{"rotate-z":ve()}],scale:[{scale:ee()}],"scale-x":[{"scale-x":ee()}],"scale-y":[{"scale-y":ee()}],"scale-z":[{"scale-z":ee()}],"scale-3d":["scale-3d"],skew:[{skew:he()}],"skew-x":[{"skew-x":he()}],"skew-y":[{"skew-y":he()}],transform:[{transform:[Qe,Ye,"","none","gpu","cpu"]}],"transform-origin":[{origin:E()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:te()}],"translate-x":[{"translate-x":te()}],"translate-y":[{"translate-y":te()}],"translate-z":[{"translate-z":te()}],"translate-none":["translate-none"],zoom:[{zoom:[qa,Qe,Ye]}],accent:[{accent:G()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:G()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",Qe,Ye]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scrollbar-thumb-color":[{"scrollbar-thumb":G()}],"scrollbar-track-color":[{"scrollbar-track":G()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":O()}],"scroll-mx":[{"scroll-mx":O()}],"scroll-my":[{"scroll-my":O()}],"scroll-ms":[{"scroll-ms":O()}],"scroll-me":[{"scroll-me":O()}],"scroll-mbs":[{"scroll-mbs":O()}],"scroll-mbe":[{"scroll-mbe":O()}],"scroll-mt":[{"scroll-mt":O()}],"scroll-mr":[{"scroll-mr":O()}],"scroll-mb":[{"scroll-mb":O()}],"scroll-ml":[{"scroll-ml":O()}],"scroll-p":[{"scroll-p":O()}],"scroll-px":[{"scroll-px":O()}],"scroll-py":[{"scroll-py":O()}],"scroll-ps":[{"scroll-ps":O()}],"scroll-pe":[{"scroll-pe":O()}],"scroll-pbs":[{"scroll-pbs":O()}],"scroll-pbe":[{"scroll-pbe":O()}],"scroll-pt":[{"scroll-pt":O()}],"scroll-pr":[{"scroll-pr":O()}],"scroll-pb":[{"scroll-pb":O()}],"scroll-pl":[{"scroll-pl":O()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",Qe,Ye]}],fill:[{fill:["none",...G()]}],"stroke-w":[{stroke:[Nt,Wd,ki,GC]}],stroke:[{stroke:["none",...G()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{"container-named":["container-type"],overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","inset-bs","inset-be","start","end","top","right","bottom","left"],"inset-x":["start","end","right","left"],"inset-y":["inset-bs","inset-be","top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pbs","pbe","pt","pr","pb","pl"],px:["ps","pe","pr","pl"],py:["pbs","pbe","pt","pb"],m:["mx","my","ms","me","mbs","mbe","mt","mr","mb","ml"],mx:["ms","me","mr","ml"],my:["mbs","mbe","mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-bs","border-w-be","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-s","border-w-e","border-w-r","border-w-l"],"border-w-y":["border-w-bs","border-w-be","border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-bs","border-color-be","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-s","border-color-e","border-color-r","border-color-l"],"border-color-y":["border-color-bs","border-color-be","border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mbs","scroll-mbe","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-ms","scroll-me","scroll-mr","scroll-ml"],"scroll-my":["scroll-mbs","scroll-mbe","scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pbs","scroll-pbe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-ps","scroll-pe","scroll-pr","scroll-pl"],"scroll-py":["scroll-pbs","scroll-pbe","scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},postfixLookupClassGroups:["container-type"],orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}});function Ue(...e){return yB(DC(e))}const jB=Qc(["group/button inline-flex shrink-0 items-center justify-center gap-1.5 whitespace-nowrap border","font-medium transition-[background-color,border-color,color,transform,box-shadow] duration-150 ease-out","outline-none select-none active:translate-y-[0.5px]","disabled:pointer-events-none disabled:opacity-45 disabled:shadow-none","[&_svg]:pointer-events-none [&_svg]:shrink-0"],{variants:{variant:{default:"border-primary bg-primary font-semibold text-primary-on shadow-glow hover:border-primary-hover hover:bg-primary-hover",outline:"border-control-border bg-control text-foreground shadow-1 hover:border-control-border-hover hover:bg-control-hover",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"border-transparent bg-transparent text-subtle shadow-none hover:bg-control-hover hover:text-foreground",destructive:"border-destructive-bd bg-destructive-soft text-destructive hover:bg-destructive-hover",dashed:"border-dashed border-border-strong bg-transparent text-muted-foreground shadow-none hover:border-primary hover:text-primary-fg",link:"border-transparent bg-transparent text-primary shadow-none underline-offset-4 hover:underline"},size:{default:"h-[30px] rounded-md px-3 text-[12.5px]","2xs":"h-4 rounded-pill px-1.5 text-[10px]",xs:"h-6 rounded-sm px-2 text-[11.5px]",sm:"h-[26px] rounded-sm px-2.5 text-[12px]",lg:"h-9 rounded-md px-4 text-[13px]",icon:"h-[30px] w-[30px] rounded-md p-0","icon-2xs":"size-4 rounded-pill p-0","icon-xs":"size-6 rounded-sm p-0","icon-sm":"h-[26px] w-[26px] rounded-sm p-0","icon-lg":"size-9 rounded-md p-0"}},defaultVariants:{variant:"default",size:"default"}});function ne({className:e,variant:t,size:a,...o}){return s.jsx(Rz,{className:Ue(jB({variant:t,size:a}),e),...o})}const wB="data-valid",SB="data-invalid",NB={badInput:!1,customError:!1,patternMismatch:!1,rangeOverflow:!1,rangeUnderflow:!1,stepMismatch:!1,tooLong:!1,tooShort:!1,typeMismatch:!1,valid:null,valueMissing:!1},n1={valid:null,touched:!1,dirty:!1,filled:!1,focused:!1},kB={disabled:!1,...n1},Ti={valid(e){return e===null?null:e?{[wB]:""}:{[SB]:""}}},s1={invalid:void 0,name:void 0,validityData:{state:NB,errors:[],error:"",value:"",initialValue:null},setValidityData:Kt,disabled:void 0,setTouched:Kt,setDirty:Kt,setFilled:Kt,setFocused:Kt,validationMode:"onSubmit",shouldValidateOnChange:()=>!1,state:kB,registerFieldControl:Kt,validation:{getValidationProps:(e,t=mn)=>t,inputRef:{current:null},registeredInputs:new Map,registerInput:Kt,getInputControl:()=>null,commit:async()=>{},change:Kt}},r1=x.createContext(s1);function Na(e=!0){const t=x.useContext(r1);if(t.setValidityData===Kt&&!e)throw new Error(un(28));return t}const CB=x.createContext(void 0);function TB(e=!1){const t=x.useContext(CB);if(!t&&!e)throw new Error(un(86));return t}const EB=x.createContext({elementRef:{current:null},formRef:{current:{fields:new Map}},errors:{},clearErrors:Kt,validationMode:"onSubmit",submitCountRef:{current:0}});function Zc(){return x.useContext(EB)}let a1=0;function AB(e,t="mui"){const[a,o]=x.useState(e),c=e||a;return x.useEffect(()=>{a==null&&(a1+=1,o(`${t}-${a1}`))},[a,t]),c}const l1=Mv.useId;function Jd(e,t){if(l1!==void 0){const a=l1();return e??(t?`${t}-${a}`:a)}return AB(e,t)}function ka(e){return Jd(e,"base-ui")}const RB=x.createContext({controlId:void 0,registerControlId:Kt,resetControlId:Kt,labelId:void 0,setLabelId:Kt,messageIds:[],setMessageIds:Kt,getDescriptionProps:e=>e});function yl(){return x.useContext(RB)}function Fv(e,t,a,o=!0,c){const[d,f]=x.useState(),p=ka(c?`${c}-label`:void 0),h=e??t??d;return Me(()=>{const b=e||t||!o?void 0:OB(a.current,p);d!==b&&f(b)}),h}function OB(e,t){const a=MB(e);if(a)return!a.id&&t&&(a.id=t),a.id||void 0}function MB(e){if(!e)return;const t=e.parentElement;if(t&&t.tagName==="LABEL")return t;const a=e.id;if(a){const c=e.nextElementSibling;if(c&&c.htmlFor===a)return c}const o=e.labels;return o&&o[0]}function co(e={}){const{id:t,enabled:a=!0}=e,{controlId:o,registerControlId:c,resetControlId:d}=yl(),f=ka(),p=Ps(()=>Symbol()),h=x.useRef(!1),b=x.useRef(!1),y=Ie(()=>{!h.current||c===Kt||(h.current=!1,c(p.current,void 0))});return Me(()=>{if(!a||c===Kt){y();return}let v;if(t!==void 0)b.current=!0,v=t;else if(b.current)v=f;else{d();return}if(v===void 0){y();return}h.current=!0,c(p.current,v)},[t,a,c,d,f,p,y]),Me(()=>y,[y]),(a?o:void 0)??t??f}function DB(){return typeof navigator>"u"?{userAgent:"",platform:"",maxTouchPoints:0}:{userAgent:navigator.userAgent,platform:navigator.platform??"",maxTouchPoints:navigator.maxTouchPoints??0}}const{userAgent:IB,platform:PB,maxTouchPoints:_B}=DB(),Ym=IB.toLowerCase(),ef=PB.toLowerCase(),tf=/^i(os$|p)/.test(ef)||ef==="macintel"&&_B>1,o1="android",Xm=ef===o1||Ym.includes(o1),i1=!tf&&ef.startsWith("mac");ef.startsWith("win");const LB=i1||tf,jl=typeof CSS<"u"&&!!CSS.supports?.("-webkit-backdrop-filter:none"),c1=!jl&&Ym.includes("firefox");!jl&&Ym.includes("chrom");const zB=LB,$v=/jsdom|happydom/.test(Ym);function ir(e){let t=e.activeElement;for(;t?.shadowRoot?.activeElement!=null;)t=t.shadowRoot.activeElement;return t}function Ze(e,t){if(!e||!t)return!1;const a=t.getRootNode?.();if(e.contains(t))return!0;if(a&&Kc(a)){let o=t;for(;o;){if(e===o)return!0;o=o.parentNode||o.host}}return!1}function fs(e){return"composedPath"in e?e.composedPath()[0]??e.target:e.target}const qv="data-base-ui-focusable",u1="input:not([type='hidden']):not([disabled]),[contenteditable]:not([contenteditable='false']),textarea:not([disabled])",Ei="ArrowLeft",Ai="ArrowRight",Gv="ArrowUp",Qm="ArrowDown",d1="data-starting-style",BB="data-ending-style",HB={[d1]:""},UB={[BB]:""},uo={transitionStatus(e){return e==="starting"?HB:e==="ending"?UB:null}},VB="data-open",FB="data-closed",$B="data-anchor-hidden",f1="data-popup-open",qB="data-pressed",GB={[f1]:""},KB={[f1]:"",[qB]:""},YB={[VB]:""},XB={[FB]:""},QB={[$B]:""},Kv={open(e){return e?GB:null}},Yv={open(e){return e?KB:null}},Wc={open(e){return e?YB:XB},anchorHidden(e){return e?QB:null}},Xv={...Wc,...uo},Qv="data-trigger-disabled";function Zm(e,t){if(!Rt(e))return!1;const a=e;if(t.hasElement(a))return!a.hasAttribute(Qv);for(const[,o]of t.entries())if(Ze(o,a))return!o.hasAttribute(Qv);return!1}function Zv(e,t){if(t==null)return!1;if("composedPath"in e)return e.composedPath().includes(t);const a=e;return a.target!=null&&t.contains(a.target)}function ZB(e){return e.matches("html,body")}function Wm(e){return pn(e)&&e.matches(u1)}function WB(e){return e?.closest(`button,a[href],[role="button"],select,[tabindex]:not([tabindex="-1"]),${u1}`)!=null}function Wv(e){return e?e.getAttribute("role")==="combobox"&&Wm(e):!1}function JB(e){if(!e||$v)return!0;try{return e.matches(":focus-visible")}catch{return!0}}function Jm(e){return e?e.hasAttribute(qv)?e:e.querySelector(`[${qv}]`)||e:null}function fo(e,t,a=!0){return e.filter(c=>c.parentId===t).flatMap(c=>[...!a||c.context?.open?[c]:[],...fo(e,c.id,a)])}function p1(e,t){let a=[],o=e.find(c=>c.id===t)?.parentId;for(;o;){const c=e.find(d=>d.id===o);o=c?.parentId,c&&(a=a.concat(c))}return a}function Cs(e){e.preventDefault(),e.stopPropagation()}function e4(e){return"nativeEvent"in e}function eh(e){return e.pointerType===""&&e.isTrusted?!0:Xm&&e.pointerType?e.type==="click"&&e.buttons===1:e.detail===0&&!e.pointerType}function Jv(e){return $v?!1:!Xm&&e.width===0&&e.height===0||Xm&&e.width===1&&e.height===1&&e.pressure===0&&e.detail===0&&e.pointerType==="mouse"||e.width<1&&e.height<1&&e.pressure===0&&e.detail===0&&e.pointerType==="touch"}function po(e,t){const a=["mouse","pen"];return t||a.push("",void 0),a.includes(e)}function t4(e){const t=e.type;return t==="click"||t==="mousedown"||t==="keydown"||t==="keyup"}const Jc=Math.min,wl=Math.max,th=Math.round,Ri=Math.floor,Sl=e=>({x:e,y:e}),n4={left:"right",right:"left",bottom:"top",top:"bottom"};function m1(e,t,a){return wl(e,Jc(t,a))}function mo(e,t){return typeof e=="function"?e(t):e}function ra(e){return e.split("-")[0]}function Nl(e){return e.split("-")[1]}function ey(e){return e==="x"?"y":"x"}function ty(e){return e==="y"?"height":"width"}function aa(e){const t=e[0];return t==="t"||t==="b"?"y":"x"}function ny(e){return ey(aa(e))}function s4(e,t,a){a===void 0&&(a=!1);const o=Nl(e),c=ny(e),d=ty(c);let f=c==="x"?o===(a?"end":"start")?"right":"left":o==="start"?"bottom":"top";return t.reference[d]>t.floating[d]&&(f=nh(f)),[f,nh(f)]}function r4(e){const t=nh(e);return[sy(e),t,sy(t)]}function sy(e){return e.includes("start")?e.replace("start","end"):e.replace("end","start")}const h1=["left","right"],g1=["right","left"],a4=["top","bottom"],l4=["bottom","top"];function o4(e,t,a){switch(e){case"top":case"bottom":return a?t?g1:h1:t?h1:g1;case"left":case"right":return t?a4:l4;default:return[]}}function i4(e,t,a,o){const c=Nl(e);let d=o4(ra(e),a==="start",o);return c&&(d=d.map(f=>f+"-"+c),t&&(d=d.concat(d.map(sy)))),d}function nh(e){const t=ra(e);return n4[t]+e.slice(t.length)}function c4(e){var t,a,o,c;return{top:(t=e.top)!=null?t:0,right:(a=e.right)!=null?a:0,bottom:(o=e.bottom)!=null?o:0,left:(c=e.left)!=null?c:0}}function x1(e){return typeof e!="number"?c4(e):{top:e,right:e,bottom:e,left:e}}function nf(e){const{x:t,y:a,width:o,height:c}=e;return{width:o,height:c,top:a,left:t,right:t+o,bottom:a+c,x:t,y:a}}function sh(e,t,a){return Math.floor(e/t)!==a}function ho(e,t){return t<0||t>=e.length}function rh(e,t){return _s(e.current,{disabledIndices:t})}function ry(e,t){return _s(e.current,{decrement:!0,startingIndex:e.current.length,disabledIndices:t})}function _s(e,{startingIndex:t=-1,decrement:a=!1,disabledIndices:o,amount:c=1}={}){let d=t;do d+=a?-c:c;while(d>=0&&d<=e.length-1&&go(e,d,o));return d}function u4(e,{event:t,orientation:a,loopFocus:o,onLoop:c,rtl:d,cols:f,disabledIndices:p,minIndex:h,maxIndex:b,prevIndex:y,stopEvent:v=!1}){let j=y,w;if(t.key===Gv?w="up":t.key===Qm&&(w="down"),w){const k=[],S=[];let N=!1,R=0;{let _=null,z=-1;e.forEach((H,B)=>{if(H==null)return;R+=1;const L=H.closest('[role="row"]');L&&(N=!0),(L!==_||z===-1)&&(_=L,z+=1,k[z]=[]),k[z].push(B),S[B]=z})}let P=!1,T=0;if(N)for(const _ of k){const z=_.length;z>T&&(T=z),z!==f&&(P=!0)}const C=P&&R{if(!P||y===-1)return;const z=S[y];if(z==null)return;const H=k[z].indexOf(y),B=_==="up"?-1:1;for(let L=z+B,F=0;F=k.length){if(!o||C)return;if(L=L<0?k.length-1:0,c){const X=Math.min(H,k[L].length-1),K=k[L][X]??k[L][0],q=c(t,y,K);L=S[q]??L}}const $=k[L];for(let X=Math.min(H,$.length-1);X>=0;X-=1){const K=$[X];if(!go(e,K,p))return K}}},I=_=>{if(!C||y===-1)return;const z=y%E,H=_==="up"?-E:E,B=b-b%E,L=Ri(b/E)+1;for(let F=y-z+H,$=0;$b){if(!o)return;F=F<0?B:0}const X=Math.min(F+E-1,b);for(let K=Math.min(F+z,X);K>=F;K-=1)if(!go(e,K,p))return K}};v&&Cs(t);const O=D(w)??I(w);if(O!==void 0)j=O;else if(y===-1)j=w==="up"?b:h;else if(j=_s(e,{startingIndex:y,amount:E,decrement:w==="up",disabledIndices:p}),o){if(w==="up"&&(y-E_?H:H-E,c&&(j=c(t,y,j))}w==="down"&&y+E>b&&(j=_s(e,{startingIndex:y%E-E,amount:E,disabledIndices:p}),c&&(j=c(t,y,j)))}ho(e,j)&&(j=y)}if(a==="both"){const k=Ri(y/f);t.key===(d?Ei:Ai)&&(v&&Cs(t),y%f!==f-1?(j=_s(e,{startingIndex:y,disabledIndices:p}),o&&sh(j,f,k)&&(j=_s(e,{startingIndex:y-y%f-1,disabledIndices:p}),c&&(j=c(t,y,j)))):o&&(j=_s(e,{startingIndex:y-y%f-1,disabledIndices:p}),c&&(j=c(t,y,j))),sh(j,f,k)&&(j=y)),t.key===(d?Ai:Ei)&&(v&&Cs(t),y%f!==0?(j=_s(e,{startingIndex:y,decrement:!0,disabledIndices:p}),o&&sh(j,f,k)&&(j=_s(e,{startingIndex:y+(f-y%f),decrement:!0,disabledIndices:p}),c&&(j=c(t,y,j)))):o&&(j=_s(e,{startingIndex:y+(f-y%f),decrement:!0,disabledIndices:p}),c&&(j=c(t,y,j))),sh(j,f,k)&&(j=y));const S=Ri(b/f)===k;ho(e,j)&&(o&&S?(j=t.key===(d?Ai:Ei)?b:_s(e,{startingIndex:y-y%f-1,disabledIndices:p}),c&&(j=c(t,y,j))):j=y)}return j}function go(e,t,a){if(typeof a=="function"?a(t):a?.includes(t)??!1)return!0;const c=e[t];return c?!ah(c)||c.matches(":disabled")?!0:!a&&(c.hasAttribute("disabled")||c.getAttribute("aria-disabled")==="true"):!1}function d4(e){return e.visibility==="hidden"||e.visibility==="collapse"}function ah(e,t=e?jr(e):null){return!e||!e.isConnected||!t||d4(t)?!1:typeof e.checkVisibility=="function"?e.checkVisibility():t.display!=="none"&&t.display!=="contents"}const f4='a[href],button,input,select,textarea,summary,details,iframe,object,embed,[tabindex],[contenteditable]:not([contenteditable="false"]),audio[controls],video[controls]';function p4(e){const t=e.assignedSlot;if(t)return t;if(e.parentElement)return e.parentElement;const a=e.getRootNode();return Kc(a)?a.host:null}function ay(e){for(const t of Array.from(e.children))if(Fs(t)==="summary")return t;return null}function m4(e,t){const a=ay(t);return!!a&&(e===a||Ze(a,e))}function b1(e){const t=e?Fs(e):"";return e!=null&&e.matches(f4)&&(t!=="summary"||e.parentElement!=null&&Fs(e.parentElement)==="details"&&ay(e.parentElement)===e)&&(t!=="details"||ay(e)==null)&&(t!=="input"||e.type!=="hidden")}function v1(e){if(!b1(e)||!e.isConnected||e.matches(":disabled"))return!1;for(let t=e;t;t=p4(t)){const a=t!==e,o=Fs(t)==="slot";if(t.hasAttribute("inert")||a&&Fs(t)==="details"&&!t.open&&!m4(e,t)||t.hasAttribute("hidden")||!o&&!h4(t,a))return!1}return!0}function h4(e,t){const a=jr(e);return t?a.display!=="none":ah(e,a)}function y1(e){const t=e.tabIndex;if(t<0){const a=Fs(e);if(a==="details"||a==="audio"||a==="video"||pn(e)&&e.isContentEditable)return 0}return t}function ly(e){if(Fs(e)!=="input")return null;const t=e;return t.type==="radio"&&t.name!==""?t:null}function g4(e,t){const a=ly(e);if(!a)return!0;const o=t.find(c=>{const d=ly(c);return d?.name===a.name&&d.form===a.form&&d.checked});return o?o===a:t.find(c=>{const d=ly(c);return d?.name===a.name&&d.form===a.form})===a}function j1(e){if(pn(e)&&Fs(e)==="slot"){const t=e.assignedElements({flatten:!0});if(t.length>0)return t}return pn(e)&&e.shadowRoot?Array.from(e.shadowRoot.children):Array.from(e.children)}function w1(e,t){j1(e).forEach(a=>{b1(a)&&t.push(a),w1(a,t)})}function S1(e,t,a){j1(e).forEach(o=>{pn(o)&&o.matches(t)&&a.push(o),S1(o,t,a)})}function oy(e){return v1(e)&&y1(e)>=0}function N1(e){const t=[];return w1(e,t),t.filter(v1)}function sf(e){const t=N1(e);return t.filter(a=>y1(a)>=0&&g4(a,t))}function k1(e,t){const a=sf(e),o=a.length;if(o===0)return;const c=ir(Gt(e)),d=a.indexOf(c),f=d===-1?t===1?0:o-1:d+t;return a[f]}function iy(e){return k1(Gt(e).body,1)||e}function C1(e){return k1(Gt(e).body,-1)||e}function T1(e,t){if(!e)return null;const a=sf(Gt(e).body),o=a.length;if(o===0)return null;const c=a.indexOf(e);if(c===-1)return null;const d=(c+t+o)%o;return a[d]}function x4(e){return T1(e,1)}function b4(e){return T1(e,-1)}function eu(e,t){const a=t||e.currentTarget,o=e.relatedTarget;return!o||!Ze(a,o)}function v4(e){sf(e).forEach(a=>{a.dataset.tabindex=a.getAttribute("tabindex")||"",a.setAttribute("tabindex","-1")})}function E1(e){const t=[];S1(e,"[data-tabindex]",t),t.forEach(a=>{const o=a.dataset.tabindex;delete a.dataset.tabindex,o?a.setAttribute("tabindex",o):a.removeAttribute("tabindex")})}function cy(e){x.useEffect(e,Pr)}const rf=0;class la{constructor(){cn(this,"currentId",rf);cn(this,"clear",()=>{this.currentId!==rf&&(clearTimeout(this.currentId),this.currentId=rf)});cn(this,"disposeEffect",()=>this.clear)}static create(){return new la}start(t,a){this.clear(),this.currentId=setTimeout(()=>{this.currentId=rf,a()},t)}isStarted(){return this.currentId!==rf}}function er(){const e=Ps(la.create).current;return cy(e.disposeEffect),e}function y4(e,t){return e.matches(":disabled")?!1:!t||e.form===t?!0:e.form===null&&!e.hasAttribute("form")}const j4=x.createContext({disabled:!1});function A1(){return x.useContext(j4)}var uy={exports:{}},$s={};var R1;function w4(){if(R1)return $s;R1=1;var e=Xd();function t(y){var v="https://react.dev/errors/"+y;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),uy.exports=w4(),uy.exports}var Ts=M1();const lh=null;class S4{constructor(){cn(this,"callbacks",[]);cn(this,"callbacksCount",0);cn(this,"nextId",1);cn(this,"startId",1);cn(this,"isScheduled",!1);cn(this,"tick",t=>{this.isScheduled=!1;const a=this.callbacks,o=this.callbacksCount;if(this.callbacks=[],this.callbacksCount=0,this.startId=this.nextId,o>0)for(let c=0;c=this.callbacks.length||this.callbacks[a]!==null&&(this.callbacks[a]=null,this.callbacksCount-=1)}}let oh=new S4;class Ga{constructor(){cn(this,"currentId",lh);cn(this,"cancel",()=>{this.currentId!==lh&&(oh.cancel(this.currentId),this.currentId=lh)});cn(this,"disposeEffect",()=>this.cancel)}static create(){return new Ga}static request(t){return oh.request(t)}static cancel(t){return oh.cancel(t)}request(t){this.cancel(),this.currentId=oh.request(()=>{this.currentId=lh,t()})}}function tu(){const e=Ps(Ga.create).current;return cy(e.disposeEffect),e}function kl(e){return e==null?e:"current"in e?e.current:e}let ih=null;function N4(e){if(!ih){const t=[];ih=t,queueMicrotask(()=>{ih=null,Ts.flushSync(()=>{for(const a of t)a()})})}ih.push(e)}function D1(e,t=!1,a=!1){const o=tu();return Ie((c,d=null)=>{o.cancel();const f=kl(e);if(f==null)return;const p=f,h=()=>{if(!a){Ts.flushSync(c);return}N4(()=>{d?.aborted||c()})};if(typeof p.getAnimations!="function"||globalThis.BASE_UI_ANIMATIONS_DISABLED){c();return}function b(){Promise.all(p.getAnimations().map(y=>y.finished)).then(()=>{d?.aborted||h()},()=>{if(d?.aborted)return;if(p.getAnimations().some(v=>v.pending||v.playState!=="finished")){b();return}h()})}if(t){const y=d1;if(!p.hasAttribute(y)){o.request(b);return}const v=new MutationObserver(()=>{p.hasAttribute(y)||(v.disconnect(),b())});v.observe(p,{attributes:!0,attributeFilter:[y]}),d?.addEventListener("abort",()=>v.disconnect(),{once:!0});return}o.request(b)})}function oa(e){const{enabled:t=!0,open:a,ref:o,batch:c=!1,onComplete:d}=e,f=Ie(d),p=D1(o,a,c);x.useEffect(()=>{if(!t)return;const h=new AbortController;return p(f,h.signal),()=>{h.abort()}},[t,a,f,p])}function Oi(e,t=!1,a=!1,o=!1){const[c,d]=x.useState(e&&t?"idle":void 0),[f,p]=x.useState(e&&!o);return e&&!f&&(p(!0),d("starting")),!e&&f&&c!=="ending"&&!a&&d("ending"),!e&&!f&&c==="ending"&&d(void 0),Me(()=>{if(!e&&f&&c!=="ending"&&a){const h=Ga.request(()=>{d("ending")});return()=>{Ga.cancel(h)}}},[e,f,c,a]),Me(()=>{if(!e||t)return;const h=Ga.request(()=>{d(void 0)});return()=>{Ga.cancel(h)}},[t,e]),Me(()=>{if(!e||!t)return;e&&f&&c!=="idle"&&d("starting");const h=Ga.request(()=>{d("idle")});return()=>{Ga.cancel(h)}},[t,e,f,c]),{mounted:f,setMounted:p,transitionStatus:c}}function Ka({controlled:e,default:t,name:a,state:o="value"}){const{current:c}=x.useRef(e!==void 0),[d,f]=x.useState(t),p=c&&e!==void 0?e:d,h=x.useCallback(b=>{c||f(b)},[]);return[p,h]}function nu(e,t,a,o,c=!0,d){const{registerFieldControl:f}=Na(),p=Ps(()=>Symbol());Me(()=>{const h=p.current;if(!c){f(h,void 0);return}f(h,{controlRef:e,getValue:o,id:t,name:d,value:a})},[e,c,o,t,d,f,p,a]),Me(()=>{const h=p.current;return()=>{f(h,void 0)}},[f,p])}function ia(e,t){const a=x.useRef(e),o=Ie(t);Me(()=>{a.current!==e&&o(a.current),a.current=e},[e,o])}const Qn="none",xo="trigger-press",qs="trigger-hover",ch="trigger-focus",uh="outside-press",af="item-press",dy="close-press",lf="input-change",Ya="input-clear",k4="input-press",bo="focus-out",su="escape-key",fy="list-navigation",I1="keyboard",P1="pointer",_1="cancel-open",C4="disabled",py="imperative-action",T4="window-resize";function qe(e,t,a,o){let c=!1,d=!1;const f=o??mn;return{reason:e,event:t??new Event("base-ui"),cancel(){c=!0},allowPropagation(){d=!0},get isCanceled(){return c},get isPropagationAllowed(){return d},trigger:a,...f}}function E4(e,t,a){const o=a??mn;return{reason:e,event:t??new Event("base-ui"),...o}}const A4=x.forwardRef(function(t,a){const{render:o,className:c,id:d,name:f,value:p,disabled:h=!1,onValueChange:b,defaultValue:y,autoFocus:v=!1,style:j,...w}=t,{state:k,name:S,disabled:N,setTouched:R,setDirty:P,validityData:T,setFocused:C,setFilled:E,validationMode:D,validation:I}=Na(),{clearErrors:O,elementRef:_,submitCountRef:z}=Zc(),H=N||h,B=S??f,L={...k,disabled:H},{labelId:F}=yl(),$=co({id:d}),[X]=Ka({controlled:p,default:y,name:"FieldControl",state:"value"}),K=p!==void 0,q=K?X:void 0,Q=q==null?void 0:String(q),G=Ie(()=>I.inputRef.current?.value);nu(I.inputRef,$,Q,G,!H,f),Me(()=>{const M=Q??I.inputRef.current?.value;M!==void 0&&E(M!=="")},[Q,I.inputRef,E]),ia(Q,()=>{Q!==void 0&&(O(B),P(Q!==(T.initialValue??"")),I.change(Q))});const J=x.useRef(null),Y=er();return Me(()=>{v&&J.current===ir(Gt(J.current))&&C(!0)},[v,C]),yt("input",t,{ref:[a,J],state:L,props:[{id:$,disabled:H,name:B,ref:I.inputRef,"aria-labelledby":F,autoFocus:v,...K?{value:q}:{defaultValue:y},onChange(M){const U=M.currentTarget.value,Z=qe(Qn,M.nativeEvent);b?.(U,Z),!K&&(P(U!==(T.initialValue??"")),E(U!==""),!M.nativeEvent.defaultPrevented&&!Z.isCanceled&&(O(B),I.change(U)))},onFocus(){C(!0)},onBlur(M){if(R(!0),C(!1),D==="onBlur"){const U=M.currentTarget.value;I.commit(U),K&&queueMicrotask(()=>{const Z=I.inputRef.current?.value;Z!==void 0&&Z!==U&&Z!==(T.initialValue??"")&&I.commit(Z)})}},onKeyDown(M){if(M.currentTarget.tagName==="INPUT"&&M.key==="Enter"){R(!0);const U=M.currentTarget.value,Z=M.currentTarget.form;if(Z&&Z===_.current&&!M.defaultPrevented){const ae=M.currentTarget,ce=z.current;Y.start(0,()=>{z.current===ce&&I.commit(ae.value)})}else I.commit(U)}}},w,M=>I.getValidationProps(H,M)],stateAttributesMapping:Ti})}),R4=x.forwardRef(function(t,a){return s.jsx(A4,{ref:a,...t})});function Fe({className:e,type:t,ref:a,...o}){return s.jsx(R4,{ref:a,type:t,"data-slot":"input",className:Ue("h-[30px] w-full min-w-0 rounded-md border border-control-border bg-control px-2.5","text-[12.5px] text-foreground outline-none","transition-[border-color,box-shadow] duration-150 ease-out","placeholder:text-muted-foreground","hover:border-control-border-hover","focus:border-primary focus:shadow-focus","disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-surface-3 disabled:text-muted-foreground","file:inline-flex file:border-0 file:bg-transparent file:text-foreground",e),...o})}function Mi({className:e,...t}){return s.jsx("textarea",{"data-slot":"textarea",className:Ue("min-h-26 w-full resize-y rounded-md border border-control-border bg-control px-3 py-2.5","font-mono text-[12px] leading-[1.6] text-foreground outline-none","transition-[border-color,box-shadow] duration-150 ease-out","placeholder:text-muted-foreground","hover:border-control-border-hover","focus:border-primary focus:shadow-focus","disabled:cursor-not-allowed disabled:bg-surface-3 disabled:text-muted-foreground",e),...t})}function Di({className:e,...t}){return s.jsx("div",{"data-slot":"input-group",role:"group",className:Ue("group/input-group relative flex h-[30px] w-full min-w-0 items-center rounded-md border border-control-border bg-control","transition-[border-color,box-shadow] duration-150 ease-out","outline-none","has-[[data-slot=input-group-control]:focus-visible]:border-primary","has-[[data-slot=input-group-control]:focus-visible]:shadow-focus","has-[[data-slot=input-group-control]:hover:not(:focus-visible)]:border-control-border-hover","has-[>textarea]:h-auto","has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:pl-1.5","has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:pr-1.5","has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col","has-[>[data-align=block-start]]:[&>[data-slot=input-group-control]]:pb-1.5","has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col","has-[>[data-align=block-end]]:[&>[data-slot=input-group-control]]:pt-1.5",e),...t})}const O4=Qc(["flex h-auto cursor-text items-center justify-center gap-1.5 select-none","text-[12px] font-medium text-muted-foreground","group-data-[disabled=true]/input-group:opacity-50"],{variants:{align:{"inline-start":"order-first pl-[9px] has-[>button]:-ml-1","inline-end":"order-last pr-[9px] has-[>button]:-mr-1","block-start":"order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-1.5","block-end":"order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-1.5"}},defaultVariants:{align:"inline-start"}});function Ii({className:e,align:t="inline-start",...a}){return s.jsx("div",{role:"group","data-slot":"input-group-addon","data-align":t,className:Ue(O4({align:t}),e),onClick:o=>{o.target.closest("button")||o.currentTarget.parentElement?.querySelector("input")?.focus()},...a})}const M4=Qc("flex items-center shadow-none",{variants:{size:{xs:"h-6 gap-1 rounded-xs px-1.5",sm:"h-8 gap-1.5 rounded-sm px-2.5","icon-xs":"size-6 rounded-xs p-0","icon-sm":"size-8 rounded-sm p-0"}},defaultVariants:{size:"xs"}});function D4({className:e,type:t="button",variant:a="ghost",size:o="xs",...c}){return s.jsx(ne,{type:t,"data-size":o,variant:a,className:Ue(M4({size:o}),e),...c})}function Pi({className:e,...t}){return s.jsx(Fe,{"data-slot":"input-group-control",className:Ue("flex-1 rounded-none border-0 bg-transparent shadow-none focus:border-0 focus:shadow-none",e),...t})}function I4(e){return yt(e.defaultTagName??"div",e,e)}const P4=Qc("inline-flex w-fit shrink-0 items-center justify-center gap-[5px] overflow-hidden whitespace-nowrap border font-semibold",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground",secondary:"border-transparent bg-secondary text-secondary-foreground",destructive:"border-destructive-bd bg-destructive-soft text-destructive",outline:"border-control-border bg-control text-subtle",ghost:"border-transparent bg-transparent text-muted-foreground",link:"border-transparent bg-transparent text-primary underline-offset-4 hover:underline",success:"border-success-bd bg-success-soft text-success",warning:"border-warning-bd bg-warning-soft text-warning",info:"border-info-bd bg-info-soft text-info",brand:"border-primary-bd bg-primary-soft text-primary-fg",cn:"border-cn-bd bg-cn-soft text-cn",intl:"border-intl-bd bg-intl-soft text-intl",sensitive:"border-sensitive-bd bg-sensitive-soft text-sensitive"},shape:{pill:"min-h-[21px] rounded-pill px-[9px] py-px text-[11.5px]",tag:"min-h-[19px] rounded-xs px-2 py-0 text-[11px]"}},defaultVariants:{variant:"default",shape:"pill"}});function ze({className:e,variant:t,shape:a,render:o,...c}){return I4({render:o,defaultTagName:"span",props:ta({"data-slot":"badge"},c,{className:Ue(P4({variant:t,shape:a}),e)})})}function my({className:e,...t}){return s.jsx("span",{className:Ue("size-1.5 flex-none rounded-full bg-current",e),...t})}function vo(e,t){if(typeof window>"u")return e;const a=window.wbI18n;return a?a.t(e,t)??e:e}function of({className:e,...t}){return s.jsx("svg",{"data-slot":"spinner",role:"status","aria-label":vo("加载中"),viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",className:Ue("size-4 animate-spin [animation-duration:0.7s]",e),...t,children:s.jsx("path",{d:"M21 12a9 9 0 1 1-6.219-8.56"})})}function Je({className:e,...t}){return s.jsx("label",{"data-slot":"label",className:Ue("flex items-center gap-[6px] text-[11.5px] text-muted-foreground",e),...t})}const L1={clipPath:"inset(50%)",overflow:"hidden",whiteSpace:"nowrap",border:0,padding:0,width:1,height:1,margin:-1},_i={...L1,position:"fixed",top:0,left:0},ru={...L1,position:"absolute"},z1=x.createContext(void 0);function _4(){const e=x.useContext(z1);if(e===void 0)throw new Error(un(63));return e}const L4="data-checked",z4="data-unchecked",B1={...Ti,checked(e){return e?{[L4]:""}:{[z4]:""}}},B4=x.forwardRef(function(t,a){const{checked:o,className:c,defaultChecked:d,"aria-labelledby":f,form:p,id:h,inputRef:b,name:y,nativeButton:v=!1,onCheckedChange:j,readOnly:w=!1,required:k=!1,disabled:S=!1,render:N,uncheckedValue:R,value:P,style:T,...C}=t,{clearErrors:E}=Zc(),{state:D,setTouched:I,setDirty:O,validityData:_,setFilled:z,setFocused:H,validationMode:B,disabled:L,name:F,validation:$}=Na(),{labelId:X}=yl(),K=L||S,q=F??y,Q=x.useRef(null),G=sa(Q,b,$.inputRef),J=x.useRef(null),Y=ka(),re=co({id:h}),M=v?void 0:re,[U,Z]=Ka({controlled:o,default:!!d,name:"Switch",state:"checked"});nu(J,Y,U,void 0,!K,y),Me(()=>{z(U)},[U,z]),ia(U,()=>{E(q),O(U!==_.initialValue),$.change(U)});const{getButtonProps:ae,buttonRef:ce}=na({disabled:K,native:v}),W=Fv(f,X,Q,!v,M),ue={id:v?re:Y,role:"switch","aria-checked":U,"aria-readonly":w||void 0,"aria-required":k||void 0,"aria-labelledby":W,onFocus(){K||H(!0)},onBlur(){const te=Q.current;!te||K||(I(!0),H(!1),B==="onBlur"&&$.commit(te.checked))},onClick(te){if(w||K)return;te.preventDefault();const ke=Q.current;ke&&Xc(ke,te)}},ve={...$.getValidationProps(K),checked:U,disabled:K,form:p,id:M,name:q,required:k,style:q?ru:_i,tabIndex:-1,type:"checkbox","aria-hidden":!0,ref:G,onChange(te){if(te.nativeEvent.defaultPrevented)return;if(w){te.preventDefault();return}const ke=te.currentTarget.checked,le=qe(Qn,te.nativeEvent);j?.(ke,le),!le.isCanceled&&Z(ke)},onClick(te){te.stopPropagation()},onFocus(){J.current?.focus()},...P!==void 0?{value:P}:mn},ee=x.useMemo(()=>({...D,checked:U,disabled:K,readOnly:w,required:k}),[D,U,K,w,k]),he=yt("span",t,{state:ee,ref:[a,J,ce],props:[ue,C,ae,te=>$.getValidationProps(K,te)],stateAttributesMapping:B1});return s.jsxs(z1.Provider,{value:ee,children:[he,!U&&q&&R!==void 0&&s.jsx("input",{type:"hidden",form:p,name:q,value:R,disabled:K}),s.jsx("input",{...ve,suppressHydrationWarning:!0})]})}),H4=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,p=_4();return yt("span",t,{state:p,ref:a,stateAttributesMapping:B1,props:f})});function Zn({className:e,size:t="default",...a}){const o=t==="sm";return s.jsx(B4,{"data-slot":"switch",className:Ue("relative inline-flex flex-none cursor-pointer items-center rounded-pill border-0 bg-border-strong p-0","transition-colors duration-[180ms] ease-out","data-checked:bg-primary","focus-visible:shadow-focus focus-visible:outline-none","data-disabled:cursor-not-allowed data-disabled:opacity-50",o?"h-[14px] w-6":"h-[21px] w-9",e),...a,children:s.jsx(H4,{"data-slot":"switch-thumb",className:Ue("block rounded-full bg-primary-on shadow-1","transition-transform duration-[180ms] [transition-timing-function:cubic-bezier(.3,1.4,.6,1)]",o?"size-[10px] translate-x-0.5 data-checked:translate-x-[10px]":"size-[17px] translate-x-0.5 data-checked:translate-x-[15px]")})})}function U4(e){if(!e)return null;for(const t of e.elements){const a=t.tagName;if(a==="BUTTON"||a==="INPUT"){const o=t;if(o.type==="submit")return o}}return null}const V4="data-checked",F4="data-unchecked";function H1(e){return{checked(t){return e.indeterminate?{}:t?{[V4]:""}:{[F4]:""}},...Ti}}const $4=x.createContext(void 0);function q4(){return x.useContext($4)}const U1=x.createContext(void 0);function G4(){const e=x.useContext(U1);if(e===void 0)throw new Error(un(14));return e}const K4="data-parent",Y4=x.forwardRef(function(t,a){const{checked:o,className:c,defaultChecked:d=!1,"aria-labelledby":f,disabled:p=!1,form:h,id:b,indeterminate:y=!1,inputRef:v,name:j,onCheckedChange:w,parent:k=!1,readOnly:S=!1,render:N,required:R=!1,uncheckedValue:P,value:T,nativeButton:C=!1,style:E,...D}=t,{clearErrors:I}=Zc(),{disabled:O,name:_,setDirty:z,setFilled:H,setFocused:B,setTouched:L,state:F,validationMode:$,validityData:X,validation:K}=Na(),q=A1(),{labelId:Q,registerControlId:G,getDescriptionProps:J}=yl(),Y=q4(),re=Y?.allValues===void 0?void 0:Y.parent,M=re!==void 0,U=O||q.disabled||Y?.disabled||p,Z=_??j,ae=T??Z,ce=ka(),W=Y?.registerControlId!==G,ue=co({id:b||void 0,enabled:W}),ve=C?ue:ce;let ee={};M&&(k?ee=re.getParentProps():ae!==void 0&&(ee=re.getChildProps(ae)));const{checked:he=o,indeterminate:te=y,onCheckedChange:ke,...le}=ee,de=Y?.value,Se=x.useRef(null),{getButtonProps:Te,buttonRef:Le}=na({disabled:U,native:C}),Ae=Y?.validation??K,[oe,me]=Ka({controlled:ae!==void 0&&de!==void 0&&!k?de.includes(ae):he,default:d,name:"Checkbox",state:"checked"}),pe=M?!!he:oe,Ce=M&&te||y;nu(Se,ce,oe,void 0,!Y&&!U,j);const Ne=re?.registerChildId,be=x.useRef(null),De=Ae.registerInput,Ge=Y?ae:void 0,Ct=x.useCallback(it=>De(it,{controlRef:Se,value:Ge}),[De,Ge]),Tt=sa(v,be,k?void 0:Ct),Mt=Fv(f,Q,be,!C,ue);Me(()=>{be.current&&(be.current.indeterminate=Ce),Y||H(oe)},[oe,Ce,Y,H]),ia(oe,()=>{Y||(I(Z),z(oe!==X.initialValue),Ae.change(oe))});const ot=ta({checked:oe,disabled:U,form:h,name:k?void 0:Z,id:C?void 0:ue,required:R,ref:Tt,style:Z?ru:_i,tabIndex:-1,type:"checkbox","aria-hidden":!0,onChange(it){if(it.nativeEvent.defaultPrevented)return;if(S){it.preventDefault();return}const $t=it.currentTarget.checked,Vn=qe(Qn,it.nativeEvent);if(w?.($t,Vn),!Vn.isCanceled&&(ke?.($t,Vn),!Vn.isCanceled&&(me($t),ae!==void 0&&Y!==void 0&&!k&&!M))){const rn=$t?[...Y.value,ae]:Y.value.filter(nt=>nt!==ae);Y.setValue(rn,Vn)}},onClick(it){it.stopPropagation()},onFocus(){Se.current?.focus()}},T!==void 0?{value:(Y?oe&&T:T)||""}:mn,J,it=>Ae.getValidationProps(U,it));x.useEffect(()=>{if(!re||ae===void 0)return;const it=re.disabledStatesRef.current;return it.set(ae,U),()=>{it.delete(ae)}},[re,U,ae]);const Kn=x.useMemo(()=>({...F,checked:pe,disabled:U,readOnly:S,required:R,indeterminate:Ce}),[F,pe,U,S,R,Ce]),ms=H1(Kn),Yn=yt("span",t,{state:Kn,ref:[Le,Se,a],props:[{id:ve,role:"checkbox","aria-checked":Ce?"mixed":pe,"aria-readonly":S||void 0,"aria-required":R||void 0,"aria-labelledby":Mt,[K4]:k?"":void 0,onFocus(){U||B(!0)},onBlur(){const it=be.current;it&&(L(!0),B(!1),$==="onBlur"&&Ae.commit(Y?de:it.checked))},onKeyDown(it){if(it.key!=="Enter"||(it.preventBaseUIHandler(),it.defaultPrevented))return;const $t=be.current?.form??null,Vn=it.currentTarget,rn=it.nativeEvent,nt=it.preventDefault,Dt=rn.preventDefault;let qt=!1;it.preventDefault=()=>{qt=!0,nt.call(it)},rn.preventDefault=()=>{qt=!0,Dt.call(rn)},Dt.call(rn),Cn(Vn).queueMicrotask(()=>{it.preventDefault=nt,rn.preventDefault=Dt,qt||U4($t)?.click()})},onClick(it){if(S||U)return;it.preventDefault();const $t=be.current;$t&&Xc($t,it)}},D,le,Te,J,it=>Ae.getValidationProps(U,it)],stateAttributesMapping:ms}),vs=Yn.props.id;return Me(()=>{if(!(!Ne||k||ae===void 0||vs===void 0))return Ne(ae,vs)},[Ne,k,ae,vs]),s.jsxs(U1.Provider,{value:Kn,children:[Yn,!oe&&!Y&&Z&&!k&&P!==void 0&&s.jsx("input",{type:"hidden",form:h,name:Z,value:P,disabled:U}),s.jsx("input",{...ot,suppressHydrationWarning:!0})]})}),X4=x.forwardRef(function(t,a){const{render:o,className:c,style:d,keepMounted:f=!1,...p}=t,h=G4(),b=h.checked||h.indeterminate,{mounted:y,transitionStatus:v,setMounted:j}=Oi(b),w=x.useRef(null),k={...h,transitionStatus:v};oa({batch:!0,enabled:!b,open:b,ref:w,onComplete(){b||j(!1)}});const N={...H1(h),...uo},R=f||y,P=yt("span",t,{ref:[a,w],state:k,stateAttributesMapping:N,props:p});return R?P:null});function _r({className:e,...t}){return s.jsx(Y4,{"data-slot":"checkbox",className:Ue("group/checkbox relative inline-flex size-3.5 shrink-0 cursor-pointer items-center justify-center rounded-[3px] border border-control-border bg-control","outline-none transition-colors duration-150 ease-out","hover:border-control-border-hover","data-checked:border-primary data-checked:bg-primary","focus-visible:shadow-focus","data-disabled:cursor-not-allowed data-disabled:opacity-45",e),...t,children:s.jsx(X4,{"data-slot":"checkbox-indicator",className:"grid place-content-center text-primary-foreground data-unchecked:hidden",children:s.jsxs("svg",{viewBox:"0 0 12 12",className:"size-2.5","aria-hidden":"true",children:[s.jsx("path",{d:"M2 6h8",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",fill:"none",className:"hidden group-aria-[checked=indeterminate]/checkbox:block"}),s.jsx("path",{d:"M2.5 6.2 4.8 8.5 9.5 3.8",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",fill:"none",className:"group-aria-[checked=indeterminate]/checkbox:hidden"})]})})})}function hy(e){return Array.isArray(e)?e.map(t=>hy(t)).join(","):e==null?"":String(e)}const V1=new Map;function Q4(e,t){const a=JSON.stringify({locale:hy(e),options:t}),o=V1.get(a);if(o)return o;const c=new Intl.NumberFormat(e,t);return V1.set(a,c),c}function F1(e,t,a){return e==null?"":Q4(t,a).format(e)}function Li(e,t=Number.MIN_SAFE_INTEGER,a=Number.MAX_SAFE_INTEGER){return Math.max(t,Math.min(e,a))}function Z4(e,t,a){return(e-t)*100/(a-t)}const $1=x.createContext(void 0);function q1(){const e=x.useContext($1);if(e===void 0)throw new Error(un(51));return e}const W4="data-complete",J4="data-indeterminate",eH="data-progressing",gy={status(e){return e==="progressing"?{[eH]:""}:e==="complete"?{[W4]:""}:e==="indeterminate"?{[J4]:""}:null}},tH=x.forwardRef(function(t,a){const{format:o,getAriaValueText:c,locale:d,max:f=100,min:p=0,value:h,render:b,className:y,children:v,style:j,...w}=t,[k,S]=x.useState();let N="indeterminate",R=null,P=null,T="",C="indeterminate progress";if(h!=null&&Number.isFinite(h)){const _=Z4(h,p,f);R=Li(Number.isNaN(_)?0:_,0,100),P=Li(h,p,f),N=P===f?"complete":"progressing",T=o?F1(P,d,o):F1(R/100,d,{style:"percent"}),C=T}const E=x.useMemo(()=>({status:N}),[N]),D={"aria-labelledby":k,"aria-valuemax":f,"aria-valuemin":p,"aria-valuenow":P??void 0,"aria-valuetext":c?c(T,h):C,role:"progressbar",children:s.jsxs(x.Fragment,{children:[v,s.jsx("span",{role:"presentation",style:_i,children:"x"})]})},I=x.useMemo(()=>({formattedValue:T,percentageValue:R,setLabelId:S,state:E,value:h}),[T,R,S,E,h]),O=yt("div",t,{state:E,ref:a,props:[D,w],stateAttributesMapping:gy});return s.jsx($1.Provider,{value:I,children:O})}),nH=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,{state:p}=q1();return yt("div",t,{state:p,ref:a,props:f,stateAttributesMapping:gy})}),sH=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,{percentageValue:p,state:h}=q1(),b=p==null?{}:{insetInlineStart:0,height:"inherit",width:`${p}%`};return yt("div",t,{state:h,ref:a,props:[{style:b},f],stateAttributesMapping:gy})});function cf({className:e,children:t,value:a,...o}){return s.jsxs(tH,{value:a,"data-slot":"progress",className:Ue("flex w-full flex-wrap items-center gap-3",e),...o,children:[t,s.jsx(rH,{children:s.jsx(aH,{})})]})}function rH({className:e,...t}){return s.jsx(nH,{"data-slot":"progress-track",className:Ue("relative flex h-1.5 w-full items-center overflow-x-hidden overflow-y-hidden rounded-pill bg-surface-3",e),...t})}function aH({className:e,...t}){return s.jsx(sH,{"data-slot":"progress-indicator",className:Ue("h-full rounded-[inherit] bg-primary transition-[width] duration-300 ease-out",e),...t})}const xy=[];let by;function lH(){return by}function oH(e){xy.push(e)}function dh(e){const t=(a,o)=>{const c=Ps(iH).current;let d;try{by=c;for(const f of xy)f.before(c);d=e(a,o);for(const f of xy)f.after(c);c.didInitialize=!0}finally{by=void 0}return d};return t.displayName=e.displayName||e.name,t}function G1(e){return x.forwardRef(dh(e))}function iH(){return{didInitialize:!1}}const K1=x.createContext(void 0);function uf(e){const t=x.useContext(K1);if(t===void 0&&!e)throw new Error(un(72));return t}function cH(e,t){return t!=null&&!po(t)?0:typeof e=="function"?e():e}function zi(e,t,a){const o=cH(e,a);return typeof o=="number"?o:o?.[t]}function Y1(e){return typeof e=="function"?e():e}function X1(e,t){return t||e==="click"||e==="mousedown"}function uH(e){return e?.includes("mouse")&&e!=="mousedown"}const Q1=x.createContext({hasProvider:!1,timeoutMs:0,delayRef:{current:0},initialDelayRef:{current:0},timeout:new la,currentIdRef:{current:null},currentContextRef:{current:null}});function dH(e,t){e.current=t.current}function fH(e){const{children:t,delay:a,timeoutMs:o=0}=e,c=x.useRef(a),d=x.useRef(a),f=x.useRef(null),p=x.useRef(null),h=er();return Me(()=>{if(d.current=a,!f.current){c.current=a;return}c.current={open:zi(c.current,"open"),close:zi(a,"close")}},[a,f,c,d]),s.jsx(Q1.Provider,{value:x.useMemo(()=>({hasProvider:!0,delayRef:c,initialDelayRef:d,currentIdRef:f,timeoutMs:o,currentContextRef:p,timeout:h}),[o,h]),children:t})}function pH(e,t={open:!1}){const{open:a}=t,o="rootStore"in e?e.rootStore:e,c=o.useState("floatingId"),d=x.useContext(Q1),{currentIdRef:f,delayRef:p,timeoutMs:h,initialDelayRef:b,currentContextRef:y,hasProvider:v,timeout:j}=d,[w,k]=x.useState(!1),S=x.useRef(a);return Me(()=>{S.current=a},[a]),Me(()=>{function N(){y.current?.setIsInstantPhase(!1),f.current=null,y.current=null,p.current=b.current,j.clear()}if(f.current&&!a&&f.current===c){if(k(!1),h){const R=c;return j.start(h,()=>{o.select("open")||f.current&&f.current!==R||N()}),()=>{(S.current||f.current!==R)&&j.clear()}}N()}},[a,c,f,p,h,b,y,j,o]),Me(()=>{if(!a)return;const N=y.current,R=f.current;j.clear(),y.current={onOpenChange:o.setOpen,setIsInstantPhase:k},f.current=c,p.current={open:0,close:zi(b.current,"close")},R!==null&&R!==c?(k(!0),N?.setIsInstantPhase(!0),N?.onOpenChange(!1,qe(Qn))):(k(!1),N?.setIsInstantPhase(!1))},[a,c,o,f,p,b,y,j]),Me(()=>()=>{if(f.current===c){if(y.current=null,!S.current)return;f.current=null,dH(p,b),j.clear()}},[y,f,p,c,b,j]),x.useMemo(()=>({activeIdRef:f,hasProvider:v,delayRef:p,isInstantPhase:w}),[f,v,p,w])}function St(e,t,a,o){return e.addEventListener(t,a,o),()=>{e.removeEventListener(t,a,o)}}function Xa(...e){return()=>{for(let t=0;t{t.current=t.next}};return t}const au=x.forwardRef(function(t,a){const[o,c]=x.useState();Me(()=>{zB&&jl&&c("button")},[]);const d={tabIndex:0,role:o};return s.jsx("span",{...t,ref:a,style:_i,"aria-hidden":o?void 0:!0,...d,"data-base-ui-focus-guard":""})});function df(e){return`data-base-ui-${e}`}let fh=0;function ph(e,t={}){const{preventScroll:a=!1,sync:o=!1,shouldFocus:c}=t;cancelAnimationFrame(fh);function d(){c&&!c()||e?.focus({preventScroll:a})}if(o)return d(),Kt;const f=requestAnimationFrame(d);return fh=f,()=>{fh===f&&(cancelAnimationFrame(f),fh=0)}}const vy={inert:new WeakMap,"aria-hidden":new WeakMap},Z1="data-base-ui-inert",yy={inert:new WeakSet,"aria-hidden":new WeakSet};let ff=new WeakMap,jy=0;function hH(e){return yy[e]}function W1(e){return e?Kc(e)?e.host:W1(e.parentNode):null}const J1=(e,t)=>t.map(a=>{if(e.contains(a))return a;const o=W1(a);return e.contains(o)?o:null}).filter(a=>a!=null),eT=e=>{const t=new Set;return e.forEach(a=>{let o=a;for(;o&&!t.has(o);)t.add(o),o=o.parentNode}),t},tT=(e,t,a)=>{const o=[],c=d=>{!d||a.has(d)||Array.from(d.children).forEach(f=>{Fs(f)!=="script"&&(t.has(f)?c(f):o.push(f))})};return c(e),o};function gH(e,t,a,o,{mark:c=!0}){let d=null;o?d="inert":a&&(d="aria-hidden");let f=null,p=null;const h=J1(t,e),b=c?tT(t,eT(h),new Set(h)):[],y=[],v=[];if(d){const j=vy[d],w=hH(d);p=w,f=j;const k=J1(t,Array.from(t.querySelectorAll("[aria-live]"))),S=h.concat(k);tT(t,eT(S),new Set(S)).forEach(R=>{const P=R.getAttribute(d),T=P!==null&&P!=="false",C=(j.get(R)||0)+1;j.set(R,C),y.push(R),C===1&&T&&w.add(R),T||R.setAttribute(d,d==="inert"?"":"true")})}return c&&b.forEach(j=>{const w=(ff.get(j)||0)+1;ff.set(j,w),v.push(j),w===1&&j.setAttribute(Z1,"")}),jy+=1,()=>{f&&y.forEach(j=>{const k=(f.get(j)||0)-1;f.set(j,k),k||(!p?.has(j)&&d&&j.removeAttribute(d),p?.delete(j))}),c&&v.forEach(j=>{const w=(ff.get(j)||0)-1;ff.set(j,w),w||j.removeAttribute(Z1)}),jy-=1,jy||(vy.inert=new WeakMap,vy["aria-hidden"]=new WeakMap,yy.inert=new WeakSet,yy["aria-hidden"]=new WeakSet,ff=new WeakMap)}}function nT(e,t={}){const{ariaHidden:a=!1,inert:o=!1,mark:c=!0}=t,d=Gt(e[0]).body;return gH(e,d,a,o,{mark:c})}const xH=500,bH={style:{transition:"none"}},sT="data-base-ui-click-trigger",rT={fallbackAxisSide:"none"},aT={fallbackAxisSide:"end"},vH={clipPath:"inset(50%)",position:"fixed",top:0,left:0},lT=x.createContext(null),oT=()=>x.useContext(lT),yH=df("portal");function iT(e={}){const{ref:t,container:a,componentProps:o=mn,elementProps:c}=e,d=Jd(),p=oT()?.portalNode,[h,b]=x.useState(null),[y,v]=x.useState(null),j=Ie(N=>{N!==null&&v(N)}),w=x.useRef(null);Me(()=>{if(a===null){w.current&&(w.current=null,v(null),b(null));return}const N=(a&&(Tv(a)?a:a.current))??p??document.body;if(N==null){w.current&&(w.current=null,v(null),b(null));return}w.current!==N&&(w.current=N,v(null),b(N))},[a,p]);const k=yt("div",o,{ref:[t,j],props:[{id:d,[yH]:""},c]}),S=h&&k?Ts.createPortal(k,h):null;return{node:y,nodeId:x.isValidElement(k)?k.props.id:void 0,subtree:S}}const mh=x.forwardRef(function(t,a){const{render:o,className:c,style:d,children:f,container:p,portalOwnerRole:h,...b}=t,{node:y,nodeId:v,subtree:j}=iT({container:p,ref:a,componentProps:t,elementProps:b}),w=x.useRef(null),k=x.useRef(null),S=x.useRef(null),N=x.useRef(null),[R,P]=x.useState(null),T=x.useRef(!1),C=R?.modal,E=R?.open,D=!!R&&!R.modal&&R.open&&!!y;x.useEffect(()=>{if(!y||C)return;function O(_){y&&_.relatedTarget&&eu(_)&&(_.type==="focusin"?T.current&&(E1(y),T.current=!1):(v4(y),T.current=!0))}return Xa(St(y,"focusin",O,!0),St(y,"focusout",O,!0))},[y,C]),Me(()=>{!y||E!==!0||!T.current||(E1(y),T.current=!1)},[E,y]);const I=x.useMemo(()=>({beforeOutsideRef:w,afterOutsideRef:k,beforeInsideRef:S,afterInsideRef:N,portalNode:y,setFocusManagerState:P}),[y]);return s.jsxs(x.Fragment,{children:[j,s.jsxs(lT.Provider,{value:I,children:[D&&y&&s.jsx(au,{"data-type":"outside",ref:w,onFocus:O=>{if(eu(O,y))S.current?.focus();else{const _=R?R.domReference:null;C1(_)?.focus()}}}),D&&y&&s.jsx("span",{role:h,"aria-owns":v,style:vH}),y&&Ts.createPortal(f,y),D&&y&&s.jsx(au,{"data-type":"outside",ref:k,onFocus:O=>{if(eu(O,y))N.current?.focus();else{const _=R?R.domReference:null;iy(_)?.focus(),R?.closeOnFocusOut&&R?.onOpenChange(!1,qe(bo,O.nativeEvent))}}})]})]})});function cT(){const e=new Map;return{emit(t,a){e.get(t)?.forEach(o=>o(a))},on(t,a){e.has(t)||e.set(t,new Set),e.get(t).add(a)},off(t,a){e.get(t)?.delete(a)}}}class jH{constructor(){cn(this,"nodesRef",{current:[]});cn(this,"events",cT())}addNode(t){this.nodesRef.current.push(t)}removeNode(t){const a=this.nodesRef.current.findIndex(o=>o===t);a!==-1&&this.nodesRef.current.splice(a,1)}}const uT=x.createContext(null),dT=x.createContext(null),lu=()=>x.useContext(uT)?.id||null,Bi=e=>{const t=x.useContext(dT);return e??t};function wH(e){const t=Jd(),a=Bi(e),o=lu();return Me(()=>{if(!t)return;const c={id:t,parentId:o};return a?.addNode(c),()=>{a?.removeNode(c)}},[a,t,o]),t}function SH(e){const{children:t,id:a}=e,o=lu();return s.jsx(uT.Provider,{value:x.useMemo(()=>({id:a,parentId:o}),[a,o]),children:t})}function NH(e){const{children:t,externalTree:a}=e,o=Ps(()=>a??new jH).current;return s.jsx(dT.Provider,{value:o,children:t})}function kH(e,t){const a=Cn(fs(e));return e instanceof a.KeyboardEvent?"keyboard":e instanceof a.FocusEvent?t||"keyboard":"pointerType"in e?e.pointerType||"keyboard":"touches"in e?"touch":e instanceof a.MouseEvent?t||(e.detail===0?"keyboard":"mouse"):""}const fT=20;let yo=[];function wy(){yo=yo.filter(e=>e.deref()?.isConnected)}function pT(e){wy(),e&&Fs(e)!=="body"&&(yo.push(new WeakRef(e)),yo.length>fT&&(yo=yo.slice(-fT)))}function mT(){return wy(),yo[yo.length-1]?.deref()}function CH(e){return e?oy(e)?e:sf(e)[0]||e:null}function hT(e){if(e.hasAttribute("tabindex")&&!e.hasAttribute("data-tabindex")||!e.getAttribute("role")?.includes("dialog"))return;const a=N1(e).filter(c=>{const d=c.getAttribute("data-tabindex")||"";return oy(c)||c.hasAttribute("data-tabindex")&&!d.startsWith("-")}),o=e.getAttribute("tabindex");a.length===0?o!=="0"&&(e.setAttribute("tabindex","0"),e.setAttribute("data-tabindex","0")):(o!=="-1"||e.hasAttribute("data-tabindex")&&e.getAttribute("data-tabindex")!=="-1")&&(e.setAttribute("tabindex","-1"),e.setAttribute("data-tabindex","-1"))}function hh(e){const{context:t,children:a,disabled:o=!1,initialFocus:c=!0,returnFocus:d=!0,restoreFocus:f=!1,modal:p=!0,closeOnFocusOut:h=!0,openInteractionType:b="",nextFocusableElement:y,previousFocusableElement:v,beforeContentFocusGuardRef:j,externalTree:w,getInsideElements:k}=e,S="rootStore"in t?t.rootStore:t,N=S.useState("open"),R=S.useState("domReferenceElement"),P=S.useState("floatingElement"),{events:T,dataRef:C}=S.context,E=Ie(()=>C.current.floatingContext?.nodeId),D=c===!1,I=Wv(R)&&D,O=Wn(c),_=Wn(d),z=Wn(b),H=Wn(N),B=Bi(w),L=oT(),F=x.useRef(!1),$=x.useRef(!1),X=x.useRef(!1),K=x.useRef(null),q=x.useRef(""),Q=x.useRef(""),G=x.useRef(null),J=x.useRef(null),Y=sa(G,j,L?.beforeInsideRef),re=sa(J,L?.afterInsideRef),M=er(),U=er(),Z=tu(),ae=L!=null,ce=Jm(P),W=Ie((ee=ce)=>ee?sf(ee):[]),ue=Ie(()=>k?.().filter(ee=>ee!=null)??[]);x.useEffect(()=>{if(o||!p)return;function ee(te){te.key==="Tab"&&Ze(ce,ir(Gt(ce)))&&W().length===0&&!I&&Cs(te)}const he=Gt(ce);return St(he,"keydown",ee)},[o,ce,p,I,W]),x.useEffect(()=>{if(o||!N)return;const ee=Gt(ce);function he(){X.current=!1}function te(le){const de=fs(le),Se=ue(),Te=Ze(P,de)||Ze(R,de)||Ze(L?.portalNode,de)||Se.some(Le=>Le===de||Ze(Le,de));X.current=!Te,Q.current=le.pointerType||"keyboard",de?.closest(`[${sT}]`)&&($.current=!0,U.start(0,()=>{$.current=!1}))}function ke(){Q.current="keyboard"}return Xa(St(ee,"pointerdown",te,!0),St(ee,"pointerup",he,!0),St(ee,"pointercancel",he,!0),St(ee,"keydown",ke,!0),he)},[o,P,R,ce,N,L,U,ue]),x.useEffect(()=>{if(o||!h)return;const ee=Gt(ce);function he(){$.current=!0,U.start(0,()=>{$.current=!1})}function te(Se){const Te=fs(Se);oy(Te)&&(K.current=Te)}function ke(Se){const Te=Se.relatedTarget,Le=Se.currentTarget,Ae=fs(Se);p&&Te==null&&Ae!=null&&Ze(P,Ae)&&pT(Ae),queueMicrotask(()=>{const oe=E(),me=S.context.triggerElements,pe=ue(),Ce=Te?.hasAttribute(df("focus-guard"))&&[G.current,J.current,L?.beforeInsideRef.current,L?.afterInsideRef.current,L?.beforeOutsideRef.current,L?.afterOutsideRef.current,kl(v),kl(y)].includes(Te),Ne=!(Ze(R,Te)||Ze(P,Te)||Ze(Te,P)||Ze(L?.portalNode,Te)||pe.some(be=>be===Te||Ze(be,Te))||me.hasMatchingElement(be=>Ze(be,Te))||Ce||B&&(fo(B.nodesRef.current,oe).find(be=>Ze(be.context?.elements.floating,Te)||Ze(be.context?.elements.domReference,Te))||p1(B.nodesRef.current,oe).find(be=>[be.context?.elements.floating,Jm(be.context?.elements.floating)].includes(Te)||be.context?.elements.domReference===Te)));if(Le===R&&ce&&hT(ce),f&&Le!==R&&!ah(Ae)&&ir(ee)===ee.body){if(pn(ce)&&(ce.focus(),f==="popup")){Z.request(()=>{ce.focus()});return}const be=W(),De=K.current,Ge=(De&&be.includes(De)?De:null)||be[be.length-1]||ce;pn(Ge)&&Ge.focus()}if(C.current.insideReactTree){C.current.insideReactTree=!1;return}(I||!p)&&Te&&Ne&&!$.current&&(I||Te!==mT())&&(F.current=!0,S.setOpen(!1,qe(bo,Se)))})}function le(){X.current||(C.current.insideReactTree=!0,M.start(0,()=>{C.current.insideReactTree=!1}))}const de=pn(R)?R:null;if(!(!P&&!de))return Xa(de&&St(de,"focusout",ke),de&&St(de,"pointerdown",he),P&&St(P,"focusin",te),P&&St(P,"focusout",ke),P&&L&&St(P,"focusout",le,!0))},[o,R,P,ce,p,B,L,S,h,f,W,I,E,C,M,U,Z,y,v,ue]),x.useEffect(()=>{if(o||!P||!N)return;const ee=Array.from(L?.portalNode?.querySelectorAll(`[${df("portal")}]`)||[]),te=(B?p1(B.nodesRef.current,E()):[]).find(Le=>Wv(Le.context?.elements.domReference||null))?.context?.elements.domReference,le=[...[P,...ee,G.current,J.current,L?.beforeOutsideRef.current,L?.afterOutsideRef.current,...ue()],te,kl(v),kl(y),I?R:null].filter(Le=>Le!=null),de=nT(le,{ariaHidden:p||I,mark:!1}),Se=[P,...ee].filter(Le=>Le!=null),Te=nT(Se);return()=>{Te(),de()}},[N,o,R,P,p,L,I,B,E,y,v,ue]),Me(()=>{if(!N||o||!pn(ce))return;q.current="",Q.current="";const ee=Gt(ce),he=ir(ee);queueMicrotask(()=>{const te=O.current,ke=typeof te=="function"?te(z.current||""):te;if(ke===void 0||ke===!1||Ze(ce,he))return;let de=null;const Se=()=>(de==null&&(de=W(ce)),de[0]||ce);let Te;ke===!0||ke===null?Te=Se():Te=kl(ke),Te=Te||Se();const Le=Ze(ce,ir(ee));ph(Te,{preventScroll:Te===ce,shouldFocus(){if(!H.current)return!1;if(Le)return!0;const Ae=ir(ee);return!(Ae!==Te&&Ze(ce,Ae))}})})},[o,N,ce,W,O,z,H]),Me(()=>{if(o||!ce)return;const ee=Gt(ce),he=ir(ee),te=z.current==null;pT(he);function ke(de){if(de.open||(q.current=kH(de.nativeEvent,Q.current)),de.reason===qs&&de.nativeEvent.type==="mouseleave"&&(F.current=!0),de.reason===uh)if(de.nested)F.current=!1;else if(eh(de.nativeEvent)||Jv(de.nativeEvent))F.current=!1;else{let Se=!1;Gt(ce).createElement("div").focus({get preventScroll(){return Se=!0,!1}}),Se?F.current=!1:F.current=!0}}T.on("openchange",ke);function le(de){const Se=_.current;let Te=typeof Se=="function"?Se(de):Se;if(Te===void 0||Te===!1)return null;Te===null&&(Te=!0);const Le=R?.isConnected?R:null,Ae=he?.isConnected&&Fs(he)!=="body"?he:null;let oe=te?Ae||Le:Le||Ae;return oe||(oe=mT()||null),typeof Te=="boolean"?oe:kl(Te)||oe||null}return()=>{T.off("openchange",ke);const de=ir(ee),Se=ue(),Te=Ze(P,de)||Se.some(me=>me===de||Ze(me,de))||B&&fo(B.nodesRef.current,E(),!1).some(me=>Ze(me.context?.elements.floating,de)),Le=_.current,Ae=q.current,oe=le(Ae);queueMicrotask(()=>{const me=CH(oe),pe=typeof Le!="boolean";if(Le&&!F.current&&pn(me)&&(!(!pe&&me!==de&&de!==ee.body)||Te)){const Ce={preventScroll:!0};Ae==="keyboard"&&(Ce.focusVisible=!0),me.focus(Ce)}F.current=!1})}},[o,P,ce,_,z,T,B,R,E,ue]),Me(()=>{if(!jl||N||!P)return;const ee=ir(Gt(P));!pn(ee)||!Wm(ee)||Ze(P,ee)&&ee.blur()},[N,P]),Me(()=>{if(!(o||!L))return L.setFocusManagerState({modal:p,closeOnFocusOut:h,open:N,onOpenChange:S.setOpen,domReference:R}),()=>{L.setFocusManagerState(null)}},[o,L,p,N,S,h,R]),Me(()=>{if(!(o||!ce))return hT(ce),()=>{queueMicrotask(wy)}},[o,ce]);const ve=!o&&(p?!I:!0)&&(ae||p);return s.jsxs(x.Fragment,{children:[ve&&s.jsx(au,{"data-type":"inside",ref:Y,onFocus:ee=>{if(p){const he=W();ph(he[he.length-1])}else L?.portalNode&&(F.current=!1,eu(ee,L.portalNode)?iy(R)?.focus():kl(v??L.beforeOutsideRef)?.focus())}}),a,ve&&s.jsx(au,{"data-type":"inside",ref:re,onFocus:ee=>{p?ph(W()[0]):L?.portalNode&&(h&&(F.current=!0),eu(ee,L.portalNode)?C1(R)?.focus():kl(y??L.afterOutsideRef)?.focus())}})]})}function gh(e,t={}){const{enabled:a=!0,event:o="click",toggle:c=!0,ignoreMouse:d=!1,stickIfOpen:f=!0,touchOpenDelay:p=0,reason:h=xo}=t,b="rootStore"in e?e.rootStore:e,y=b.context.dataRef,v=x.useRef(void 0),j=tu(),w=er(),k=x.useMemo(()=>{function S(R,P,T,C){const E=qe(h,P,T);R&&C==="touch"&&p>0?w.start(p,()=>{b.setOpen(!0,E)}):b.setOpen(R,E)}function N(R,P,T){const C=y.current.openEvent,E=b.select("domReferenceElement")!==P;return R&&E||!R||!c?!0:C&&f?!T(C.type):!1}return{onPointerDown(R){v.current=po(R.pointerType,!0)&&Jv(R.nativeEvent)?"virtual":R.pointerType},onMouseDown(R){const P=v.current,T=R.nativeEvent,C=b.select("open");if(R.button!==0||o==="click"||po(P,!0)&&d)return;const E=N(C,R.currentTarget,O=>O==="click"||O==="mousedown"),D=fs(T);if(Wm(D)){S(E,T,D,P);return}const I=R.currentTarget;j.request(()=>{S(E,T,I,P)})},onClick(R){if(o==="mousedown-only")return;const P=v.current;if(o==="mousedown"&&P){v.current=void 0;return}if(po(P,!0)&&d)return;const T=b.select("open"),C=N(T,R.currentTarget,E=>E==="click"||E==="mousedown"||E==="keydown"||E==="keyup");S(C,R.nativeEvent,R.currentTarget,P)},onKeyDown(){v.current=void 0}}},[y,o,d,h,b,f,c,j,w,p]);return x.useMemo(()=>a?{reference:k}:mn,[a,k])}function TH(e,t){let a=null,o=null,c=!1;return{contextElement:e||void 0,getBoundingClientRect(){const d=e?.getBoundingClientRect()||{width:0,height:0,x:0,y:0},f=t.axis==="x"||t.axis==="both",p=t.axis==="y"||t.axis==="both",h=["mouseenter","mousemove"].includes(t.dataRef.current.openEvent?.type||"")&&t.pointerType!=="touch";let b=d.width,y=d.height,v=d.x,j=d.y;return a==null&&t.x&&f&&(a=d.x-t.x),o==null&&t.y&&p&&(o=d.y-t.y),v-=a||0,j-=o||0,b=0,y=0,!c||h?(b=t.axis==="y"?d.width:0,y=t.axis==="x"?d.height:0,v=f&&t.x!=null?t.x:v,j=p&&t.y!=null?t.y:j):c&&!h&&(y=t.axis==="x"?d.height:y,b=t.axis==="y"?d.width:b),c=!0,{width:b,height:y,x:v,y:j,top:j,right:v+b,bottom:j+y,left:v}}}}function gT(e){return e!=null&&e.clientX!=null}function EH(e,t={}){const{enabled:a=!0,axis:o="both"}=t,c="rootStore"in e?e.rootStore:e,d=c.useState("open"),f=c.useState("floatingElement"),p=c.useState("domReferenceElement"),h=c.context.dataRef,b=x.useRef(!1),y=x.useRef(null),[v,j]=x.useState(),[w,k]=x.useState([]),S=Ie(C=>{c.set("positionReference",C)}),N=Ie((C,E,D)=>{b.current||h.current.openEvent&&!gT(h.current.openEvent)||c.set("positionReference",TH(D??p,{x:C,y:E,axis:o,dataRef:h,pointerType:v}))}),R=Ie(C=>{d?y.current||(N(C.clientX,C.clientY,C.currentTarget),k([])):N(C.clientX,C.clientY,C.currentTarget)}),P=po(v)?f:d;x.useEffect(()=>{if(!a){S(p);return}if(!P)return;function C(){y.current?.(),y.current=null}const E=Cn(f);function D(I){const O=fs(I);Ze(f,O)?C():N(I.clientX,I.clientY)}return!h.current.openEvent||gT(h.current.openEvent)?y.current=St(E,"mousemove",D):S(p),C},[P,a,f,h,p,c,N,S,w]),x.useEffect(()=>()=>{c.set("positionReference",null)},[c]),x.useEffect(()=>{a&&!f&&(b.current=!1)},[a,f]),x.useEffect(()=>{!a&&d&&(b.current=!0)},[a,d]);const T=x.useMemo(()=>{function C(E){j(E.pointerType)}return{onPointerDown:C,onPointerEnter:C,onMouseMove:R,onMouseEnter:R}},[R]);return x.useMemo(()=>a?{reference:T,trigger:T}:{},[a,T])}function AH(){return!1}function RH(e){return{escapeKey:typeof e=="boolean"?e:e?.escapeKey??!1,outsidePress:typeof e=="boolean"?e:e?.outsidePress??!0}}function pf(e,t={}){const{enabled:a=!0,escapeKey:o=!0,outsidePress:c=!0,outsidePressEvent:d="sloppy",referencePress:f=AH,bubbles:p,externalTree:h}=t,b="rootStore"in e?e.rootStore:e,y=b.useState("open"),v=b.useState("floatingElement"),{dataRef:j,events:w}=b.context,k=Bi(h),S=Ie(typeof c=="function"?c:()=>!1),N=typeof c=="function"?S:c,R=N!==!1,P=Ie(()=>d),{escapeKey:T,outsidePress:C}=RH(p),E=x.useRef(!1),D=x.useRef(!1),I=x.useRef(!1),O=x.useRef(!1),_=x.useRef(!1),z=x.useRef(""),H=x.useRef(null),B=er(),L=er(),F=Ie(()=>{L.clear(),j.current.insideReactTree=!1}),$=Ie(M=>{const U=j.current.floatingContext?.nodeId;return(k?fo(k.nodesRef.current,U):[]).some(ae=>ae.context?.open&&!ae.context.dataRef.current[M])}),X=Ie(M=>Zv(M,b.select("floatingElement"))||Zv(M,b.select("domReferenceElement"))),K=Ie(M=>{f()&&b.setOpen(!1,qe(xo,M.nativeEvent))}),q=Ie(M=>{if(!y||!a||!o||M.key!=="Escape"||_.current||!T&&$("__escapeKeyBubbles"))return;const U=e4(M)?M.nativeEvent:M,Z=qe(su,U);b.setOpen(!1,Z),Z.isCanceled||M.preventDefault(),!T&&!Z.isPropagationAllowed&&M.stopPropagation()}),Q=Ie(()=>{j.current.insideReactTree=!0,L.start(0,F)}),G=Ie(M=>{if(!y||!a||M.button!==0)return;const U=fs(M.nativeEvent);Ze(b.select("floatingElement"),U)&&(E.current||(E.current=!0,D.current=!1))}),J=Ie(M=>{!y||!a||(M.defaultPrevented||M.nativeEvent.defaultPrevented)&&E.current&&(D.current=!0)});x.useEffect(()=>{function M(U){U.open||(O.current=!1)}return w.on("openchange",M),()=>{w.off("openchange",M)}},[w]),x.useEffect(()=>{if(!y||!a)return y||(O.current=!1),F;j.current.__escapeKeyBubbles=T,j.current.__outsidePressBubbles=C;const M=new la,U=new la,Z=Gt(v);function ae(){M.clear(),_.current=!0}function ce(){M.start(jl?5:0,()=>{_.current=!1})}function W(){I.current=!0,U.start(0,()=>{I.current=!1})}function ue(){E.current=!1,D.current=!1}function ve(){const Ne=z.current,be=Ne==="pen"||!Ne?"mouse":Ne,De=P(),Ge=typeof De=="function"?De():De;return typeof Ge=="string"?Ge:Ge[be]}function ee(Ne){const be=ve();return be==="intentional"&&Ne.type!=="click"||be==="sloppy"&&Ne.type==="click"}function he(Ne){const be=j.current.floatingContext?.nodeId,De=k&&fo(k.nodesRef.current,be).some(Ge=>Zv(Ne,Ge.context?.elements.floating));return X(Ne)||De}function te(Ne){if(ee(Ne)){Ne.type!=="click"&&!X(Ne)&&(U.clear(),I.current=!1),F();return}if(j.current.insideReactTree){F();return}const be=fs(Ne),De=`[${df("inert")}]`,Ge=Rt(be)?be.getRootNode():null,Ct=Array.from((Kc(Ge)?Ge:Gt(b.select("floatingElement"))).querySelectorAll(De)),Tt=b.context.triggerElements;if(be&&(Tt.hasElement(be)||Tt.hasMatchingElement(ot=>Ze(ot,be))))return;let Mt=Rt(be)?be:null;for(;Mt&&!ao(Mt);){const ot=lo(Mt);if(ao(ot)||!Rt(ot))break;Mt=ot}if(!(Ct.length&&Rt(be)&&!ZB(be)&&!Ze(be,b.select("floatingElement"))&&Ct.every(ot=>!Ze(Mt,ot)))){if(pn(be)&&!("touches"in Ne)){const ot=ao(be),Kn=jr(be),ms=/auto|scroll/,Yn=ot||ms.test(Kn.overflowX),vs=ot||ms.test(Kn.overflowY),it=Yn&&be.clientWidth>0&&be.scrollWidth>be.clientWidth,$t=vs&&be.clientHeight>0&&be.scrollHeight>be.clientHeight,Vn=Kn.direction==="rtl",rn=$t&&(Vn?Ne.offsetX<=be.offsetWidth-be.clientWidth:Ne.offsetX>be.clientWidth),nt=it&&Ne.offsetY>be.clientHeight;if(rn||nt)return}if(!he(Ne)){if(ve()==="intentional"){if(Ne.detail!==0&&!eh(Ne)&&!O.current)return;if(I.current){U.clear(),I.current=!1;return}}typeof N=="function"&&!N(Ne)||$("__outsidePressBubbles")||(b.setOpen(!1,qe(uh,Ne)),F())}}}function ke(Ne){ve()!=="sloppy"||Ne.pointerType==="touch"||!b.select("open")||!a||X(Ne)||te(Ne)}function le(Ne){if(ve()!=="sloppy"||!b.select("open")||!a||X(Ne))return;const be=Ne.touches[0];be&&(H.current={startTime:Date.now(),startX:be.clientX,startY:be.clientY,dismissOnTouchEnd:!1,dismissOnMouseDown:!0},B.start(1e3,()=>{H.current&&(H.current.dismissOnTouchEnd=!1,H.current.dismissOnMouseDown=!1)}))}function de(Ne,be){const De=fs(Ne);if(!De)return;const Ge=St(De,Ne.type,()=>{be(Ne),Ge()})}function Se(Ne){z.current="touch",de(Ne,le)}function Te(Ne){B.clear(),Ne.type==="pointerdown"&&(Ne.button===0&&(O.current=!0),z.current=Ne.pointerType),!(Ne.type==="mousedown"&&H.current&&!H.current.dismissOnMouseDown)&&de(Ne,be=>{be.type==="pointerdown"?ke(be):te(be)})}function Le(Ne){if(Ne.type==="pointercancel"&&(O.current=!1),!E.current)return;const be=D.current;if(ue(),ve()==="intentional"){if(Ne.type==="pointercancel"){be&&W();return}if(!he(Ne)){if(be){W();return}typeof N=="function"&&!N(Ne)||(U.clear(),I.current=!0,F())}}}function Ae(Ne){if(ve()!=="sloppy"||!H.current||X(Ne))return;const be=Ne.touches[0];if(!be)return;const De=Math.abs(be.clientX-H.current.startX),Ge=Math.abs(be.clientY-H.current.startY),Ct=Math.sqrt(De*De+Ge*Ge);Ct>5&&(H.current.dismissOnTouchEnd=!0),Ct>10&&(te(Ne),B.clear(),H.current=null)}function oe(Ne){de(Ne,Ae)}function me(Ne){ve()!=="sloppy"||!H.current||X(Ne)||(H.current.dismissOnTouchEnd&&te(Ne),B.clear(),H.current=null)}function pe(Ne){de(Ne,me)}const Ce=Xa(o&&Xa(St(Z,"keydown",q),St(Z,"compositionstart",ae),St(Z,"compositionend",ce)),R&&Xa(St(Z,"click",Te,!0),St(Z,"pointerdown",Te,!0),St(Z,"pointerup",Le,!0),St(Z,"pointercancel",Le,!0),St(Z,"mousedown",Te,!0),St(Z,"mouseup",Le,!0),St(Z,"touchstart",Se,{capture:!0,passive:!0}),St(Z,"touchmove",oe,{capture:!0,passive:!0}),St(Z,"touchend",pe,{capture:!0,passive:!0})));return()=>{Ce(),M.clear(),U.clear(),ue(),I.current=!1,F()}},[j,v,o,R,N,y,a,T,C,q,F,P,$,X,k,b,B]);const Y=x.useMemo(()=>({onKeyDown:q,onPointerDown:K,onClick:K}),[q,K]),re=x.useMemo(()=>({onKeyDown:q,onPointerDown:J,onMouseDown:J,onClickCapture:Q,onMouseDownCapture(M){Q(),G(M)},onPointerDownCapture(M){Q(),G(M)},onMouseUpCapture:Q,onTouchEndCapture:Q,onTouchMoveCapture:Q}),[q,Q,G,J]);return x.useMemo(()=>a?{reference:Y,floating:re,trigger:Y}:{},[a,Y,re])}function xT(e,t,a){let{reference:o,floating:c}=e;const d=aa(t),f=ny(t),p=ty(f),h=ra(t),b=d==="y",y=o.x+o.width/2-c.width/2,v=o.y+o.height/2-c.height/2,j=o[p]/2-c[p]/2;let w;switch(h){case"top":w={x:y,y:o.y-c.height};break;case"bottom":w={x:y,y:o.y+o.height};break;case"right":w={x:o.x+o.width,y:v};break;case"left":w={x:o.x-c.width,y:v};break;default:w={x:o.x,y:o.y}}const k=Nl(t);return k&&(w[f]+=j*(k==="end"?1:-1)*(a&&b?-1:1)),w}async function OH(e,t){var a;t===void 0&&(t={});const{x:o,y:c,platform:d,rects:f,elements:p,strategy:h}=e,{boundary:b="clippingAncestors",rootBoundary:y="viewport",elementContext:v="floating",altBoundary:j=!1,padding:w=0}=mo(t,e),k=x1(w),N=p[j?v==="floating"?"reference":"floating":v],R=nf(await d.getClippingRect({element:(a=await(d.isElement==null?void 0:d.isElement(N)))==null||a?N:N.contextElement||await(d.getDocumentElement==null?void 0:d.getDocumentElement(p.floating)),boundary:b,rootBoundary:y,strategy:h})),P=v==="floating"?{x:o,y:c,width:f.floating.width,height:f.floating.height}:f.reference,T=await(d.getOffsetParent==null?void 0:d.getOffsetParent(p.floating)),C=await(d.isElement==null?void 0:d.isElement(T))&&await(d.getScale==null?void 0:d.getScale(T))||{x:1,y:1},E=nf(d.convertOffsetParentRelativeRectToViewportRelativeRect?await d.convertOffsetParentRelativeRectToViewportRelativeRect({elements:p,rect:P,offsetParent:T,strategy:h}):P);return{top:(R.top-E.top+k.top)/C.y,bottom:(E.bottom-R.bottom+k.bottom)/C.y,left:(R.left-E.left+k.left)/C.x,right:(E.right-R.right+k.right)/C.x}}const MH=50,DH=async(e,t,a)=>{const{placement:o="bottom",strategy:c="absolute",middleware:d=[],platform:f}=a,p=f.detectOverflow?f:{...f,detectOverflow:OH},h=await(f.isRTL==null?void 0:f.isRTL(t));let b=await f.getElementRects({reference:e,floating:t,strategy:c}),{x:y,y:v}=xT(b,o,h),j=o,w=0;const k={};for(let S=0;SF<=0)){var H,B;const F=(((H=d.flip)==null?void 0:H.index)||0)+1,$=I[F];if($&&(!(v==="alignment"?P!==aa($):!1)||z.every(q=>aa(q.placement)===P?q.overflows[0]>0:!0)))return{data:{index:F,overflows:z},reset:{placement:$}};let X=(B=z.filter(K=>K.overflows[0]<=0).sort((K,q)=>K.overflows[1]-q.overflows[1])[0])==null?void 0:B.placement;if(!X)switch(w){case"bestFit":{var L;const K=(L=z.filter(q=>{if(D){const Q=aa(q.placement);return Q===P||Q==="y"}return!0}).map(q=>[q.placement,q.overflows.filter(Q=>Q>0).reduce((Q,G)=>Q+G,0)]).sort((q,Q)=>q[1]-Q[1])[0])==null?void 0:L[0];K&&(X=K);break}case"initialPlacement":X=p;break}if(c!==X)return{reset:{placement:X}}}return{}}}},bT=new Set(["left","top"]);async function PH(e,t){const{placement:a,platform:o,elements:c}=e,d=await(o.isRTL==null?void 0:o.isRTL(c.floating)),f=ra(a),p=Nl(a),h=aa(a)==="y",b=bT.has(f)?-1:1,y=d&&h?-1:1,v=mo(t,e);let{mainAxis:j,crossAxis:w,alignmentAxis:k}=typeof v=="number"?{mainAxis:v,crossAxis:0,alignmentAxis:null}:{mainAxis:v.mainAxis||0,crossAxis:v.crossAxis||0,alignmentAxis:v.alignmentAxis};return p&&typeof k=="number"&&(w=p==="end"?k*-1:k),h?{x:w*y,y:j*b}:{x:j*b,y:w*y}}const _H=function(e){return e===void 0&&(e=0),{name:"offset",options:e,async fn(t){var a,o;const{x:c,y:d,placement:f,middlewareData:p}=t,h=await PH(t,e);return f===((a=p.offset)==null?void 0:a.placement)&&(o=p.arrow)!=null&&o.alignmentOffset?{}:{x:c+h.x,y:d+h.y,data:{...h,placement:f}}}}},LH=function(e){return e===void 0&&(e={}),{name:"shift",options:e,async fn(t){const{x:a,y:o,placement:c,platform:d}=t,{mainAxis:f=!0,crossAxis:p=!1,limiter:h={fn:P=>{let{x:T,y:C}=P;return{x:T,y:C}}},...b}=mo(e,t),y={x:a,y:o},v=await d.detectOverflow(t,b),j=aa(c),w=ey(j);let k=y[w],S=y[j];const N=(P,T)=>m1(T+v[P==="y"?"top":"left"],T,T-v[P==="y"?"bottom":"right"]);f&&(k=N(w,k)),p&&(S=N(j,S));const R=h.fn({...t,[w]:k,[j]:S});return{...R,data:{x:R.x-a,y:R.y-o,enabled:{[w]:f,[j]:p}}}}}},zH=function(e){return e===void 0&&(e={}),{options:e,fn(t){var a,o;const{x:c,y:d,placement:f,rects:p,middlewareData:h}=t,{offset:b=0,mainAxis:y=!0,crossAxis:v=!0}=mo(e,t),j={x:c,y:d},w=aa(f),k=ey(w);let S=j[k],N=j[w];const R=mo(b,t),P=typeof R=="number"?{mainAxis:R,crossAxis:0}:{mainAxis:(a=R.mainAxis)!=null?a:0,crossAxis:(o=R.crossAxis)!=null?o:0};if(y){const E=k==="y"?"height":"width",D=p.reference[k]-p.floating[E]+P.mainAxis,I=p.reference[k]+p.reference[E]-P.mainAxis;SI&&(S=I)}if(v){var T,C;const E=k==="y"?"width":"height",D=bT.has(ra(f)),I=p.reference[w]-p.floating[E]+(D&&((T=h.offset)==null?void 0:T[w])||0)+(D?0:P.crossAxis),O=p.reference[w]+p.reference[E]+(D?0:((C=h.offset)==null?void 0:C[w])||0)-(D?P.crossAxis:0);NO&&(N=O)}return{[k]:S,[w]:N}}}},BH=function(e){return e===void 0&&(e={}),{name:"size",options:e,async fn(t){const{placement:a,rects:o,platform:c,elements:d}=t,{apply:f=()=>{},...p}=mo(e,t),h=await c.detectOverflow(t,p),b=ra(a),y=Nl(a),v=aa(a)==="y",{width:j,height:w}=o.floating;let k,S;b==="top"||b==="bottom"?(k=b,S=y===(await(c.isRTL==null?void 0:c.isRTL(d.floating))?"start":"end")?"left":"right"):(S=b,k=y==="end"?"top":"bottom");const N=w-h.top-h.bottom,R=j-h.left-h.right,P=Jc(w-h[k],N),T=Jc(j-h[S],R),C=t.middlewareData.shift,E=!C;let D=P,I=T;C!=null&&C.enabled.x&&(I=R),C!=null&&C.enabled.y&&(D=N),E&&!y&&(v?I=j-2*wl(h.left,h.right):D=w-2*wl(h.top,h.bottom)),await f({...t,availableWidth:I,availableHeight:D});const O=await c.getDimensions(d.floating);return j!==O.width||w!==O.height?{reset:{rects:!0}}:{}}}};function vT(e){const t=jr(e);let a=parseFloat(t.width)||0,o=parseFloat(t.height)||0;const c=pn(e),d=c?e.offsetWidth:a,f=c?e.offsetHeight:o,p=th(a)!==d||th(o)!==f;return p&&(a=d,o=f),{width:a,height:o,$:p}}function Sy(e){return Rt(e)?e:e.contextElement}function ou(e){const t=Sy(e);if(!pn(t))return Sl(1);const a=t.getBoundingClientRect(),{width:o,height:c,$:d}=vT(t);let f=(d?th(a.width):a.width)/o,p=(d?th(a.height):a.height)/c;return(!f||!Number.isFinite(f))&&(f=1),(!p||!Number.isFinite(p))&&(p=1),{x:f,y:p}}const HH=Sl(0);function yT(e){const t=Cn(e);return!Rv()||!t.visualViewport?HH:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function UH(e,t,a){return t===void 0&&(t=!1),!!a&&t&&a===Cn(e)}function Hi(e,t,a,o){t===void 0&&(t=!1),a===void 0&&(a=!1);const c=e.getBoundingClientRect(),d=Sy(e);let f=Sl(1);t&&(o?Rt(o)&&(f=ou(o)):f=ou(e));const p=UH(d,a,o)?yT(d):Sl(0);let h=(c.left+p.x)/f.x,b=(c.top+p.y)/f.y,y=c.width/f.x,v=c.height/f.y;if(d&&o){const j=Cn(d),w=Rt(o)?Cn(o):o;let k=j,S=Ov(k);for(;S&&w!==k;){const N=ou(S),R=S.getBoundingClientRect(),P=jr(S),T=R.left+(S.clientLeft+parseFloat(P.paddingLeft))*N.x,C=R.top+(S.clientTop+parseFloat(P.paddingTop))*N.y;h*=N.x,b*=N.y,y*=N.x,v*=N.y,h+=T,b+=C,k=Cn(S),S=Ov(k)}}return nf({width:y,height:v,x:h,y:b})}function xh(e,t){const a=Vm(e).scrollLeft;return t?t.left+a:Hi(bl(e)).left+a}function jT(e,t){const a=e.getBoundingClientRect(),o=a.left+t.scrollLeft-xh(e,a),c=a.top+t.scrollTop;return{x:o,y:c}}function VH(e){let{elements:t,rect:a,offsetParent:o,strategy:c}=e;const d=c==="fixed",f=bl(o),p=t?Um(t.floating):!1;if(o===f||p&&d)return a;let h={scrollLeft:0,scrollTop:0},b=Sl(1);const y=Sl(0),v=pn(o);if((v||!d)&&((Fs(o)!=="body"||Qd(f))&&(h=Vm(o)),v)){const w=Hi(o);b=ou(o),y.x=w.x+o.clientLeft,y.y=w.y+o.clientTop}const j=f&&!v&&!d?jT(f,h):Sl(0);return{width:a.width*b.x,height:a.height*b.y,x:a.x*b.x-h.scrollLeft*b.x+y.x+j.x,y:a.y*b.y-h.scrollTop*b.y+y.y+j.y}}function FH(e){return e.getClientRects?Array.from(e.getClientRects()):[]}function $H(e){const t=Vm(e),a=e.ownerDocument.body,o=wl(e.scrollWidth,e.clientWidth,a.scrollWidth,a.clientWidth),c=wl(e.scrollHeight,e.clientHeight,a.scrollHeight,a.clientHeight);let d=-t.scrollLeft+xh(e);const f=-t.scrollTop;return jr(a).direction==="rtl"&&(d+=wl(e.clientWidth,a.clientWidth)-o),{width:o,height:c,x:d,y:f}}const qH=25;function GH(e,t,a){a===void 0&&(a="viewport");const o=a==="layoutViewport",c=Cn(e),d=bl(e),f=c.visualViewport;let p=d.clientWidth,h=d.clientHeight,b=0,y=0;if(f){const j=!Rv()||t==="fixed";o?j||(b=-f.offsetLeft,y=-f.offsetTop):(p=f.width,h=f.height,j&&(b=f.offsetLeft,y=f.offsetTop))}if(xh(d)<=0){const j=d.ownerDocument,w=j.body,k=getComputedStyle(w),S=j.compatMode==="CSS1Compat"&&parseFloat(k.marginLeft)+parseFloat(k.marginRight)||0,N=Math.abs(d.clientWidth-w.clientWidth-S),R=getComputedStyle(d).scrollbarGutter==="stable both-edges"?N/2:N;R<=qH&&(p-=R)}return{width:p,height:h,x:b,y}}function KH(e,t){const a=Hi(e,!0,t==="fixed"),o=a.top+e.clientTop,c=a.left+e.clientLeft,d=ou(e),f=e.clientWidth*d.x,p=e.clientHeight*d.y,h=c*d.x,b=o*d.y;return{width:f,height:p,x:h,y:b}}function wT(e,t,a){let o;if(t==="viewport"||t==="layoutViewport")o=GH(e,a,t);else if(t==="document")o=$H(bl(e));else if(Rt(t))o=KH(t,a);else{const c=yT(e);o={x:t.x-c.x,y:t.y-c.y,width:t.width,height:t.height}}return nf(o)}function YH(e,t){const a=t.get(e);if(a)return a;let o=Yc(e,[],!1).filter(p=>Rt(p)&&Fs(p)!=="body"),c=null;const d=jr(e).position==="fixed";let f=d?lo(e):e;for(;Rt(f)&&!ao(f);){const p=jr(f),h=Av(f),b=c?c.position:d?"fixed":"";!h&&(b==="fixed"||b==="absolute"&&p.position==="static")?o=o.filter(v=>v!==f):c=p,f=lo(f)}return t.set(e,o),o}function XH(e){let{element:t,boundary:a,rootBoundary:o,strategy:c}=e;const f=[...a==="clippingAncestors"?Um(t)?[]:YH(t,this._c):[].concat(a),o],p=wT(t,f[0],c);let h=p.top,b=p.right,y=p.bottom,v=p.left;for(let j=1;j{p(!1,1e-7)},1e3)}I=!1}try{o=new IntersectionObserver(O,{...D,root:d.ownerDocument})}catch{o=new IntersectionObserver(O,D)}o.observe(e)}const h=Cn(e),b=()=>p(a);return h.addEventListener("resize",b),p(!0),()=>{h.removeEventListener("resize",b),f()}}function TT(e,t,a,o){o===void 0&&(o={});const{ancestorScroll:c=!0,ancestorResize:d=!0,elementResize:f=typeof ResizeObserver=="function",layoutShift:p=typeof IntersectionObserver=="function",animationFrame:h=!1}=o,b=Sy(e),y=c||d?[...b?Yc(b):[],...t?Yc(t):[]]:[];y.forEach(R=>{c&&R.addEventListener("scroll",a),d&&R.addEventListener("resize",a)});const v=b&&p?eU(b,a,d):null;let j=-1,w=null;f&&(w=new ResizeObserver(R=>{let[P]=R;P&&P.target===b&&w&&t&&(w.unobserve(t),cancelAnimationFrame(j),j=requestAnimationFrame(()=>{var T;(T=w)==null||T.observe(t)})),a()}),b&&!h&&w.observe(b),t&&w.observe(t));let k,S=h?Hi(e):null;h&&N();function N(){const R=Hi(e);S&&!CT(S,R)&&a(),S=R,k=requestAnimationFrame(N)}return a(),()=>{var R;y.forEach(P=>{c&&P.removeEventListener("scroll",a),d&&P.removeEventListener("resize",a)}),v?.(),(R=w)==null||R.disconnect(),w=null,h&&cancelAnimationFrame(k)}}const tU=_H,nU=LH,sU=IH,rU=BH,aU=zH,lU=(e,t,a)=>{const o=new Map,c=a??{},d={...kT,...c.platform,_c:o};return DH(e,t,{...c,platform:d})};var oU=typeof document<"u",iU=function(){},bh=oU?x.useLayoutEffect:iU;function vh(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(typeof e=="function"&&e.toString()===t.toString())return!0;let a,o,c;if(e&&t&&typeof e=="object"){if(Array.isArray(e)){if(a=e.length,a!==t.length)return!1;for(o=a;o--!==0;)if(!vh(e[o],t[o]))return!1;return!0}if(c=Object.keys(e),a=c.length,a!==Object.keys(t).length)return!1;for(o=a;o--!==0;)if(!{}.hasOwnProperty.call(t,c[o]))return!1;for(o=a;o--!==0;){const d=c[o];if(!(d==="_owner"&&e.$$typeof)&&!vh(e[d],t[d]))return!1}return!0}return e!==e&&t!==t}function ET(e){return typeof window>"u"?1:(e.ownerDocument.defaultView||window).devicePixelRatio||1}function AT(e,t){const a=ET(e);return Math.round(t*a)/a}function ky(e){const t=x.useRef(e);return bh(()=>{t.current=e}),t}function cU(e){e===void 0&&(e={});const{placement:t="bottom",strategy:a="absolute",middleware:o=[],platform:c,elements:{reference:d,floating:f}={},transform:p=!0,whileElementsMounted:h,open:b}=e,[y,v]=x.useState({x:0,y:0,strategy:a,placement:t,middlewareData:{},isPositioned:!1}),[j,w]=x.useState(o);vh(j,o)||w(o);const[k,S]=x.useState(null),[N,R]=x.useState(null),P=x.useCallback(q=>{q!==D.current&&(D.current=q,S(q))},[]),T=x.useCallback(q=>{q!==I.current&&(I.current=q,R(q))},[]),C=d||k,E=f||N,D=x.useRef(null),I=x.useRef(null),O=x.useRef(y),_=h!=null,z=ky(h),H=ky(c),B=ky(b),L=x.useCallback(()=>{if(!D.current||!I.current)return;const q={placement:t,strategy:a,middleware:j};H.current&&(q.platform=H.current),lU(D.current,I.current,q).then(Q=>{const G={...Q,isPositioned:B.current!==!1};F.current&&!vh(O.current,G)&&(O.current=G,Ts.flushSync(()=>{v(G)}))})},[j,t,a,H,B]);bh(()=>{b===!1&&O.current.isPositioned&&(O.current.isPositioned=!1,v(q=>({...q,isPositioned:!1})))},[b]);const F=x.useRef(!1);bh(()=>(F.current=!0,()=>{F.current=!1}),[]),bh(()=>{if(C&&(D.current=C),E&&(I.current=E),C&&E){if(z.current)return z.current(C,E,L);L()}},[C,E,L,z,_]);const $=x.useMemo(()=>({reference:D,floating:I,setReference:P,setFloating:T}),[P,T]),X=x.useMemo(()=>({reference:C,floating:E}),[C,E]),K=x.useMemo(()=>{const q={position:a,left:0,top:0};if(!X.floating)return q;const Q=AT(X.floating,y.x),G=AT(X.floating,y.y);return p?{...q,transform:"translate("+Q+"px, "+G+"px)",...ET(X.floating)>=1.5&&{willChange:"transform"}}:{position:a,left:Q,top:G}},[a,p,X.floating,y.x,y.y]);return x.useMemo(()=>({...y,update:L,refs:$,elements:X,floatingStyles:K}),[y,L,$,X,K])}const uU=(e,t)=>{const a=tU(e);return{name:a.name,fn:a.fn,options:[e,t]}},dU=(e,t)=>{const a=nU(e);return{name:a.name,fn:a.fn,options:[e,t]}},fU=(e,t)=>({fn:aU(e).fn,options:[e,t]}),pU=(e,t)=>{const a=sU(e);return{name:a.name,fn:a.fn,options:[e,t]}},mU=(e,t)=>{const a=rU(e);return{name:a.name,fn:a.fn,options:[e,t]}};var Cy={exports:{}},Ty={};var RT;function hU(){if(RT)return Ty;RT=1;var e=Xd();function t(v,j){return v===j&&(v!==0||1/v===1/j)||v!==v&&j!==j}var a=typeof Object.is=="function"?Object.is:t,o=e.useState,c=e.useEffect,d=e.useLayoutEffect,f=e.useDebugValue;function p(v,j){var w=j(),k=o({inst:{value:w,getSnapshot:j}}),S=k[0].inst,N=k[1];return d(function(){S.value=w,S.getSnapshot=j,h(S)&&N({inst:S})},[v,w,j]),c(function(){return h(S)&&N({inst:S}),v(function(){h(S)&&N({inst:S})})},[v]),f(w),w}function h(v){var j=v.getSnapshot;v=v.value;try{var w=j();return!a(v,w)}catch{return!0}}function b(v,j){return j()}var y=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?b:p;return Ty.useSyncExternalStore=e.useSyncExternalStore!==void 0?e.useSyncExternalStore:y,Ty}var OT;function MT(){return OT||(OT=1,Cy.exports=hU()),Cy.exports}var Ey=MT(),Ay={exports:{}},Ry={};var DT;function gU(){if(DT)return Ry;DT=1;var e=Xd(),t=MT();function a(b,y){return b===y&&(b!==0||1/b===1/y)||b!==b&&y!==y}var o=typeof Object.is=="function"?Object.is:a,c=t.useSyncExternalStore,d=e.useRef,f=e.useEffect,p=e.useMemo,h=e.useDebugValue;return Ry.useSyncExternalStoreWithSelector=function(b,y,v,j,w){var k=d(null);if(k.current===null){var S={hasValue:!1,value:null};k.current=S}else S=k.current;k=p(function(){function R(D){if(!P){if(P=!0,T=D,D=j(D),w!==void 0&&S.hasValue){var I=S.value;if(w(I,D))return C=I}return C=D}if(I=C,o(T,D))return I;var O=j(D);return w!==void 0&&w(I,O)?(T=D,I):(T=D,C=O)}var P=!1,T,C,E=v===void 0?null:v;return[function(){return R(y())},E===null?void 0:function(){return R(E())}]},[y,v,j,w]);var N=c(b,k[0],k[1]);return f(function(){S.hasValue=!0,S.value=N},[N]),h(N),N},Ry}var IT;function xU(){return IT||(IT=1,Ay.exports=gU()),Ay.exports}var bU=xU();const vU=zv(19)?jU:wU;function PT(e,t,a,o,c){return vU(e,t,a,o,c)}function yU(e,t,a,o,c){const d=x.useCallback(()=>t(e.getSnapshot(),a,o,c),[e,t,a,o,c]);return Ey.useSyncExternalStore(e.subscribe,d,d)}oH({before(e){e.syncIndex=0,e.didInitialize||(e.syncTick=1,e.syncHooks=[],e.didChangeStore=!0,e.getSnapshot=()=>{let t=!1;for(let a=0;a0&&(e.didChangeStore&&(e.didChangeStore=!1,e.subscribe=t=>{const a=new Set;for(const c of e.syncHooks)a.add(c.store);const o=[];for(const c of a)o.push(c.subscribe(t));return()=>{for(const c of o)c()}}),Ey.useSyncExternalStore(e.subscribe,e.getSnapshot,e.getSnapshot))}});function jU(e,t,a,o,c){const d=lH();if(!d)return yU(e,t,a,o,c);const f=d.syncIndex;d.syncIndex+=1;let p;return d.didInitialize?(p=d.syncHooks[f],(p.store!==e||p.selector!==t||!Object.is(p.a1,a)||!Object.is(p.a2,o)||!Object.is(p.a3,c))&&(p.store!==e&&(d.didChangeStore=!0),p.store=e,p.selector=t,p.a1=a,p.a2=o,p.a3=c,p.value=t(e.getSnapshot(),a,o,c))):(p={store:e,selector:t,a1:a,a2:o,a3:c,value:t(e.getSnapshot(),a,o,c)},d.syncHooks.push(p)),p.value}function wU(e,t,a,o,c){return bU.useSyncExternalStoreWithSelector(e.subscribe,e.getSnapshot,e.getSnapshot,d=>t(d,a,o,c))}class SU{constructor(t){cn(this,"subscribe",t=>(this.listeners.add(t),()=>{this.listeners.delete(t)}));cn(this,"getSnapshot",()=>this.state);this.state=t,this.listeners=new Set,this.updateTick=0}static create(t){return new this(t)}setState(t){if(this.state===t)return;this.state=t,this.updateTick+=1;const a=this.updateTick;for(const o of this.listeners){if(a!==this.updateTick)return;o(t)}}update(t){for(const a in t)if(!Object.is(this.state[a],t[a])){this.setState({...this.state,...t});return}}set(t,a){Object.is(this.state[t],a)||this.setState({...this.state,[t]:a})}notifyAll(){const t={...this.state};this.setState(t)}use(t,a,o,c){return PT(this,t,a,o,c)}}class iu extends SU{constructor(t,a={},o){super(t),this.context=a,this.selectors=o}useSyncedValue(t,a){x.useDebugValue(t);const o=this;Me(()=>{o.state[t]!==a&&o.set(t,a)},[o,t,a])}useSyncedValueWithCleanup(t,a){const o=this;Me(()=>(o.state[t]!==a&&o.set(t,a),()=>{o.set(t,void 0)}),[o,t,a])}useSyncedValues(t){const a=this,o=Object.values(t);Me(()=>{a.update(t)},[a,...o])}useControlledProp(t,a){x.useDebugValue(t);const o=this,c=a!==void 0;Me(()=>{c&&!Object.is(o.state[t],a)&&o.setState({...o.state,[t]:a})},[o,t,a,c])}select(t,a,o,c){const d=this.selectors[t];return d(this.state,a,o,c)}useState(t,a,o,c){return x.useDebugValue(t),PT(this,this.selectors[t],a,o,c)}useContextCallback(t,a){x.useDebugValue(t);const o=Ie(a??Kt);this.context[t]=o}useStateSetter(t){const a=x.useRef(void 0);return a.current===void 0&&(a.current=o=>{this.set(t,o)}),a.current}observe(t,a){let o;typeof t=="function"?o=t:o=this.selectors[t];let c=o(this.state);return a(c,c,this),this.subscribe(d=>{const f=o(d);if(!Object.is(c,f)){const p=c;c=f,a(f,p,this)}})}}const NU={open:e=>e.open,transitionStatus:e=>e.transitionStatus,domReferenceElement:e=>e.domReferenceElement,referenceElement:e=>e.positionReference??e.referenceElement,floatingElement:e=>e.floatingElement,floatingId:e=>e.floatingId};class Oy extends iu{constructor(a){const{syncOnly:o,nested:c,onOpenChange:d,triggerElements:f,...p}=a;super({...p,positionReference:p.referenceElement,domReferenceElement:p.referenceElement},{onOpenChange:d,dataRef:{current:{}},events:cT(),nested:c,triggerElements:f},NU);cn(this,"syncOpenEvent",(a,o)=>{(!a||!this.state.open||o!=null&&t4(o))&&(this.context.dataRef.current.openEvent=a?o:void 0)});cn(this,"dispatchOpenChange",(a,o)=>{this.syncOpenEvent(a,o.event);const c={open:a,reason:o.reason,nativeEvent:o.event,nested:this.context.nested,triggerElement:o.trigger};this.context.events.emit("openchange",c)});cn(this,"setOpen",(a,o)=>{if(this.syncOnly){this.context.onOpenChange?.(a,o);return}this.dispatchOpenChange(a,o),this.context.onOpenChange?.(a,o)});this.syncOnly=o}}function kU(e){const{popupStore:t,treatPopupAsFloatingElement:a=!1,floatingRootContext:o,floatingId:c,nested:d,onOpenChange:f}=e,p=t.useState("open"),h=t.useState("activeTriggerElement"),b=t.useState(a?"popupElement":"positionerElement"),y=t.context.triggerElements,v=f,j=x.useRef(null);o===void 0&&j.current===null&&(j.current=new Oy({open:p,transitionStatus:void 0,referenceElement:h,floatingElement:b,triggerElements:y,onOpenChange:v,floatingId:c,syncOnly:!0,nested:d}));const w=o??j.current;return t.useSyncedValue("floatingId",c),Me(()=>{const k={open:p,floatingId:c,referenceElement:h,floatingElement:b};Rt(h)&&(k.domReferenceElement=h),w.state.positionReference===w.state.referenceElement&&(k.positionReference=h),w.update(k)},[p,c,h,b,w]),w.context.onOpenChange=v,w.context.nested=d,w}const mf={tabIndex:-1,[qv]:""};function _T(e){return t=>t==="touch"?e.current:!0}function My(e,t=!1){const a=Jd(),o=lu()!=null,c=Ps(()=>e(a,o)).current;return kU({popupStore:c,treatPopupAsFloatingElement:t,floatingRootContext:c.state.floatingRootContext,floatingId:a,nested:o,onOpenChange:c.setOpen}),c}function Dy({handle:e,store:t}){return Me(()=>e.attachStore(t),[e,t]),null}function LT(e){const t=e.context.triggerElements.size;e.select("open")&&e.state.triggerCount!==t&&e.set("triggerCount",t)}function CU(e,t){const a=x.useRef(null);return Ie(o=>{const c=a.current;if(c!==null){if(c.element===o&&c.store===t&&c.id===e)return;a.current=null;const d=c.store;d.context.triggerElements.getById(c.id)===c.element&&(d.context.triggerElements.delete(c.id),LT(d))}o!==null&&e!==void 0&&(a.current={store:t,id:e,element:o},t.context.triggerElements.add(e,o),LT(t))})}function Iy(e,t,a,o=!1){let c=e.preventUnmountingOnClose;t?c=!1:o&&(c=!0);const d=a?.id??null;let f=e.activeTriggerId,p=e.activeTriggerElement;return(d||t)&&(f=d,p=a??null),{open:t,preventUnmountingOnClose:c,activeTriggerId:f,activeTriggerElement:p}}function zT(e){let t=!1;return e.preventUnmountOnClose=()=>{t=!0},()=>t}function TU(e,t,a,o={}){const c=a.reason,d=c===qs,f=t&&c===ch,p=!t&&(c===xo||c===su),h=zT(a);if(e.context.onOpenChange?.(t,a),a.isCanceled)return;o.onBeforeDispatch?.(),e.state.floatingRootContext.dispatchOpenChange(t,a);const b=()=>{const y=Iy(e.state,t,a.trigger,h()),v={...o.extraState,...y};f?v.instantType="focus":p?v.instantType="dismiss":d&&(v.instantType=void 0),e.update(v)};d?Ts.flushSync(b):b()}function BT(e,t,a,o){const c=a.useState("isMountedByTrigger",e),d=CU(e,a),f=Ie(h=>{const b=a.select("open"),y=a.select("activeTriggerId");if(y===e){const v={activeTriggerElement:h,...b?o:null};a.update(v);return}if(y==null&&b){const v={activeTriggerId:e??null,activeTriggerElement:h,...o};a.update(v)}}),p=Ie(h=>{d(h),h&&f(h)});return Me(()=>(p(t.current),()=>p(null)),[p,t,a,e]),Me(()=>{if(c){const h={activeTriggerElement:t.current,...o};a.update(h)}},[c,a,t,...Object.values(o)]),{registerTrigger:p,isMountedByThisTrigger:c}}function Py(e,t={}){const{closeOnActiveTriggerUnmount:a=!1}=t,o=x.useRef(null),c=e.useState("open"),d=e.useState("triggerCount"),f=e.useState("activeTriggerId"),p=e.useState("activeTriggerElement");Me(()=>{if(!c){o.current=null,e.state.triggerCount!==0&&e.set("triggerCount",0);return}const h=e.context.triggerElements.size,b={};e.state.triggerCount!==h&&(b.triggerCount=h);const y=e.select("activeTriggerId");let v=null;if(y){const j=e.context.triggerElements.getById(y);if(j)o.current=y,j!==e.state.activeTriggerElement&&(b.activeTriggerElement=j);else{for(const[w,k]of e.context.triggerElements.entries())if(k===e.state.activeTriggerElement){b.activeTriggerId=w,b.activeTriggerElement=k,o.current=w;break}b.activeTriggerId===void 0&&(o.current===y?v=y:o.current=null)}}else o.current=null;if(!v&&!y&&h===1){const j=e.context.triggerElements.entries().next();if(!j.done){const[w,k]=j.value;b.activeTriggerId=w,b.activeTriggerElement=k,o.current=w}}(b.triggerCount!==void 0||b.activeTriggerId!==void 0||b.activeTriggerElement!==void 0)&&e.update(b),v&&a&&queueMicrotask(()=>{if(e.select("open")&&e.select("activeTriggerId")===v&&!e.context.triggerElements.getById(v)){const j=qe(Qn);e.setOpen(!1,j),j.isCanceled||e.update({activeTriggerId:null,activeTriggerElement:null})}})},[c,e,d,f,p,a])}function _y(e,t,a,o){const{mounted:c,setMounted:d,transitionStatus:f}=Oi(e,!1,!1,o),p=t.useState("preventUnmountingOnClose"),h=e?!1:p;t.useSyncedValues({mounted:c,transitionStatus:f,preventUnmountingOnClose:h});const b=Ie(()=>{d(!1),t.update({activeTriggerId:null,activeTriggerElement:null,mounted:!1,preventUnmountingOnClose:!1}),a?.(),t.context.onOpenChangeComplete?.(!1)});return oa({enabled:c&&!e&&!h,open:e,ref:t.context.popupRef,onComplete(){e||b()}}),{forceUnmount:b,transitionStatus:f}}function Ly(e,t){e.useSyncedValues(t),Me(()=>()=>{e.update({activeTriggerProps:mn,inactiveTriggerProps:mn,popupProps:mn})},[e])}function HT(e,t){Me(()=>{!t&&e.state.openMethod!==null&&e.set("openMethod",null)},[t,e]),Me(()=>()=>{e.state.openMethod!==null&&e.set("openMethod",null)},[e])}class yh{constructor(){this.idMap=new Map}add(t,a){this.idMap.set(t,a)}delete(t){this.idMap.delete(t)}hasElement(t){for(const a of this.idMap.values())if(a===t)return!0;return!1}hasMatchingElement(t){for(const a of this.idMap.values())if(t(a))return!0;return!1}getById(t){return this.idMap.get(t)}entries(){return this.idMap.entries()}elements(){return this.idMap.values()}get size(){return this.idMap.size}}function zy(e,t,a=!1){return{open:!1,openProp:void 0,mounted:!1,transitionStatus:void 0,floatingRootContext:new Oy({open:!1,transitionStatus:void 0,floatingElement:null,referenceElement:null,triggerElements:e,floatingId:t,syncOnly:!0,nested:a,onOpenChange:void 0}),floatingId:t,triggerCount:0,preventUnmountingOnClose:!1,payload:void 0,activeTriggerId:null,activeTriggerElement:null,triggerIdProp:void 0,popupElement:null,positionerElement:null,activeTriggerProps:mn,inactiveTriggerProps:mn,popupProps:mn}}const hf=e=>e.triggerIdProp??e.activeTriggerId,By=e=>e.openProp??e.open,UT=e=>(e.popupElement?.id??e.floatingId)||void 0;function VT(e,t){return t!==void 0&&By(e)&&hf(e)===t}function EU(e,t){return VT(e,t)?!0:t!==void 0&&By(e)&&hf(e)==null&&e.triggerCount===1}const Hy={open:By,mounted:e=>e.mounted,transitionStatus:e=>e.transitionStatus,floatingRootContext:e=>e.floatingRootContext,triggerCount:e=>e.triggerCount,preventUnmountingOnClose:e=>e.preventUnmountingOnClose,payload:e=>e.payload,activeTriggerId:hf,activeTriggerElement:e=>e.mounted?e.activeTriggerElement:null,popupId:UT,isTriggerActive:(e,t)=>t!==void 0&&hf(e)===t,isOpenedByTrigger:(e,t)=>VT(e,t),isMountedByTrigger:(e,t)=>t!==void 0&&hf(e)===t&&e.mounted,triggerProps:(e,t)=>t?e.activeTriggerProps:e.inactiveTriggerProps,triggerPopupId:(e,t)=>EU(e,t)?UT(e):void 0,popupProps:e=>e.popupProps,popupElement:e=>e.popupElement,positionerElement:e=>e.positionerElement};function FT(e){const t=x.useCallback(o=>e===void 0?Kt:e.subscribeStore(o),[e]),a=x.useCallback(()=>e===void 0?void 0:e.store,[e]);return Ey.useSyncExternalStore(t,a,()=>e?.serverStore)}function $T(e){const{open:t=!1,onOpenChange:a,elements:o={}}=e,c=Jd(),d=lu()!=null,f=Ps(()=>new Oy({open:t,transitionStatus:void 0,onOpenChange:a,referenceElement:o.reference??null,floatingElement:o.floating??null,triggerElements:new yh,floatingId:c,syncOnly:!1,nested:d})).current;return Me(()=>{const p={open:t,floatingId:c};o.reference!==void 0&&(p.referenceElement=o.reference,p.domReferenceElement=Rt(o.reference)?o.reference:null),o.floating!==void 0&&(p.floatingElement=o.floating),f.update(p)},[t,c,o.reference,o.floating,f]),f.context.onOpenChange=a,f.context.nested=d,f}function AU(e){return RU(e,e.rootContext)}function RU(e,t){const{nodeId:a,externalTree:o}=e,c=t.useState("referenceElement"),d=t.useState("floatingElement"),f=t.useState("domReferenceElement"),p=t.useState("open"),h=t.useState("floatingId"),[b,y]=x.useState(null),[v,j]=x.useState(void 0),[w,k]=x.useState(void 0),S=x.useRef(null),N=Bi(o),R=x.useMemo(()=>({reference:c,floating:d,domReference:f}),[c,d,f]),P=cU({...e,elements:{...R,...b&&{reference:b}}}),T=Rt(v)?v:null,C=w===void 0?t.state.floatingElement:w;t.useSyncedValue("referenceElement",v??null),t.useSyncedValue("domReferenceElement",v===void 0?f:T),t.useSyncedValue("floatingElement",C);const E=x.useCallback(H=>{const B=Rt(H)?{getBoundingClientRect:()=>H.getBoundingClientRect(),getClientRects:()=>H.getClientRects(),contextElement:H}:H;y(B),P.refs.setReference(B)},[P.refs]),D=x.useCallback(H=>{(Rt(H)||H===null)&&(S.current=H,j(H)),(Rt(P.refs.reference.current)||P.refs.reference.current===null||H!==null&&!Rt(H))&&P.refs.setReference(H)},[P.refs,j]),I=x.useCallback(H=>{k(H),P.refs.setFloating(H)},[P.refs]),O=x.useMemo(()=>({...P.refs,setReference:D,setFloating:I,setPositionReference:E,domReference:S}),[P.refs,D,I,E]),_=x.useMemo(()=>({...P.elements,domReference:f}),[P.elements,f]),z=x.useMemo(()=>({...P,dataRef:t.context.dataRef,open:p,onOpenChange:t.setOpen,events:t.context.events,floatingId:h,refs:O,elements:_,nodeId:a,rootStore:t}),[P,O,_,a,t,p,h]);return Me(()=>{f&&(S.current=f)},[f]),Me(()=>{t.context.dataRef.current.floatingContext=z;const H=N?.nodesRef.current.find(B=>B.id===a);H&&(H.context=z)}),x.useMemo(()=>({...P,context:z,refs:O,elements:_,rootStore:t}),[P,O,_,z,t])}const Uy=i1&&jl;function OU(e,t={}){const{enabled:a=!0,delay:o}=t,c="rootStore"in e?e.rootStore:e,{events:d,dataRef:f}=c.context,p=x.useRef(!1),h=x.useRef(null),b=x.useRef(!0),y=er();x.useEffect(()=>{const j=c.select("domReferenceElement");if(!a)return;const w=Cn(j);function k(){const R=c.select("domReferenceElement");!c.select("open")&&pn(R)&&R===ir(Gt(R))&&(p.current=!0,h.current=R)}function S(){b.current=!0}function N(){b.current=!1}return Xa(St(w,"blur",k),Uy&&St(w,"keydown",S,!0),Uy&&St(w,"pointerdown",N,!0))},[c,a]),x.useEffect(()=>{if(!a)return;function j(w){if(w.reason===xo||w.reason===su){const k=c.select("domReferenceElement");Rt(k)&&(h.current=k,p.current=!0)}}return d.on("openchange",j),()=>{d.off("openchange",j)}},[d,a,c]);const v=x.useMemo(()=>{function j(){p.current=!1,h.current=null}return{onMouseLeave(){j()},onFocus(w){const k=w.currentTarget;if(p.current){if(h.current===k)return;j()}const S=fs(w.nativeEvent);if(Rt(S)){if(Uy&&!w.relatedTarget){if(!b.current&&!Wm(S))return}else if(!JB(S))return}const N=Zm(w.relatedTarget,c.context.triggerElements),{nativeEvent:R,currentTarget:P}=w,T=typeof o=="function"?o():o;if(c.select("open")&&N||T===0||T===void 0){c.setOpen(!0,qe(ch,R,P));return}y.start(T,()=>{p.current||c.setOpen(!0,qe(ch,R,P))})},onBlur(w){j();const k=w.relatedTarget,S=w.nativeEvent,N=Rt(k)&&k.hasAttribute(df("focus-guard"))&&k.getAttribute("data-type")==="outside";y.start(0,()=>{const R=c.select("domReferenceElement"),P=ir(Gt(R));!k&&P===R||Ze(f.current.floatingContext?.refs.floating.current,P)||Ze(R,P)||N||Zm(k??P,c.context.triggerElements)||c.setOpen(!1,qe(ch,S))})}}},[f,o,c,y]);return x.useMemo(()=>a?{reference:v,trigger:v}:{},[a,v])}class Vy{constructor(){cn(this,"dispose",()=>{this.openChangeTimeout.clear(),this.restTimeout.clear()});cn(this,"disposeEffect",()=>this.dispose);this.pointerType=void 0,this.interactedInside=!1,this.handler=void 0,this.blockMouseMove=!0,this.performedPointerEventsMutation=!1,this.pointerEventsScopeElement=null,this.pointerEventsReferenceElement=null,this.pointerEventsFloatingElement=null,this.restTimeoutPending=!1,this.openChangeTimeout=new la,this.restTimeout=new la,this.handleCloseOptions=void 0}static create(){return new Vy}}const jh=new WeakMap;function wh(e){if(!e.performedPointerEventsMutation)return;const t=e.pointerEventsScopeElement;t&&jh.get(t)===e&&(e.pointerEventsScopeElement?.style.removeProperty("pointer-events"),e.pointerEventsReferenceElement?.style.removeProperty("pointer-events"),e.pointerEventsFloatingElement?.style.removeProperty("pointer-events"),jh.delete(t)),e.performedPointerEventsMutation=!1,e.pointerEventsScopeElement=null,e.pointerEventsReferenceElement=null,e.pointerEventsFloatingElement=null}function qT(e,t){const{scopeElement:a,referenceElement:o,floatingElement:c}=t,d=jh.get(a);d&&d!==e&&wh(d),wh(e),e.performedPointerEventsMutation=!0,e.pointerEventsScopeElement=a,e.pointerEventsReferenceElement=o,e.pointerEventsFloatingElement=c,jh.set(a,e),a.style.pointerEvents="none",o.style.pointerEvents="auto",c.style.pointerEvents="auto"}function Fy(e){const t=e.context.dataRef.current,a=Ps(()=>t.hoverInteractionState??Vy.create()).current;return t.hoverInteractionState||(t.hoverInteractionState=a),cy(t.hoverInteractionState.disposeEffect),t.hoverInteractionState}function GT(e,t={}){const{enabled:a=!0,closeDelay:o=0,nodeId:c}=t,d="rootStore"in e?e.rootStore:e,f=d.useState("open"),p=d.useState("floatingElement"),h=d.useState("domReferenceElement"),{dataRef:b}=d.context,y=Bi(),v=lu(),j=Fy(d),w=er(),k=Ie(()=>X1(b.current.openEvent?.type,j.interactedInside)),S=Ie(()=>uH(b.current.openEvent?.type)),N=Ie(()=>{wh(j)});Me(()=>{f||(j.pointerType=void 0,j.restTimeoutPending=!1,j.interactedInside=!1,N())},[f,j,N]),x.useEffect(()=>N,[N]),Me(()=>{if(a&&f&&j.handleCloseOptions?.blockPointerEvents&&S()&&Rt(h)&&p){const R=h,P=p,T=Gt(p),C=y?.nodesRef.current.find(O=>O.id===v)?.context?.elements.floating;C&&(C.style.pointerEvents="");const E=j.pointerEventsScopeElement!==P?j.pointerEventsScopeElement:null,D=C!==P?C:null,I=j.handleCloseOptions?.getScope?.()??E??D??R.closest("[data-rootownerid]")??T.body;return qT(j,{scopeElement:I,referenceElement:R,floatingElement:P}),()=>{N()}}},[a,f,h,p,j,S,y,v,N]),x.useEffect(()=>{if(!a)return;function R(){return!!(y&&v&&fo(y.nodesRef.current,v).length>0)}function P(O){const _=zi(o,"close",j.pointerType),z=()=>{d.setOpen(!1,qe(qs,O)),y?.events.emit("floating.closed",O)};_?j.openChangeTimeout.start(_,z):(j.openChangeTimeout.clear(),z())}function T(O){const _=fs(O);if(!WB(_)){j.interactedInside=!1;return}j.interactedInside=_?.closest("[aria-haspopup]")!=null}function C(){j.openChangeTimeout.clear(),w.clear(),y?.events.off("floating.closed",D),N()}function E(O){if(R()&&y){y.events.on("floating.closed",D);return}if(Zm(O.relatedTarget,d.context.triggerElements))return;const _=b.current.floatingContext?.nodeId??c,z=O.relatedTarget;if(!(y&&_&&Rt(z)&&fo(y.nodesRef.current,_,!1).some(B=>Ze(B.context?.elements.floating,z)))){if(j.handler){j.handler(O);return}N(),S()&&!k()&&P(O)}}function D(O){!y||!v||R()||w.start(0,()=>{y.events.off("floating.closed",D),d.setOpen(!1,qe(qs,O)),y.events.emit("floating.closed",O)})}const I=p;return Xa(I&&St(I,"mouseenter",C),I&&St(I,"mouseleave",E),I&&St(I,"pointerdown",T,!0),()=>{y?.events.off("floating.closed",D)})},[a,p,d,b,o,c,S,k,N,j,y,v,w])}const MU={current:null};function KT(e,t={}){const{enabled:a=!0,delay:o=0,handleClose:c=null,mouseOnly:d=!1,restMs:f=0,move:p=!0,triggerElementRef:h=MU,externalTree:b,isActiveTrigger:y=!0,getHandleCloseContext:v,isClosing:j,shouldOpen:w,guardStaleOpen:k=!1}=t,S="rootStore"in e?e.rootStore:e,{dataRef:N,events:R}=S.context,P=Bi(b),T=Fy(S),C=x.useRef(!1),E=Wn(c),D=Wn(o),I=Wn(f),O=Wn(a),_=Wn(w),z=Wn(j),H=Ie(()=>X1(N.current.openEvent?.type,T.interactedInside)),B=Ie(()=>_.current?.()!==!1),L=Ie((X,K,q)=>{const Q=S.context.triggerElements;if(Q.hasElement(K))return!X||!Ze(X,K);if(!Rt(q))return!1;const G=q;return Q.hasMatchingElement(J=>Ze(J,G))&&(!X||!Ze(X,G))}),F=Ie(()=>{if(!T.handler)return;Gt(S.select("domReferenceElement")).removeEventListener("mousemove",T.handler),T.handler=void 0}),$=Ie(()=>{wh(T)});return y&&(T.handleCloseOptions=c?.__options),x.useEffect(()=>F,[F]),x.useEffect(()=>{if(!a)return;function X(K){K.open?C.current=!1:(C.current=K.reason===qs,F(),T.openChangeTimeout.clear(),T.restTimeout.clear(),T.blockMouseMove=!0,T.restTimeoutPending=!1)}return R.on("openchange",X),()=>{R.off("openchange",X)}},[a,R,T,F]),x.useEffect(()=>{if(!a)return;function X(Y,re=!0){const M=zi(D.current,"close",T.pointerType);M?T.openChangeTimeout.start(M,()=>{S.setOpen(!1,qe(qs,Y)),P?.events.emit("floating.closed",Y)}):re&&(T.openChangeTimeout.clear(),S.setOpen(!1,qe(qs,Y)),P?.events.emit("floating.closed",Y))}const K=h.current??(y?S.select("domReferenceElement"):null);if(!Rt(K))return;function q(Y){if(T.openChangeTimeout.clear(),T.blockMouseMove=!1,d&&!po(T.pointerType))return;const re=Y1(I.current),M=zi(D.current,"open",T.pointerType),U=fs(Y),Z=Y.currentTarget??null,ae=S.select("domReferenceElement");let ce=Z;if(Rt(U)&&!S.context.triggerElements.hasElement(U)){for(const de of S.context.triggerElements.elements())if(Ze(de,U)){ce=de;break}}Rt(Z)&&Rt(ae)&&!S.context.triggerElements.hasElement(Z)&&Ze(Z,ae)&&(ce=ae);const W=ce==null?!1:L(ae,ce,U),ue=S.select("open"),ve=z.current?.()??S.select("transitionStatus")==="ending",ee=!ue&&ve&&C.current,he=!W&&Rt(ce)&&Rt(ae)&&Ze(ae,ce)&&ee,te=re>0&&!M,ke=W&&(ue||ee)||he,le=!ue||W;if(ke){B()&&S.setOpen(!0,qe(qs,Y,ce));return}te||(M?T.openChangeTimeout.start(M,()=>{le&&B()&&S.setOpen(!0,qe(qs,Y,ce))}):le&&B()&&S.setOpen(!0,qe(qs,Y,ce)))}function Q(Y){if(H()){$();return}F();const re=S.select("domReferenceElement"),M=Gt(re);T.restTimeout.clear(),T.restTimeoutPending=!1;const U=N.current.floatingContext??v?.();if(Zm(Y.relatedTarget,S.context.triggerElements))return;if(E.current&&U){S.select("open")||T.openChangeTimeout.clear();const ae=h.current;T.handler=E.current({...U,tree:P,x:Y.clientX,y:Y.clientY,onClose(){$(),F(),O.current&&!H()&&ae===S.select("domReferenceElement")&&X(Y,!0)}}),M.addEventListener("mousemove",T.handler),T.handler(Y);return}(T.pointerType!=="touch"||!Ze(S.select("floatingElement"),Y.relatedTarget))&&X(Y)}function G(Y){Ze(K,Y.relatedTarget)||(T.openChangeTimeout.clear(),T.restTimeout.clear(),T.restTimeoutPending=!1)}const J=k?St(K,"mouseout",G):void 0;return p?Xa(St(K,"mousemove",q,{once:!0}),St(K,"mouseenter",q),St(K,"mouseleave",Q),J):Xa(St(K,"mouseenter",q),St(K,"mouseleave",Q),J)},[F,$,N,D,S,a,E,T,y,L,H,d,p,I,h,P,O,v,z,B,k]),x.useMemo(()=>{if(!a)return;function X(K){T.pointerType=K.pointerType}return{onPointerDown:X,onPointerEnter:X,onMouseMove(K){const{nativeEvent:q}=K,Q=K.currentTarget,G=S.select("domReferenceElement"),J=S.select("open"),Y=L(G,Q,K.target);if(d&&!po(T.pointerType))return;if(J&&Y&&T.handleCloseOptions?.blockPointerEvents){const U=S.select("floatingElement");if(U){const Z=T.handleCloseOptions?.getScope?.()??Q.ownerDocument.body;qT(T,{scopeElement:Z,referenceElement:Q,floatingElement:U})}}const re=Y1(I.current);if(J&&!Y||re===0||!Y&&T.restTimeoutPending&&K.movementX**2+K.movementY**2<2)return;T.restTimeout.clear();function M(){if(T.restTimeoutPending=!1,H())return;const U=S.select("open");!T.blockMouseMove&&(!U||Y)&&B()&&S.setOpen(!0,qe(qs,q,Q))}T.pointerType==="touch"?Ts.flushSync(()=>{M()}):Y&&J?M():(T.restTimeoutPending=!0,T.restTimeout.start(re,M))}}},[a,T,H,L,d,S,I,B])}const DU="Escape";function YT(e){return jl&&e.movementX===0&&e.movementY===0}function Sh(e,t,a){switch(e){case"vertical":return t;case"horizontal":return a;default:return t||a}}function Nh(e,t){return Sh(t,e===Gv||e===Qm,e===Ei||e===Ai)}function $y(e,t,a){return Sh(t,e===Qm,a?e===Ei:e===Ai)||e==="Enter"||e===" "||e===""}function IU(e,t,a){return Sh(t,a?e===Ei:e===Ai,e===Qm)}function PU(e,t,a,o){const c=a?e===Ai:e===Ei,d=e===Gv;return t==="both"||t==="horizontal"&&o?e===DU:Sh(t,c,d)}function XT(e,t){const{listRef:a,activeIndex:o,onNavigate:c=()=>{},enabled:d=!0,selectedIndex:f=null,allowEscape:p=!1,loopFocus:h=!1,nested:b=!1,rtl:y=!1,virtual:v=!1,focusItemOnOpen:j="auto",focusItemOnHover:w=!0,openOnArrowKeyDown:k=!0,disabledIndices:S=void 0,orientation:N="vertical",parentOrientation:R,id:P,resetOnPointerLeave:T=!0,externalTree:C,grid:E}=t,D=E!=null,I="rootStore"in e?e.rootStore:e,O=I.useState("open"),_=I.useState("floatingElement"),z=I.useState("domReferenceElement"),H=I.context.dataRef,B=Jm(_),L=Wv(z),F=Wn(B),$=lu(),X=Bi(C),K=x.useRef(j),q=x.useRef(f??-1),Q=x.useRef(null),G=x.useRef(!0),J=Ie(pe=>{c(q.current===-1?null:q.current,pe)}),Y=x.useRef(!!_),re=x.useRef(O),M=x.useRef(!1),U=x.useRef(!1),Z=x.useRef(null),ae=Wn(S),ce=Wn(O),W=Wn(f),ue=Wn(T),ve=tu(),ee=tu(),he=Ie(()=>{function pe(De){v?X?.events.emit("virtualfocus",De):Z.current=ph(De,{sync:M.current,preventScroll:!0})}const Ce=a.current[q.current],Ne=U.current;Ce&&pe(Ce),(M.current?De=>De():De=>ve.request(De))(()=>{const De=a.current[q.current]||Ce;if(!De)return;Ce||pe(De),Te&&(Ne||!G.current)&&De.scrollIntoView?.({block:"nearest",inline:"nearest"})})});Me(()=>{H.current.orientation=N},[H,N]),Me(()=>{d&&(O&&_?(q.current=f??-1,K.current&&f!=null&&(U.current=!0,J())):Y.current&&(q.current=-1,J()))},[d,O,_,f,J]),Me(()=>{if(d){if(!O){M.current=!1;return}if(_)if(o==null){if(M.current=!1,W.current!=null)return;if(Y.current&&(q.current=-1,he()),(!re.current||!Y.current)&&K.current&&(Q.current!=null||K.current===!0&&Q.current==null)){let pe=0;const Ce=()=>{a.current[0]==null?(pe<2&&(pe?be=>ee.request(be):queueMicrotask)(Ce),pe+=1):(q.current=Q.current==null||$y(Q.current,N,y)||b?rh(a):ry(a),Q.current=null,J())};Ce()}}else ho(a.current,o)||(q.current=o,he(),U.current=!1)}},[d,O,_,o,W,b,a,N,y,J,he,ee]),Me(()=>{if(!d||_||!X||v||!Y.current)return;const pe=X.nodesRef.current,Ce=pe.find(De=>De.id===$)?.context?.elements.floating,Ne=ir(Gt(z??Ce??null)),be=pe.some(De=>De.context&&Ze(De.context.elements.floating,Ne));Ce&&!be&&G.current&&Ce.focus({preventScroll:!0})},[d,_,z,X,$,v]),Me(()=>{re.current=O,Y.current=!!_}),Me(()=>{O||(Q.current=null,K.current=j)},[O,j]);const te=o!=null,ke=Ie(pe=>{if(!ce.current)return;const Ce=a.current.indexOf(pe.currentTarget);Ce!==-1&&(q.current!==Ce||o!==Ce)&&(q.current=Ce,J(pe))}),le=Ie(()=>R??X?.nodesRef.current.find(pe=>pe.id===$)?.context?.dataRef?.current.orientation),de=Ie(()=>rh(a,ae.current)),Se=Ie(pe=>{if(G.current=!1,M.current=!0,pe.which===229||!ce.current&&pe.currentTarget===F.current)return;if(b&&PU(pe.key,N,y,D)){Nh(pe.key,le())||Cs(pe),I.setOpen(!1,qe(fy,pe.nativeEvent)),pn(z)&&(v?X?.events.emit("virtualfocus",z):z.focus());return}const Ce=q.current,Ne=rh(a,S),be=ry(a,S);if(L||(pe.key==="Home"&&(Cs(pe),q.current=Ne,J(pe)),pe.key==="End"&&(Cs(pe),q.current=be,J(pe))),E!=null){const De=E(pe,q.current,a,N,h,y,S,Ne,be);if(De!=null&&(q.current=De,J(pe)),N==="both")return}if(Nh(pe.key,N)){if(Cs(pe),O&&!v&&ir(pe.currentTarget.ownerDocument)===pe.currentTarget){q.current=$y(pe.key,N,y)?Ne:be,J(pe);return}$y(pe.key,N,y)?h?Ce>=be?p&&Ce!==a.current.length?q.current=-1:(M.current=!1,q.current=Ne):q.current=_s(a.current,{startingIndex:Ce,disabledIndices:S}):q.current=Math.min(be,_s(a.current,{startingIndex:Ce,disabledIndices:S})):h?Ce<=Ne?p&&Ce!==-1?q.current=a.current.length:(M.current=!1,q.current=be):q.current=_s(a.current,{startingIndex:Ce,decrement:!0,disabledIndices:S}):q.current=Math.max(Ne,_s(a.current,{startingIndex:Ce,decrement:!0,disabledIndices:S})),ho(a.current,q.current)&&(q.current=-1),J(pe)}}),Te=x.useMemo(()=>({onFocus(Ce){M.current=!0,ke(Ce)},onClick:({currentTarget:Ce})=>Ce.focus({preventScroll:!0}),onMouseMove(Ce){YT(Ce)||(M.current=!0,U.current=!1,w&&ke(Ce))},onPointerLeave(Ce){if(!ce.current||!G.current||Ce.pointerType==="touch")return;M.current=!0;const Ne=Ce.relatedTarget;if(!(!w||a.current.includes(Ne))&&ue.current&&(Z.current?.(),Z.current=null,q.current=-1,J(Ce),!v)){const be=F.current,De=ir(Gt(be));be&&Ze(be,De)&&be.focus({preventScroll:!0})}}}),[ke,ce,F,w,a,J,ue,v]),Le=x.useMemo(()=>v&&O&&te&&{"aria-activedescendant":`${P}-${o}`},[v,O,te,P,o]),Ae=x.useMemo(()=>({...L?{}:Le,onKeyDown(pe){if(pe.key==="Tab"&&pe.shiftKey&&O&&!v){const Ce=fs(pe.nativeEvent);if(Ce&&!Ze(F.current,Ce))return;Cs(pe),I.setOpen(!1,qe(bo,pe.nativeEvent)),pn(z)&&z.focus();return}Se(pe)},onPointerMove(pe){YT(pe)||(G.current=!0)}}),[Le,Se,F,L,I,O,v,z]),oe=x.useMemo(()=>{function pe(be){I.setOpen(!0,qe(fy,be.nativeEvent,be.currentTarget))}function Ce(be){j==="auto"&&eh(be.nativeEvent)&&(K.current=!v)}function Ne(be){K.current=j,j==="auto"&&Jv(be.nativeEvent)&&(K.current=!0)}return{onKeyDown(be){const De=I.select("open");G.current=!1;const Ge=be.key.startsWith("Arrow"),Ct=IU(be.key,le(),y),Tt=Nh(be.key,N),Mt=(b?Ct:Tt)||be.key==="Enter"||be.key.trim()==="";if(v&&De)return Se(be);if(!(!De&&!k&&Ge)){if(Mt){const ot=Nh(be.key,le());Q.current=b&&ot?null:be.key}if(b){Ct&&(Cs(be),De?(q.current=de(),J(be)):pe(be));return}Tt&&(W.current!=null&&(q.current=W.current),Cs(be),!De&&k?pe(be):Se(be),De&&J(be))}},onFocus(be){I.select("open")&&!v&&(q.current=-1,J(be))},onPointerDown:Ne,onPointerEnter:Ne,onMouseDown:Ce,onClick:Ce}},[Se,j,de,b,J,I,k,N,le,y,W,v]),me=x.useMemo(()=>({...Le,...oe}),[Le,oe]);return x.useMemo(()=>d?{reference:me,floating:Ae,item:Te,trigger:oe}:{},[d,me,Ae,oe,Te])}function QT(e,t){const{listRef:a,elementsRef:o,activeIndex:c,onMatch:d,disabledIndices:f,onTyping:p,enabled:h=!0,resetMs:b=750,selectedIndex:y=null}=t,v="rootStore"in e?e.rootStore:e,j=v.useState("open"),w=er(),k=x.useRef(""),S=x.useRef(y??c??-1),N=x.useRef(null),R=Ie(C=>{function E(F){return o?.current[F]}function D(F){const $=E(F);return $&&!ah($)||$?.matches(":disabled")?!1:f==null||!go(Pr,F,f)}function I(F,$,X=0){if(F.length===0)return-1;const K=(X%F.length+F.length)%F.length,q=$.toLowerCase();for(let Q=0;Q0&&C.key===" "&&(Cs(C),p?.(!0)),k.current.length>0&&k.current[0]!==" "&&I(O,k.current)===-1&&C.key!==" "&&p?.(!1),O==null||C.key.length!==1||C.ctrlKey||C.metaKey||C.altKey)return;j&&C.key!==" "&&(Cs(C),p?.(!0));const _=k.current==="";_&&(S.current=y??c??-1),O.every((F,$)=>F&&D($)?F[0]?.toLowerCase()!==F[1]?.toLowerCase():!0)&&k.current===C.key&&(k.current="",S.current=N.current),k.current+=C.key,w.start(b,()=>{k.current="",S.current=N.current,p?.(!1)});const B=((_?y??c??-1:S.current)??0)+1,L=I(O,k.current,B);L!==-1?(d?.(L),N.current=L):C.key!==" "&&(k.current="",p?.(!1))}),P=Ie(C=>{const E=C.relatedTarget,D=v.select("domReferenceElement"),I=v.select("floatingElement");Ze(D,E)||Ze(I,E)||(w.clear(),k.current="",S.current=N.current,p?.(!1))});Me(()=>{!j&&y!==null||(w.clear(),N.current=null,k.current!==""&&(k.current=""))},[j,y,w]);const T=x.useMemo(()=>({onKeyDown:R,onBlur:P}),[R,P]);return x.useMemo(()=>h?{reference:T,floating:T}:{},[h,T])}const ZT=.1,_U=ZT*ZT,yn=.5;function kh(e,t,a,o,c,d){return o>=t!=d>=t&&e<=(c-a)*(t-o)/(d-o)+a}function Ch(e,t,a,o,c,d,f,p,h,b){let y=!1;return kh(e,t,a,o,c,d)&&(y=!y),kh(e,t,c,d,f,p)&&(y=!y),kh(e,t,f,p,h,b)&&(y=!y),kh(e,t,h,b,a,o)&&(y=!y),y}function LU(e,t,a){return e>=a.x&&e<=a.x+a.width&&t>=a.y&&t<=a.y+a.height}function Th(e,t,a,o,c,d){const f=Math.min(a,c),p=Math.max(a,c),h=Math.min(o,d),b=Math.max(o,d);return e>=f&&e<=p&&t>=h&&t<=b}function WT(e={}){const{blockPointerEvents:t=!1}=e,a=new la,o=({x:c,y:d,placement:f,elements:p,onClose:h,nodeId:b,tree:y})=>{const v=f?.split("-")[0];let j=!1,w=null,k=null,S=typeof performance<"u"?performance.now():0;function N(P,T){const C=performance.now(),E=C-S;if(w===null||k===null||E===0)return w=P,k=T,S=C,!1;const D=P-w,I=T-k,O=D*D+I*I,_=E*E*_U;return w=P,k=T,S=C,O<_}function R(){a.clear(),h()}return function(T){a.clear();const C=p.domReference,E=p.floating;if(!C||!E||v==null||c==null||d==null)return;const{clientX:D,clientY:I}=T,O=fs(T),_=T.type==="mouseleave",z=Ze(E,O),H=Ze(C,O);if(z&&(j=!0,!_))return;if(H&&(j=!1,!_)){j=!0;return}if(_&&Rt(T.relatedTarget)&&Ze(E,T.relatedTarget))return;function B(){return!!(y&&fo(y.nodesRef.current,b).length>0)}function L(){B()||R()}if(B())return;const F=C.getBoundingClientRect(),$=E.getBoundingClientRect(),X=c>$.right-$.width/2,K=d>$.bottom-$.height/2,q=$.width>F.width,Q=$.height>F.height,G=(q?F:$).left,J=(q?F:$).right,Y=(Q?F:$).top,re=(Q?F:$).bottom;if(v==="top"&&d>=F.bottom-1||v==="bottom"&&d<=F.top+1||v==="left"&&c>=F.right-1||v==="right"&&c<=F.left+1){L();return}let M=!1;switch(v){case"top":M=Th(D,I,G,F.top+1,J,$.bottom-1);break;case"bottom":M=Th(D,I,G,$.top+1,J,F.bottom-1);break;case"left":M=Th(D,I,$.right-1,re,F.left+1,Y);break;case"right":M=Th(D,I,F.right-1,re,$.left+1,Y);break}if(M)return;if(j&&!LU(D,I,F)){L();return}if(!_&&N(D,I)){L();return}let U=!1;switch(v){case"top":{const Z=q?yn/2:yn*4,ae=q||X?c+Z:c-Z,ce=q?c-Z:X?c+Z:c-Z,W=d+yn+1,ue=X||q?$.bottom-yn:$.top,ve=X?q?$.bottom-yn:$.top:$.bottom-yn;U=Ch(D,I,ae,W,ce,W,$.left,ue,$.right,ve);break}case"bottom":{const Z=q?yn/2:yn*4,ae=q||X?c+Z:c-Z,ce=q?c-Z:X?c+Z:c-Z,W=d-yn,ue=X||q?$.top+yn:$.bottom,ve=X?q?$.top+yn:$.bottom:$.top+yn;U=Ch(D,I,ae,W,ce,W,$.left,ue,$.right,ve);break}case"left":{const Z=Q?yn/2:yn*4,ae=Q||K?d+Z:d-Z,ce=Q?d-Z:K?d+Z:d-Z,W=c+yn+1,ue=K||Q?$.right-yn:$.left,ve=K?Q?$.right-yn:$.left:$.right-yn;U=Ch(D,I,ue,$.top,ve,$.bottom,W,ae,W,ce);break}case"right":{const Z=Q?yn/2:yn*4,ae=Q||K?d+Z:d-Z,ce=Q?d-Z:K?d+Z:d-Z,W=c-yn,ue=K||Q?$.left+yn:$.right,ve=K?Q?$.left+yn:$.right:$.left+yn;U=Ch(D,I,W,ae,W,ce,ue,$.top,ve,$.bottom);break}}U?j||a.start(40,L):L()}};return o.__options={...e,blockPointerEvents:t},o}const zU={...Hy,disabled:e=>e.disabled,instantType:e=>e.instantType,isInstantPhase:e=>e.isInstantPhase,trackCursorAxis:e=>e.trackCursorAxis,disableHoverablePopup:e=>e.disableHoverablePopup,lastOpenChangeReason:e=>e.openChangeReason,closeOnClick:e=>e.closeOnClick,closeDelay:e=>e.closeDelay,adaptiveOrigin:e=>e.adaptiveOrigin};class BU extends iu{constructor(a,o,c){const d=new yh;super(HU(a,d,o,c),UU(d),zU);cn(this,"setOpen",(a,o)=>{TU(this,a,o,{extraState:{openChangeReason:o.reason}})})}cancelPendingOpen(a){this.state.floatingRootContext.dispatchOpenChange(!1,qe(xo,a))}}function HU(e,t,a,o=!1){return{...zy(t,a,o),disabled:!1,instantType:void 0,isInstantPhase:!1,trackCursorAxis:"none",disableHoverablePopup:!1,openChangeReason:null,closeOnClick:!0,closeDelay:0,adaptiveOrigin:void 0,...e}}function UU(e){return{popupRef:x.createRef(),onOpenChange:void 0,onOpenChangeComplete:void 0,triggerElements:e}}const VU=dh(function(t){const{disabled:a=!1,defaultOpen:o=!1,open:c,disableHoverablePopup:d=!1,trackCursorAxis:f="none",actionsRef:p,onOpenChange:h,onOpenChangeComplete:b,handle:y,triggerId:v,defaultTriggerId:j=null,children:w}=t,k=My((H,B)=>new BU({open:o,openProp:c,activeTriggerId:j,triggerIdProp:v},H,B));k.useControlledProp("openProp",c),k.useControlledProp("triggerIdProp",v),k.useContextCallback("onOpenChange",h),k.useContextCallback("onOpenChangeComplete",b);const S=k.useState("open"),N=!a&&S,R=k.useState("activeTriggerId"),P=k.useState("mounted"),T=k.useState("payload");k.useSyncedValues({trackCursorAxis:f,disableHoverablePopup:d,disabled:a}),Py(k,{closeOnActiveTriggerUnmount:!0});const{forceUnmount:C,transitionStatus:E}=_y(N,k),D=k.useState("isInstantPhase"),I=k.useState("instantType"),O=k.useState("lastOpenChangeReason"),_=x.useRef(null);Me(()=>{S&&a&&k.setOpen(!1,qe(C4))},[S,a,k]),Me(()=>{E==="ending"&&O===Qn||E!=="ending"&&D?(I!=="delay"&&(_.current=I),k.set("instantType","delay")):_.current!==null&&(k.set("instantType",_.current),_.current=null)},[E,D,O,I,k]),Me(()=>{N&&R==null&&k.set("payload",void 0)},[k,R,N]),x.useImperativeHandle(p,()=>({unmount:C,close:()=>k.setOpen(!1,qe(py))}),[C,k]);const z=N||P||!a&&f!=="none";return s.jsxs(K1.Provider,{value:k,children:[y&&s.jsx(Dy,{handle:y,store:k}),z&&s.jsx(FU,{store:k,disabled:a,trackCursorAxis:f}),typeof w=="function"?w({payload:T}):w]})});function FU({store:e,disabled:t,trackCursorAxis:a}){const o=e.useState("floatingRootContext"),c=pf(o,{enabled:!t,referencePress:()=>e.select("closeOnClick")}),d=EH(o,{enabled:!t&&a!=="none",axis:a==="none"?void 0:a}),f=x.useMemo(()=>ta(d.reference,c.reference),[d.reference,c.reference]);return Ly(e,{activeTriggerProps:f,inactiveTriggerProps:f,popupProps:c.floating??mn}),null}const JT=x.createContext(void 0);function $U(){return x.useContext(JT)}const qU=600,eE="data-base-ui-tooltip-trigger";function tE(e){if("composedPath"in e){const a=e.composedPath();for(let o=0;oN.select("transitionStatus")==="ending",shouldOpen(){return!G.current}}),ae=OU(C,{enabled:!X}).reference,ce=he=>{const te=G.current,ke=tE(he),le=U(ke),de=E.current,Se=de&&ke&&Ze(de,ke);if(le&&N.select("open")&&N.select("lastOpenChangeReason")===qs){N.setOpen(!1,qe(qs,he));return}if(te&&!le&&Se&&!K.current&&!N.select("open")&&de&&po(Y.current)){const Te=()=>{!G.current&&!K.current&&!N.select("open")&&N.setOpen(!0,qe(qs,he,de))},Le=re();Le===0?(J.clear(),Te()):J.start(Le,Te)}},W=N.useState("triggerProps",O);return yt("button",t,{state:{open:T},ref:[a,I,E],props:[Z,ae,O||q!=="none"?W:void 0,{onMouseOver(he){ce(he.nativeEvent)},onFocus(he){M(tE(he.nativeEvent))&&he.preventBaseUIHandler()},onMouseLeave(){G.current=!1,J.clear(),Y.current=void 0},onPointerEnter(he){Y.current=he.pointerType},onPointerDown(he){Y.current=he.pointerType,N.set("closeOnClick",y),y&&!N.select("open")&&N.cancelPendingOpen(he.nativeEvent)},onClick(he){y&&!N.select("open")&&N.cancelPendingOpen(he.nativeEvent)},id:R,[Qv]:X?"":void 0,[eE]:X?void 0:""},w],stateAttributesMapping:Kv})}),nE=x.createContext(void 0);function YU(){const e=x.useContext(nE);if(e===void 0)throw new Error(un(70));return e}const XU=x.forwardRef(function(t,a){const{children:o,container:c,className:d,render:f,style:p,...h}=t,{node:b,subtree:y}=iT({container:c,ref:a,componentProps:t,elementProps:h});return!y&&!b?null:s.jsxs(x.Fragment,{children:[y,b&&Ts.createPortal(o,b)]})}),QU=x.forwardRef(function(t,a){const{keepMounted:o=!1,...c}=t;return uf().useState("mounted")||o?s.jsx(nE.Provider,{value:o,children:s.jsx(XU,{ref:a,...c})}):null}),sE=x.createContext(void 0);function rE(){const e=x.useContext(sE);if(e===void 0)throw new Error(un(71));return e}const ZU=x.createContext(void 0);function gf(){return x.useContext(ZU)?.direction??"ltr"}const WU=e=>({name:"arrow",options:e,async fn(t){const{x:a,y:o,placement:c,rects:d,platform:f,elements:p,middlewareData:h}=t,{element:b,padding:y=0,offsetParent:v="real"}=mo(e,t)||{};if(b==null)return{};const j=x1(y),w={x:a,y:o},k=ny(c),S=ty(k),N=await f.getDimensions(b),R=k==="y",P=R?"top":"left",T=R?"bottom":"right",C=R?"clientHeight":"clientWidth",E=d.reference[S]+d.reference[k]-w[k]-d.floating[S],D=w[k]-d.reference[k],I=v==="real"?await f.getOffsetParent?.(b):p.floating;let O=p.floating[C]||d.floating[S];(!O||!await f.isElement?.(I))&&(O=p.floating[C]||d.floating[S]);const _=E/2-D/2,z=O/2-N[S]/2-1,H=Math.min(j[P],z),B=Math.min(j[T],z),L=H,F=O-N[S]-B,$=O/2-N[S]/2+_,X=m1(L,$,F),K=!h.arrow&&Nl(c)!=null&&$!==X&&d.reference[S]/2-(${const{name:a,fn:o}=WU(e);return{name:a,fn:o,options:[e,t]}},eV={name:"hide",async fn(e){const{width:t,height:a,x:o,y:c}=e.rects.reference,d=t===0&&a===0&&o===0&&c===0,f=await e.platform.detectOverflow(e,{elementContext:"reference"});return{data:{referenceHidden:f.top-a>=0||f.right-t>=0||f.bottom-a>=0||f.left-t>=0||d}}}},tV={sideX:"left",sideY:"top"},nV="--available-width",sV="--available-height",rV="--anchor-width",aV="--anchor-height",lV="--transform-origin",aE=nV,lE=sV;function oE(e,t,a){const o=e==="inline-start"||e==="inline-end";return{top:"top",right:o?a?"inline-start":"inline-end":"right",bottom:"bottom",left:o?a?"inline-end":"inline-start":"left"}[t]}function iE(e,t,a){const{rects:o,placement:c}=e;return{side:oE(t,ra(c),a),align:Nl(c)||"center",anchor:{width:o.reference.width,height:o.reference.height},positioner:{width:o.floating.width,height:o.floating.height}}}function Eh(e){return oV(e,AU)}function oV(e,t){const{anchor:a,positionMethod:o="absolute",side:c="bottom",sideOffset:d=0,align:f="center",alignOffset:p=0,collisionBoundary:h,collisionPadding:b=5,sticky:y=!1,arrowPadding:v=5,disableAnchorTracking:j=!1,inline:w,keepMounted:k=!1,floatingRootContext:S,mounted:N,collisionAvoidance:R,shift:P,nodeId:T,adaptiveOrigin:C,lazyFlip:E=!1,externalTree:D}=e,[I,O]=x.useState(null);!N&&I!==null&&O(null);const _=R.side||"flip",z=R.align||"flip",H=R.fallbackAxisSide||"end",B=P?.crossAxis??!1,L=P?.rootBoundary,F=typeof a=="function"?a:void 0,$=Ie(F),X=F?$:a,K=Wn(a),q=Wn(N),G=gf()==="rtl",J=I||{top:"top",right:"right",bottom:"bottom",left:"left","inline-end":G?"left":"right","inline-start":G?"right":"left"}[c],Y=f==="center"?J:`${J}-${f}`;let re=b;typeof re=="number"?re={top:re,right:re,bottom:re,left:re}:re&&(re={top:re.top||0,right:re.right||0,bottom:re.bottom||0,left:re.left||0});const M=1,U=c==="bottom"?M:0,Z=c==="top"?M:0,ae=c==="right"?M:0,ce=c==="left"?M:0,W={boundary:h==="clipping-ancestors"?"clippingAncestors":h,padding:re},ue=x.useRef(null),ve=Wn(d),ee=Wn(p),he=typeof d!="function"?d:0,te=typeof p!="function"?p:0,ke=[];w&&ke.push(w),ke.push(uU(nt=>{const Dt=iE(nt,c,G),qt=typeof ve.current=="function"?ve.current(Dt):ve.current,ts=typeof ee.current=="function"?ee.current(Dt):ee.current;return{mainAxis:qt,crossAxis:ts,alignmentAxis:ts}},[he,te,G,c]));const le=z==="none"&&_!=="shift",de=!le&&(y||B||_==="shift"),Se=_==="none"?null:pU({...W,padding:{top:re.top+M+U,right:re.right+M+ce,bottom:re.bottom+M+Z,left:re.left+M+ae},mainAxis:!B&&_==="flip",crossAxis:z==="flip"?"alignment":!1,fallbackAxisSideDirection:H}),Te=le?null:dU({...W,rootBoundary:L,mainAxis:z!=="none",crossAxis:de,limiter:y||B?void 0:fU(nt=>{if(!ue.current)return{};const{width:Dt,height:qt}=ue.current.getBoundingClientRect(),ts=aa(ra(nt.placement)),Fn=ts==="y"?Dt:qt,$n=ts==="y"?re.left+re.right:re.top+re.bottom;return{offset:Fn/2+$n/2}})},[W,y,B,L,re,z]);_==="shift"||z==="shift"||f==="center"?ke.push(Te,Se):ke.push(Se,Te),ke.push(mU({...W,apply({elements:{floating:nt},availableWidth:Dt,availableHeight:qt,rects:ts}){if(!q.current)return;const Fn=nt.style;Fn.setProperty(aE,`${Dt}px`),Fn.setProperty(lE,`${qt}px`);const $n=Cn(nt).devicePixelRatio||1,{x:Dn,y:en,width:cs,height:Et}=ts.reference,xt=(Math.round((Dn+cs)*$n)-Math.round(Dn*$n))/$n,jt=(Math.round((en+Et)*$n)-Math.round(en*$n))/$n;Fn.setProperty(rV,`${xt}px`),Fn.setProperty(aV,`${jt}px`)}}),JU(nt=>({element:ue.current||Gt(nt.elements.floating).createElement("div"),padding:ue.current?v:0,offsetParent:"floating"}),[v]),{name:"transformOrigin",fn(nt){const{elements:{floating:Dt},middlewareData:qt,placement:ts,platform:Fn,rects:$n,y:Dn}=nt,en=ra(ts),cs=Nl(ts),Et=aa(en)==="y",xt=ue.current,jt=typeof d=="function"?d(iE(nt,c,G)):d;let wt;if(!xt&&cs&&Math.abs(Et?qt.shift?.x||0:qt.shift?.y||0)<=1)wt=cs==="start"===(Et&&Fn.isRTL?.(Dt)===!0)?"100%":"0%";else{const ar=Et?qt.arrow?.x||0:qt.arrow?.y||0,Fr=Et?xt?.clientWidth||0:xt?.clientHeight||0;wt=`${ar+Fr/2}px`}let Er=en==="top"||en==="left"?`calc(100% + ${jt}px)`:`${-jt}px`;return de&&Et&&Math.abs(qt.shift?.y||0)>jt&&(Er=`${$n.reference.y+$n.reference.height/2-Dn}px`),Dt.style.setProperty(lV,Et?`${wt} ${Er}`:`${Er} ${wt}`),{}}},eV,C),Me(()=>{!N&&S&&S.update({referenceElement:null,floatingElement:null,domReferenceElement:null,positionReference:null})},[N,S]);const Le=x.useMemo(()=>({ancestorScroll:!j,elementResize:!j&&typeof ResizeObserver<"u",layoutShift:!j&&typeof IntersectionObserver<"u"}),[j]),{refs:Ae,elements:oe,x:me,y:pe,middlewareData:Ce,update:Ne,placement:be,context:De,isPositioned:Ge,floatingStyles:Ct}=t({rootContext:S,open:k?N:void 0,placement:Y,middleware:ke,strategy:o,whileElementsMounted:k?void 0:(...nt)=>TT(...nt,Le),nodeId:T,externalTree:D}),{sideX:Tt,sideY:Mt}=Ce.adaptiveOrigin||tV,ot=Ge?o:"fixed",Kn=x.useMemo(()=>{let nt;return Ge?C?nt={position:ot,[Tt]:me,[Mt]:pe}:nt={...Ct,position:ot}:nt={position:ot,top:0,left:0},nt[aE]="100vw",nt[lE]="100vh",Ge||(nt.opacity=0),nt},[C,ot,Tt,me,Mt,pe,Ct,Ge]),ms=x.useRef(null);Me(()=>{if(!N)return;const nt=K.current,Dt=typeof nt=="function"?nt():nt,ts=(cE(Dt)?Dt.current:Dt)||null||null;ts!==ms.current&&(Ae.setPositionReference(ts),ms.current=ts)},[N,Ae,X,K]),x.useEffect(()=>{if(!N)return;const nt=K.current;typeof nt!="function"&&cE(nt)&&nt.current!==ms.current&&(Ae.setPositionReference(nt.current),ms.current=nt.current)},[N,Ae,X,K]),x.useEffect(()=>{if(k&&N&&oe.reference&&oe.floating)return TT(oe.reference,oe.floating,Ne,Le)},[k,N,oe,Ne,Le]);const Yn=ra(be),vs=oE(c,Yn,G),it=Nl(be)||"center",$t=!!Ce.hide?.referenceHidden;Me(()=>{E&&N&&Ge&&Yn!==J&&O(Yn)},[E,N,Ge,Yn,J]);const Vn=x.useMemo(()=>({position:"absolute",top:Ce.arrow?.y,left:Ce.arrow?.x}),[Ce.arrow]),rn=Ce.arrow?.centerOffset!==0;return x.useMemo(()=>({positionerStyles:Kn,arrowStyles:Vn,arrowRef:ue,arrowUncentered:rn,side:vs,align:it,physicalSide:Yn,anchorHidden:$t,refs:Ae,context:De,isPositioned:Ge,update:Ne}),[Kn,Vn,ue,rn,vs,it,Yn,$t,Ae,De,Ge,Ne])}function cE(e){return e!=null&&"current"in e}function xf(e){return e==="starting"?bH:mn}function Ah(e,t,{styles:a,transitionStatus:o,props:c,refs:d,hidden:f,inert:p=!1}){const h={...a};return p&&(h.pointerEvents="none"),yt("div",e,{state:t,ref:d,props:[{role:"presentation",hidden:f,style:h},xf(o),c],stateAttributesMapping:Wc})}const iV=x.forwardRef(function(t,a){const{render:o,className:c,anchor:d,positionMethod:f="absolute",side:p="top",align:h="center",sideOffset:b=0,alignOffset:y=0,collisionBoundary:v="clipping-ancestors",collisionPadding:j=5,arrowPadding:w=5,sticky:k=!1,disableAnchorTracking:S=!1,collisionAvoidance:N=aT,style:R,...P}=t,T=uf(),C=YU(),E=T.useState("open"),D=T.useState("mounted"),I=T.useState("trackCursorAxis"),O=T.useState("disableHoverablePopup"),_=T.useState("floatingRootContext"),z=T.useState("instantType"),H=T.useState("transitionStatus"),B=T.useState("adaptiveOrigin"),L=Eh({anchor:d,positionMethod:f,floatingRootContext:_,mounted:D,side:p,sideOffset:b,align:h,alignOffset:y,collisionBoundary:v,collisionPadding:j,sticky:k,arrowPadding:w,disableAnchorTracking:S,keepMounted:C,collisionAvoidance:N,adaptiveOrigin:B}),F=x.useMemo(()=>({open:E,side:L.side,align:L.align,anchorHidden:L.anchorHidden,instant:I!=="none"?"tracking-cursor":z}),[E,L.side,L.align,L.anchorHidden,I,z]),$=Ah(t,F,{styles:L.positionerStyles,transitionStatus:H,props:P,refs:[a,T.useStateSetter("positionerElement")],hidden:!D,inert:!E||I==="both"||O});return s.jsx(sE.Provider,{value:L,children:$})}),cV=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,p=uf(),{side:h,align:b}=rE(),y=p.useState("open"),v=p.useState("instantType"),j=p.useState("transitionStatus"),w=p.useState("popupProps"),k=p.useState("floatingRootContext"),S=p.useState("disabled"),N=p.useState("closeDelay");oa({open:y,ref:p.context.popupRef,onComplete(){y&&p.context.onOpenChangeComplete?.(!0)}}),GT(k,{enabled:!S,closeDelay:N});const R=p.useStateSetter("popupElement");return yt("div",t,{state:{open:y,side:h,align:b,instant:v,transitionStatus:j},ref:[a,p.context.popupRef,R],props:[mf,w,xf(j),f],stateAttributesMapping:Xv})}),uV=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,p=uf(),{arrowRef:h,side:b,align:y,arrowUncentered:v,arrowStyles:j}=rE(),w=p.useState("open"),k=p.useState("instantType");return yt("div",t,{state:{open:w,side:b,align:y,uncentered:v,instant:k},ref:[a,h],props:[{style:j,"aria-hidden":!0},f],stateAttributesMapping:Wc})}),dV=function(t){const{delay:a,closeDelay:o,timeout:c=400}=t,d=x.useMemo(()=>({open:a,close:o}),[a,o]);return s.jsx(JT.Provider,{value:a,children:s.jsx(fH,{delay:d,timeoutMs:c,children:t.children})})};function Rh(e){return zv(19)?e:e?"true":void 0}function fV(e){const[t,a]=x.useState({current:e,previous:null});return Object.is(e,t.current)||a({current:e,previous:t.current}),t.previous}function pV(e){return s.jsx(dV,{"data-slot":"tooltip-provider",...e})}function Ui(e){return s.jsx(VU,{"data-slot":"tooltip",...e})}function Vi(e){return s.jsx(KU,{"data-slot":"tooltip-trigger",...e})}function Fi({className:e,sideOffset:t=8,side:a="top",children:o,...c}){return s.jsx(QU,{children:s.jsx(iV,{sideOffset:t,side:a,className:"z-[35]",children:s.jsx(cV,{"data-slot":"tooltip-content",className:Ue("max-w-[288px] rounded-md bg-primary px-2.5 py-2 text-[11.5px] leading-[1.55] text-primary-on shadow-3","break-words outline-none","transition-[opacity,transform] duration-150 ease-out","data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95","data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",e),...c,children:o})})})}function mV({className:e,...t}){return s.jsx(uV,{className:Ue("size-2 rotate-45 rounded-[1px] bg-primary","data-[side=top]:-bottom-1 data-[side=bottom]:-top-1",e),...t})}const uE=x.createContext(void 0);function cu(e){const t=x.useContext(uE);if(!e&&t===void 0)throw new Error(un(27));return t}const dE=x.forwardRef(function(t,a){const{render:o,className:c,style:d,forceRender:f=!1,...p}=t,h=cu(),b=h.useState("open"),y=h.useState("nested"),v=h.useState("mounted"),j=h.useState("transitionStatus");return yt("div",t,{state:{open:b,transitionStatus:j},ref:[h.context.backdropRef,a],stateAttributesMapping:Xv,props:[{role:"presentation",hidden:!v,style:{userSelect:"none",WebkitUserSelect:"none"}},p],enabled:f||!y})}),fE=x.forwardRef(function(t,a){const{render:o,className:c,style:d,disabled:f=!1,nativeButton:p=!0,...h}=t,b=cu(),y=b.useState("open"),{getButtonProps:v,buttonRef:j}=na({disabled:f,native:p}),w={disabled:f};function k(S){y&&b.setOpen(!1,qe(dy,S.nativeEvent))}return yt("button",t,{state:w,ref:[a,j],props:[{onClick:k},h,v]})}),pE=x.createContext(void 0);function hV(){const e=x.useContext(pE);if(e===void 0)throw new Error(un(26));return e}const qy="ArrowUp",Gy="ArrowDown",Ky="ArrowLeft",Yy="ArrowRight",Xy="Home",Qy="End",Oh=new Set([qy,Gy,Ky,Yy,Xy,Qy]),mE="Shift",gV=[mE,"Control","Alt","Meta"];function xV(e){return pn(e)&&e.tagName==="INPUT"}function hE(e){return!!(xV(e)&&e.selectionStart!=null||pn(e)&&e.tagName==="TEXTAREA")}function gE(e,t,a,o){if(!e||!t||!t.scrollTo)return;let c=e.scrollLeft,d=e.scrollTop;const f=e.clientWidthe.scrollLeft+e.clientWidth-b.scrollPaddingRight?c=h+t.offsetWidth+y.scrollMarginRight-e.clientWidth+b.scrollPaddingRight:h-y.scrollMarginLefte.scrollLeft+e.clientWidth-b.scrollPaddingRight&&(c=h+t.offsetWidth+y.scrollMarginRight-e.clientWidth+b.scrollPaddingRight))}if(p&&o!=="horizontal"){const h=xE(e,t,"top"),b=Mh(e),y=Mh(t);h-y.scrollMarginTope.scrollTop+e.clientHeight-b.scrollPaddingBottom&&(d=h+t.offsetHeight+y.scrollMarginBottom-e.clientHeight+b.scrollPaddingBottom)}e.scrollTo({left:c,top:d,behavior:"auto"})}function xE(e,t,a){const o=a==="left"?"offsetLeft":"offsetTop";let c=0;for(;t.offsetParent&&(c+=t[o],t.offsetParent!==e);)t=t.offsetParent;return c}function Mh(e){const t=getComputedStyle(e);return{scrollMarginTop:parseFloat(t.scrollMarginTop)||0,scrollMarginRight:parseFloat(t.scrollMarginRight)||0,scrollMarginBottom:parseFloat(t.scrollMarginBottom)||0,scrollMarginLeft:parseFloat(t.scrollMarginLeft)||0,scrollPaddingTop:parseFloat(t.scrollPaddingTop)||0,scrollPaddingRight:parseFloat(t.scrollPaddingRight)||0,scrollPaddingBottom:parseFloat(t.scrollPaddingBottom)||0,scrollPaddingLeft:parseFloat(t.scrollPaddingLeft)||0}}const bV="--nested-dialogs",vV="data-nested-dialog-open",yV={...Wc,...uo,nestedDialogOpen(e){return e?{[vV]:""}:null}},bE=x.forwardRef(function(t,a){const{render:o,className:c,style:d,finalFocus:f,initialFocus:p,...h}=t,b=cu(),y=b.useState("descriptionElementId"),v=b.useState("disablePointerDismissal"),j=b.useState("floatingRootContext"),w=b.useState("popupProps"),k=b.useState("modal"),S=b.useState("mounted"),N=b.useState("nested"),R=b.useState("nestedOpenDialogCount"),P=b.useState("open"),T=b.useState("openMethod"),C=b.useState("titleElementId"),E=b.useState("transitionStatus"),D=b.useState("role"),I=j.useState("floatingId");hV(),oa({open:P,ref:b.context.popupRef,onComplete(){P&&b.context.onOpenChangeComplete?.(!0)}});const O=p===void 0?_T(b.context.popupRef):p,_=R>0,z=b.useStateSetter("popupElement"),B=yt("div",t,{state:{open:P,nested:N,transitionStatus:E,nestedDialogOpen:_},props:[w,{id:I,"aria-labelledby":C,"aria-describedby":y,role:D,...mf,hidden:!S,onKeyDown(L){Oh.has(L.key)&&L.stopPropagation()},style:{[bV]:R}},h],ref:[a,b.context.popupRef,z],stateAttributesMapping:yV});return s.jsx(hh,{context:j,openInteractionType:T,disabled:!S,closeOnFocusOut:!v,initialFocus:O,returnFocus:f,modal:k!==!1,restoreFocus:"popup",children:B})}),Dh=x.forwardRef(function(t,a){const{cutout:o,...c}=t;let d;if(o){const f=o.getBoundingClientRect();d=`polygon(0% 0%,100% 0%,100% 100%,0% 100%,0% 0%,${f.left}px ${f.top}px,${f.left}px ${f.bottom}px,${f.right}px ${f.bottom}px,${f.right}px ${f.top}px,${f.left}px ${f.top}px)`}return s.jsx("div",{ref:a,role:"presentation","data-base-ui-inert":"",...c,style:{position:"fixed",inset:0,userSelect:"none",WebkitUserSelect:"none",clipPath:d}})}),vE=x.forwardRef(function(t,a){const{keepMounted:o=!1,...c}=t,d=cu(),f=d.useState("mounted"),p=d.useState("modal"),h=d.useState("open");return f||o?s.jsx(pE.Provider,{value:o,children:s.jsxs(mh,{ref:a,...c,children:[f&&p===!0&&s.jsx(Dh,{ref:d.context.internalBackdropRef,inert:Rh(!h)}),t.children]})}):null});let yE={},jE={},wE="";function Ih(e,t){return Qd(e)?e:t}function SE(e,t,a){return/hidden|clip/.test(e.getComputedStyle(Ih(t,a)).overflowY)}function jV(e){if(typeof document>"u")return!1;const t=Gt(e);return Cn(t).innerWidth-t.documentElement.clientWidth>0}function wV(e){if(!(typeof CSS<"u"&&CSS.supports&&CSS.supports("scrollbar-gutter","stable"))||typeof document>"u")return!1;const a=Gt(e),o=a.documentElement,c=a.body,d=Ih(o,c),f=d.style.overflowY,p=o.style.scrollbarGutter;o.style.scrollbarGutter="stable",d.style.overflowY="scroll";const h=d.offsetWidth;d.style.overflowY="hidden";const b=d.offsetWidth;return d.style.overflowY=f,o.style.scrollbarGutter=p,h===b}function SV(e){const t=Gt(e),a=t.documentElement,o=t.body,c=Ih(a,o),d={overflowY:c.style.overflowY,overflowX:c.style.overflowX};return Object.assign(c.style,{overflowY:"hidden",overflowX:"hidden"}),()=>{Object.assign(c.style,d)}}function NV(e){const t=Gt(e),a=t.documentElement,o=t.body,c=Cn(a);let d=0,f=0,p=!1;const h=Ga.create();if(jl&&(c.visualViewport?.scale??1)!==1)return()=>{};function b(){const w=c.getComputedStyle(a),k=c.getComputedStyle(o),R=(w.scrollbarGutter||"").includes("both-edges")?"stable both-edges":"stable";d=a.scrollTop,f=a.scrollLeft,yE={scrollbarGutter:a.style.scrollbarGutter,overflowY:a.style.overflowY,overflowX:a.style.overflowX},wE=a.style.scrollBehavior,jE={position:o.style.position,height:o.style.height,width:o.style.width,boxSizing:o.style.boxSizing,overflowY:o.style.overflowY,overflowX:o.style.overflowX,scrollBehavior:o.style.scrollBehavior};const P=a.scrollHeight>a.clientHeight,T=a.scrollWidth>a.clientWidth,C=w.overflowY==="scroll"||k.overflowY==="scroll",E=w.overflowX==="scroll"||k.overflowX==="scroll",D=Math.max(0,c.innerWidth-o.clientWidth),I=Math.max(0,c.innerHeight-o.clientHeight),O=parseFloat(k.marginTop)+parseFloat(k.marginBottom),_=parseFloat(k.marginLeft)+parseFloat(k.marginRight),z=Ih(a,o);if(p=wV(e),p){a.style.scrollbarGutter=R,z.style.overflowY="hidden",z.style.overflowX="hidden";return}Object.assign(a.style,{scrollbarGutter:R,overflowY:"hidden",overflowX:"hidden"}),(P||C)&&(a.style.overflowY="scroll"),(T||E)&&(a.style.overflowX="scroll"),Object.assign(o.style,{position:"relative",height:O||I?`calc(100dvh - ${O+I}px)`:"100dvh",width:_||D?`calc(100vw - ${_+D}px)`:"100vw",boxSizing:"border-box",overflowY:"hidden",overflowX:"hidden",scrollBehavior:"unset"}),o.scrollTop=d,o.scrollLeft=f,a.setAttribute("data-base-ui-scroll-locked",""),a.style.scrollBehavior="unset"}function y(){Object.assign(a.style,yE),Object.assign(o.style,jE),p||(a.scrollTop=d,a.scrollLeft=f,a.removeAttribute("data-base-ui-scroll-locked"),a.style.scrollBehavior=wE)}function v(){y(),h.request(b)}b();const j=St(c,"resize",v);return()=>{h.cancel(),y(),typeof c.removeEventListener=="function"&&j()}}class kV{constructor(){cn(this,"lockCount",0);cn(this,"restore",null);cn(this,"timeoutLock",la.create());cn(this,"timeoutUnlock",la.create());cn(this,"release",()=>{this.lockCount-=1,this.lockCount===0&&this.restore&&this.timeoutUnlock.start(0,this.unlock)});cn(this,"unlock",()=>{this.lockCount===0&&this.restore&&(this.restore?.(),this.restore=null)})}acquire(t){return this.lockCount+=1,this.lockCount===1&&this.restore===null&&this.timeoutLock.start(0,()=>this.lock(t)),this.release}lock(t){if(this.lockCount===0||this.restore!==null)return;const a=Gt(t),o=a.documentElement,c=a.body,d=Cn(o);if(SE(d,o,c)){const p=new d.MutationObserver(()=>{SE(d,o,c)||(p.disconnect(),this.restore=null,this.lock(t))}),h={attributes:!0};p.observe(o,h),p.observe(c,h),this.restore=()=>p.disconnect();return}const f=tf||!jV(t);this.restore=f?SV(t):NV(t)}}const CV=new kV;function NE(e=!0,t=null){Me(()=>{if(e)return CV.acquire(t)},[e,t])}function TV({store:e,parentContext:t,isDrawer:a}){const o=e.useState("open"),c=e.useState("disablePointerDismissal"),d=e.useState("modal"),f=e.useState("popupElement"),p=e.useState("floatingRootContext"),[h,b]=x.useState(0),[y,v]=x.useState(0),j=h===0,w=pf(p,{outsidePressEvent(){return e.context.internalBackdropRef.current||e.context.backdropRef.current?"intentional":{mouse:d==="trap-focus"?"sloppy":"intentional",touch:"sloppy"}},outsidePress(k){if(!e.context.outsidePressEnabledRef.current||"button"in k&&k.button!==0)return!1;if("touches"in k){if(k.type==="touchend"){if(k.changedTouches.length!==1||k.touches.length!==0)return!1}else if(k.touches.length!==1)return!1}const S=fs(k);if(j&&!c){if(d){const N=e.context.internalBackdropRef.current,R=e.context.backdropRef.current;return N||R?N===S||R===S||Ze(S,f)&&!S?.hasAttribute("data-base-ui-portal"):!0}return!0}return!1},escapeKey:j});return NE(o&&d===!0,f),e.useContextCallback("onNestedDialogOpen",(k,S)=>{b(k),v(S)}),Me(()=>(t?.onNestedDialogOpen&&(o?t.onNestedDialogOpen(h+1,y+(a?1:0)):t.onNestedDialogOpen(0,0)),()=>{t?.onNestedDialogOpen&&o&&t.onNestedDialogOpen(0,0)}),[a,o,h,y,t]),Ly(e,{activeTriggerProps:w.reference,inactiveTriggerProps:w.trigger,popupProps:w.floating,nestedOpenDialogCount:h,nestedOpenDrawerCount:y}),null}const EV={...Hy,modal:e=>e.modal,nested:e=>e.nested,nestedOpenDialogCount:e=>e.nestedOpenDialogCount,nestedOpenDrawerCount:e=>e.nestedOpenDrawerCount,disablePointerDismissal:e=>e.disablePointerDismissal,openMethod:e=>e.openMethod,descriptionElementId:e=>e.descriptionElementId,titleElementId:e=>e.titleElementId,viewportElement:e=>e.viewportElement,role:e=>e.role};class AV extends iu{constructor(a,o,c){const d=new yh,f=RV(a,d,o,c);super(f,OV(d),EV);cn(this,"setOpen",(a,o)=>{o.preventUnmountOnClose=()=>{this.set("preventUnmountingOnClose",!0)},!a&&o.trigger==null&&this.state.activeTriggerId!=null&&(o.trigger=this.state.activeTriggerElement??void 0),this.context.onOpenChange?.(a,o),!o.isCanceled&&(this.state.floatingRootContext.dispatchOpenChange(a,o),this.update(Iy(this.state,a,o.trigger)))})}}function RV(e,t,a,o=!1){return{...zy(t,a,o),modal:!0,disablePointerDismissal:!1,viewportElement:null,descriptionElementId:void 0,titleElementId:void 0,openMethod:null,nested:!1,nestedOpenDialogCount:0,nestedOpenDrawerCount:0,role:"dialog",...e}}function OV(e){return{popupRef:x.createRef(),backdropRef:x.createRef(),internalBackdropRef:x.createRef(),outsidePressEnabledRef:{current:!0},triggerElements:e,onOpenChange:void 0,onOpenChangeComplete:void 0}}function kE(e,t){const{children:a,open:o,defaultOpen:c=!1,onOpenChange:d,onOpenChangeComplete:f,disablePointerDismissal:p=!1,modal:h=!0,actionsRef:b,handle:y,triggerId:v,defaultTriggerId:j=null}=t,w=e==="drawer",k=e==="alert-dialog",S=k?!0:h,N=k||p,R=k?"alertdialog":"dialog",P=cu(!0),T=P!=null,C={modal:S,disablePointerDismissal:N,nested:T,role:R},E=My((H,B)=>new AV({open:c,openProp:o,activeTriggerId:j,triggerIdProp:v,...C},H,B),!0);E.useControlledProp("openProp",o),E.useControlledProp("triggerIdProp",v),E.useSyncedValues(C),E.useContextCallback("onOpenChange",d),E.useContextCallback("onOpenChangeComplete",f);const D=E.useState("open"),I=E.useState("mounted"),O=E.useState("payload");HT(E,D),Py(E);const{forceUnmount:_}=_y(D,E);x.useImperativeHandle(b,()=>({unmount:_,close:()=>E.setOpen(!1,qe(py))}),[_,E]);const z=D||I;return s.jsxs(uE.Provider,{value:E,children:[y&&s.jsx(Dy,{handle:y,store:E}),z&&s.jsx(TV,{store:E,parentContext:P?.context,isDrawer:w}),typeof a=="function"?a({payload:O}):a]})}const MV=dh(function(t){return kE("dialog",t)}),CE=x.forwardRef(function(t,a){const{render:o,className:c,style:d,id:f,...p}=t,h=cu(),b=ka(f);return h.useSyncedValueWithCleanup("titleElementId",b),yt("h2",t,{ref:a,props:[{id:b},p]})});function DV(e){const t=x.useRef(""),a=x.useCallback(c=>{c.defaultPrevented||(t.current=c.pointerType,e(c,c.pointerType))},[e]);return{onClick:x.useCallback(c=>{if(c.detail===0){e(c,"keyboard");return}"pointerType"in c?e(c,c.pointerType):e(c,t.current),t.current=""},[e]),onPointerDown:a}}function TE(e,t){const a=Ie((d,f)=>{(typeof e=="function"?e():e)||t(f||(tf?"touch":""))}),{onClick:o,onPointerDown:c}=DV(a);return x.useMemo(()=>({onClick:o,onPointerDown:c}),[o,c])}function EE(e){const[t,a]=x.useState(null),o=TE(e,a);return ia(e,c=>{c&&!e&&a(null)}),x.useMemo(()=>({openMethod:t,triggerProps:o}),[t,o])}function Yt(e){return s.jsx(MV,{"data-slot":"dialog",...e})}function IV(e){return s.jsx(vE,{"data-slot":"dialog-portal",...e})}const Ut=e=>s.jsx(CE,{"data-slot":"dialog-title",...e});function PV({className:e,...t}){return s.jsx(dE,{"data-slot":"dialog-overlay",className:Ue("fixed inset-0 isolate z-30 bg-mask backdrop-blur-[3px]","transition-opacity duration-150","data-open:animate-in data-open:fade-in-0","data-closed:animate-out data-closed:fade-out-0 data-closed:fill-mode-forwards",e),...t})}function Xt({className:e,children:t,showCloseButton:a=!0,keepMounted:o=!1,overlayForceRender:c=!1,...d}){return s.jsxs(IV,{keepMounted:o,children:[s.jsx(PV,{forceRender:c}),s.jsxs(bE,{"data-slot":"dialog-content",className:Ue("fixed top-1/2 left-1/2 z-30 flex max-h-[calc(100vh-48px)] w-[min(620px,calc(100vw-48px))] -translate-x-1/2 -translate-y-1/2 flex-col","overflow-hidden rounded-lg border border-border bg-surface shadow-3 outline-none","transition-[opacity,transform] duration-200 [transition-timing-function:cubic-bezier(.2,.9,.3,1)]","data-open:animate-in data-open:fade-in-0 data-open:zoom-in-[.985] data-open:slide-in-from-bottom-2.5","data-closed:animate-out data-closed:fade-out-0 data-closed:fill-mode-forwards",e),...d,children:[t,a&&s.jsxs(fE,{"data-slot":"dialog-close",render:s.jsx(ne,{variant:"ghost",size:"icon-sm",className:"absolute top-3 right-3"}),children:[s.jsx("svg",{viewBox:"0 0 12 12",className:"size-3","aria-hidden":"true",children:s.jsx("path",{d:"M2.5 2.5l7 7M9.5 2.5l-7 7",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",fill:"none"})}),s.jsx("span",{className:"sr-only",children:vo("关闭")})]})]})]})}function Vt({className:e,...t}){return s.jsx("div",{"data-slot":"dialog-header",className:Ue("flex items-center gap-2.5 border-b border-hairline px-5 py-[15px] pr-10","[&_h2]:flex-1 [&_h2]:text-[14.5px] [&_h2]:font-semibold",e),...t})}function Lt({className:e,...t}){return s.jsx("div",{"data-slot":"dialog-body",className:Ue("flex flex-col gap-4 overflow-y-auto px-5 py-[18px]",e),...t})}function tn({className:e,...t}){return s.jsx("div",{"data-slot":"dialog-footer",className:Ue("flex items-center gap-2 border-t border-hairline bg-surface-2 px-5 py-[13px]",e),...t})}function dn({className:e,...t}){return s.jsx("div",{"data-slot":"dialog-section",className:Ue("flex flex-col gap-2.5 rounded-md border border-border bg-surface-inset p-3.5","[&_h3]:text-[12.5px] [&_h3]:font-semibold","[&_p]:text-xs [&_p]:leading-[1.65] [&_p]:text-subtle",e),...t})}function _V(e){return kE("alert-dialog",e)}const LV=_V,zV=vE,BV=e=>s.jsx(CE,{"data-slot":"alert-dialog-title",...e});function HV({className:e,...t}){return s.jsx(dE,{"data-slot":"alert-dialog-overlay",className:Ue("fixed inset-0 isolate z-[38] bg-mask backdrop-blur-[3px]","transition-opacity duration-150","data-open:animate-in data-open:fade-in-0","data-closed:animate-out data-closed:fade-out-0 data-closed:fill-mode-forwards",e),...t})}function UV({className:e,children:t,showCloseButton:a=!1,...o}){return s.jsxs(zV,{children:[s.jsx(HV,{}),s.jsxs(bE,{"data-slot":"alert-dialog-content",className:Ue("fixed top-1/2 left-1/2 z-[38] flex max-h-[calc(100vh-48px)] w-[min(440px,calc(100vw-48px))] -translate-x-1/2 -translate-y-1/2 flex-col","overflow-hidden rounded-lg border border-border bg-surface shadow-3 outline-none","transition-[opacity,transform] duration-200 [transition-timing-function:cubic-bezier(.2,.9,.3,1)]","data-open:animate-in data-open:fade-in-0 data-open:zoom-in-[.985] data-open:slide-in-from-bottom-2.5","data-closed:animate-out data-closed:fade-out-0 data-closed:fill-mode-forwards",e),...o,children:[t,a&&s.jsxs(fE,{"data-slot":"alert-dialog-close",render:s.jsx(ne,{variant:"ghost",size:"icon-sm",className:"absolute top-3 right-3"}),children:[s.jsx("svg",{viewBox:"0 0 12 12",className:"size-3","aria-hidden":"true",children:s.jsx("path",{d:"M2.5 2.5l7 7M9.5 2.5l-7 7",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",fill:"none"})}),s.jsx("span",{className:"sr-only",children:vo("关闭")})]})]})]})}function VV({className:e,...t}){return s.jsx("div",{"data-slot":"alert-dialog-header",className:Ue("flex items-center gap-2.5 border-b border-hairline px-5 py-[15px]","[&_h2]:flex-1 [&_h2]:text-[14.5px] [&_h2]:font-semibold",e),...t})}function FV({className:e,...t}){return s.jsx("div",{"data-slot":"alert-dialog-body",className:Ue("flex flex-col gap-4 overflow-y-auto px-5 py-[18px]",e),...t})}function $V({className:e,...t}){return s.jsx("div",{"data-slot":"alert-dialog-footer",className:Ue("flex items-center gap-2 border-t border-hairline bg-surface-2 px-5 py-[13px]",e),...t})}function qV({className:e,tone:t="danger",...a}){return s.jsx("div",{"data-slot":"alert-dialog-banner","data-tone":t,className:Ue("rounded-md border px-3.5 py-3 text-xs leading-[1.65] text-subtle","[&_strong]:font-semibold",t==="danger"?"border-destructive-bd bg-destructive-soft [&_strong]:text-destructive":"border-border bg-surface-inset [&_strong]:text-foreground",e),...a})}function Zy({className:e,containerClassName:t,...a}){return s.jsx("div",{"data-slot":"table-container",className:Ue("relative w-full overflow-auto",t),children:s.jsx("table",{"data-slot":"table",className:Ue("w-full caption-bottom border-collapse text-[12.5px]",e),...a})})}function AE({className:e,...t}){return s.jsx("thead",{"data-slot":"table-header",className:Ue(e),...t})}function Wy({className:e,...t}){return s.jsx("tbody",{"data-slot":"table-body",className:Ue(e),...t})}function Cl({className:e,...t}){return s.jsx("tr",{"data-slot":"table-row",className:Ue("transition-colors duration-100 hover:[&>td]:bg-control-hover",e),...t})}function RE({className:e,...t}){return s.jsx("th",{"data-slot":"table-head",className:Ue("sticky top-0 z-[2] whitespace-nowrap border-b border-border bg-surface-2 px-3.5 py-2","text-left text-[10.5px] font-semibold tracking-[.05em] text-muted-foreground",e),...t})}function Tn({className:e,...t}){return s.jsx("td",{"data-slot":"table-cell",className:Ue("border-b border-hairline px-3.5 py-2 align-middle",e),...t})}const GV="data-checked",KV="data-unchecked",Jy={checked(e){return e?{[GV]:""}:{[KV]:""}},...uo,...Ti},ej="data-composite-item-active",OE=x.createContext({register:()=>{},unregister:()=>{},subscribeMapChange:()=>()=>{},nextIndexRef:{current:0}});function YV(){return x.useContext(OE)}function tj(e={}){const{guess:t,label:a,metadata:o,textRef:c,index:d}=e,{register:f,unregister:p,subscribeMapChange:h,nextIndexRef:b}=YV(),y=x.useRef(-1),[v,j]=x.useState(d==null&&t?()=>{if(y.current===-1){const N=b.current;b.current+=1,y.current=N}return y.current}:-1),w=d??v,k=x.useRef(null),S=x.useCallback(N=>{const R=k.current;R&&p(R),k.current=N,N&&f(N,{metadata:o??null,index:d??null,label:a,textRef:c})},[d,f,p,o,a,c]);return Me(()=>{if(d==null)return h(N=>{const R=k.current?N.get(k.current)?.index:null;R!=null&&j(R)})},[d,h]),{ref:S,index:w}}function XV(e={}){const{highlightItemOnHover:t,highlightedIndex:a,onHighlightedIndexChange:o}=EC(),{ref:c,index:d}=tj(e),f=a===d,p=x.useRef(null),h=sa(c,p);return{compositeProps:{tabIndex:f?0:-1,onFocus(){o(d)},onMouseMove(){const y=p.current;if(!t||!y)return;const v=y.hasAttribute("disabled")||y.ariaDisabled==="true";!f&&!v&&y.focus()}},compositeRef:h,index:d}}function ME(e){const{render:t,className:a,style:o,state:c=mn,props:d=Pr,refs:f=Pr,metadata:p,stateAttributesMapping:h,tag:b="div",...y}=e,{compositeProps:v,compositeRef:j}=XV({metadata:p});return yt(b,e,{state:c,ref:[j,...f],props:[v,...d,y],stateAttributesMapping:h})}const DE=x.createContext(void 0);function QV(){return x.useContext(DE)}function Ph(e){if(e==null)return"";if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return String(e)}}const IE=x.createContext(void 0);function ZV(){const e=x.useContext(IE);if(e===void 0)throw new Error(un(52));return e}const PE=x.forwardRef(function(t,a){const{render:o,className:c,disabled:d=!1,readOnly:f=!1,required:p=!1,"aria-labelledby":h,value:b,inputRef:y,nativeButton:v=!1,id:j,style:w,...k}=t,S=QV(),{disabled:N,readOnly:R,required:P,form:T,checkedValue:C,touched:E=!1,validation:D,name:I,setCheckedValue:O=Kt,setTouched:_=Kt,registerInputRef:z=Kt}=S??{},{setTouched:H,setFilled:B,state:L,disabled:F}=Na(),$=A1(),{labelId:X,getDescriptionProps:K}=yl(),q=F||$.disabled||N||d,Q=R||f,G=P||p,J=T,Y=S?C===b:b==="",re=x.useRef(null),M=x.useRef(null),U=D?.registerInput,Z=x.useCallback(oe=>U?.(oe,{controlRef:re,value:void 0}),[U]),ae=sa(y,M,z,Z);Me(()=>{M.current?.checked&&B(!0)},[B]),Me(()=>{if(M.current){if(q&&Y){z(null);return}z(M.current)}},[Y,q,z]);const ce=ka(),W=co({id:j}),ue=v?void 0:W,ve=Fv(h,X,M,!v,ue),ee={role:"radio","aria-checked":Y,"aria-labelledby":ve,[ej]:Y?"":void 0,id:v?W:ce,onKeyDown(oe){oe.key==="Enter"&&oe.preventDefault()},onClick(oe){if(oe.defaultPrevented||q||Q)return;oe.preventDefault();const me=M.current;me&&Xc(me,oe)},onFocus(oe){oe.defaultPrevented||q||Q||!E||(M.current?.click(),_(!1))}},{getButtonProps:he,buttonRef:te}=na({disabled:q,native:v,composite:!1}),ke={type:"radio",ref:ae,form:J,id:ue,name:I,tabIndex:-1,style:I?ru:_i,"aria-hidden":!0,...b!==void 0?{value:Ph(b)}:mn,disabled:q,checked:Y,required:G,readOnly:Q,onChange(oe){if(oe.nativeEvent.defaultPrevented||q||Q||b===void 0)return;const me=qe(Qn,oe.nativeEvent);O(b,me),!me.isCanceled&&H(!0)},onClick(oe){oe.stopPropagation()},onFocus(){re.current?.focus()}},le=x.useMemo(()=>({...L,required:G,disabled:q,readOnly:Q,checked:Y}),[L,q,Q,Y,G]),de=le,Se=S!==void 0,Te=[a,re,te],Le=[ee,k,he,K,D?oe=>D.getValidationProps(q,oe):mn],Ae=yt("span",t,{enabled:!Se,state:le,ref:Te,props:Le,stateAttributesMapping:Jy});return s.jsxs(IE.Provider,{value:de,children:[Se?s.jsx(ME,{tag:"span",render:o,className:c,style:w,state:le,refs:Te,props:Le,stateAttributesMapping:Jy}):Ae,s.jsx("input",{...ke,suppressHydrationWarning:!0})]})}),WV=x.forwardRef(function(t,a){const{render:o,className:c,style:d,keepMounted:f=!1,...p}=t,h=ZV(),b=h.checked,{mounted:y,transitionStatus:v,setMounted:j}=Oi(b),w={...h,transitionStatus:v},k=x.useRef(null),S=f||y,N=yt("span",t,{ref:[a,k],state:w,props:p,stateAttributesMapping:Jy});return oa({batch:!0,enabled:!b,open:b,ref:k,onComplete(){b||j(!1)}}),S?N:null});function nj(e){const{children:t,elementsRef:a,labelsRef:o,onMapChange:c}=e,d=Ie(c),[,f]=x.useState(!1),p=Ps(eF).current,h=Ps(JV).current,b=x.useRef(0),y=x.useRef(!0),v=x.useRef(null),j=x.useRef(null),w=Ie(()=>{y.current||(y.current=!0,f(E=>!E))}),k=Ie((E,D)=>{h.set(E,D),w()}),S=Ie(E=>{h.delete(E),w()}),N=Ie(E=>{const D=new Map;return a.current.length=0,o&&(o.current.length=0),E.forEach(I=>{D.set(I.element,{...I.registration.metadata??{},index:I.index}),a.current[I.index]=I.element,o&&(o.current[I.index]=I.registration.label!==void 0?I.registration.label:I.registration.textRef?.current?.textContent??I.element.textContent)}),b.current=a.current.length,D});function R(E){if(j.current?.disconnect(),j.current=null,typeof MutationObserver!="function"||E.length<2)return;const D=new MutationObserver(O=>{if(!sF(O))return;let _=null;for(const z of E)if(z.isConnected){if(_&&_E(_,z)>0){D.disconnect(),w();return}_=z}});j.current=D;const I=new Set;for(let O=1;OD.observe(O,{childList:!0}))}const P=Ie(()=>{const[E,D]=tF(h),I=N(E),O=v.current,_=!O||O.length!==E.length||E.some((z,H)=>{const B=O[H];return z.index!==B.index||z.element!==B.element||z.registration.index!==B.registration.index||z.registration.metadata!==B.registration.metadata});R(D),v.current=E,y.current=!1,_&&(p.forEach(z=>z(I)),d(I))});Me(()=>(!y.current&&v.current&&N(v.current),()=>{a.current=[],o&&(o.current=[])}),[a,o,N]),Me(()=>{y.current&&P()}),Me(()=>()=>{j.current?.disconnect(),y.current=!0},[]);const T=Ie(E=>(p.add(E),()=>{p.delete(E)})),C=x.useMemo(()=>({register:k,unregister:S,subscribeMapChange:T,nextIndexRef:b}),[k,S,T,b]);return s.jsx(OE.Provider,{value:C,children:t})}function JV(){return new Map}function eF(){return new Set}function tF(e){const t=new Set,a=[],o=[];e.forEach((d,f)=>{if(!f.isConnected)return;const p=d.index,h={index:p??-1,element:f,registration:d};p===null?o.push(h):p>=0&&(t.add(p),a.push(h))});let c=0;return o.sort((d,f)=>_E(d.element,f.element)),o.forEach(d=>{for(;t.has(c);)c+=1;d.index=c,a.push(d),c+=1}),t.size>0&&a.sort((d,f)=>d.index-f.index),[a,o.map(d=>d.element)]}function nF(e,t){let a=e.parentElement;for(;a&&!a.contains(t);)a=a.parentElement;return a}function sF(e){for(const t of e)for(let a=0;a{if(C.current=P.current[H]??null,(p??k)(H),B){const L=P.current[H];gE(N.current,L,d,a)}}),I=Ie(H=>{if(H.size===0)return;if(T.current){const $=P.current,X=$.indexOf(C.current);if(X===-1){const K=$[E];!K||go($,E,v)?D(aF($,v)):C.current=K}else X!==E&&D(X);return}T.current=!0;const B=Array.from(H.keys()),L=B.find($=>$?.hasAttribute(ej))??null,F=L?H.get(L)?.index??-1:-1;if(F!==-1)D(F);else if(go(B,E,v)){const $=_s(B,{disabledIndices:v});ho(B,$)||D($)}gE(N.current,L,d,a)});Me(()=>{if(v==null||f!=null||!T.current)return;const H=P.current;if(go(H,E,v)){const B=_s(H,{disabledIndices:v});ho(H,B)||D(B)}},[v,f,E,P,D]);const O=Ie((H,B,L)=>c?c(H,B,L,P):L),_=Ie(H=>{const B=H.key===Xy||H.key===Qy;if(!Oh.has(H.key)||!b&&B||lF(H,j)||!N.current)return;const F=d==="rtl",$=F?Ky:Yy,X=F?Yy:Ky,K=a==="vertical"?Gy:$,q=a==="vertical"?qy:X,Q=fs(H.nativeEvent);if(Q!=null&&hE(Q)&&!LE(Q)){const U=Q.selectionStart,Z=Q.selectionEnd,ae=Q.value;if(U==null||H.shiftKey||U!==Z||H.key!==q&&U0)return}let G=E;const J=rh(P,v),Y=ry(P,v);o!=null&&(G=o({disabledIndices:v,elementsRef:P,event:H,highlightedIndex:E,loopFocus:t,maxIndex:Y,minIndex:J,onLoop:O,orientation:a,rtl:F}));const re=a!=="vertical"&&H.key===$||a!=="horizontal"&&H.key===Gy,M=a!=="vertical"&&H.key===X||a!=="horizontal"&&H.key===qy;b&&(H.key===Xy?G=J:H.key===Qy&&(G=Y)),G===E&&(re||M)&&(t&&G===Y&&re?(G=J,c&&(G=c(H,E,G,P))):t&&G===J&&M?(G=Y,c&&(G=c(H,E,G,P))):G=_s(P.current,{startingIndex:G,decrement:M,disabledIndices:v})),G!==E&&!ho(P.current,G)&&(y&&H.stopPropagation(),(S||B||re||M)&&H.preventDefault(),D(G,!0),queueMicrotask(()=>{P.current[G]?.focus()}))});return{props:{ref:R,onFocus(H){const B=N.current,L=fs(H.nativeEvent);!B||L==null||!hE(L)||L.setSelectionRange(0,L.value.length)},onKeyDown:_},highlightedIndex:E,onHighlightedIndexChange:D,elementsRef:P,onMapChange:I,relayKeyboardEvent:_}}function aF(e,t){let a=-1;for(let o=0;o({highlightedIndex:_,onHighlightedIndexChange:z,highlightItemOnHover:C,relayKeyboardEvent:L}),[_,z,C,L]);return s.jsx(TC.Provider,{value:$,children:s.jsx(nj,{elementsRef:H,onMapChange:X=>{S?.(X),B(X)},children:F})})}const iF=[mE],zE=x.forwardRef(function(t,a){const{render:o,className:c,disabled:d,readOnly:f,required:p,onValueChange:h,value:b,defaultValue:y,form:v,name:j,inputRef:w,id:k,style:S,...N}=t,{setTouched:R,setFocused:P,validationMode:T,name:C,disabled:E,state:D,validation:I,setDirty:O,setFilled:_,validityData:z}=Na(),{labelId:H}=yl(),{clearErrors:B,elementRef:L}=Zc(),F=TB(!0),$=E||d,X=C??j,K=ka(k),[q,Q]=Ka({controlled:b,default:y,name:"RadioGroup",state:"value"}),[G,J]=x.useState(!1),Y=Ie((te,ke)=>{h?.(te,ke),!ke.isCanceled&&Q(te)}),re=I.getInputControl,M=x.useMemo(()=>({get current(){return re()}}),[re]),U=x.useRef(null),Z=x.useRef(null);function ae(te){let ke;return w&&(typeof w=="function"?ke=w(te):w.current=te),U.current=te,ke}const ce=Ie(te=>{if(!te||te.disabled)return;Z.current||(Z.current=te);const ke=U.current,le=te.checked||ke==null||ke.disabled?ae(te):void 0;return()=>{Z.current===te&&(Z.current=null),U.current===te?le?(le(),U.current=null):ae(null):le?.()}}),W=Ie(()=>{const te=L.current;if(!te)return q??null;for(const ke of I.registeredInputs.keys())if(ke.checked&&y4(ke,te))return q??null;return null});nu(M,K,q??null,W,!$,j),ia(q,()=>{B(X),O(q!==z.initialValue),_(q!=null),I.change(q);const te=Z.current;q==null&&te&&!te.disabled&&ae(te)});const ue=H??F?.legendId,ve={...D,disabled:$??!1,required:p??!1,readOnly:f??!1},ee=x.useMemo(()=>({checkedValue:q,disabled:$,form:v,validation:I,name:X,readOnly:f,registerInputRef:ce,required:p,setCheckedValue:Y,setTouched:J,touched:G}),[q,$,v,I,X,f,ce,p,Y,J,G]),he={id:k,role:"radiogroup","aria-required":p||void 0,"aria-disabled":$||void 0,"aria-readonly":f||void 0,"aria-labelledby":ue,onFocus(){P(!0)},onBlur(te){Ze(te.currentTarget,te.relatedTarget)||(R(!0),P(!1),T==="onBlur"&&I.commit(q))},onKeyDownCapture(te){te.key.startsWith("Arrow")&&(J(!0),P(!0))}};return s.jsx(DE.Provider,{value:ee,children:s.jsx(oF,{render:o,className:c,style:S,state:ve,props:[he,N,te=>I.getValidationProps($??!1,te)],refs:[a],stateAttributesMapping:Ti,enableHomeAndEndKeys:!1,modifierKeys:iF})})});function _h({className:e,...t}){return s.jsx(zE,{"data-slot":"radio-group",className:Ue("flex flex-col gap-2",e),...t})}function jo({className:e,...t}){return s.jsx(PE,{"data-slot":"radio-group-item",className:Ue("relative inline-flex size-3.5 flex-none cursor-pointer items-center justify-center rounded-full border border-control-border bg-control","outline-none transition-colors duration-150 ease-out","hover:border-control-border-hover","data-checked:border-primary data-checked:bg-primary","focus-visible:shadow-focus","data-disabled:cursor-not-allowed data-disabled:opacity-45",e),...t,children:s.jsx(WV,{"data-slot":"radio-group-indicator",className:"grid place-content-center data-unchecked:hidden",children:s.jsx("span",{className:"block size-[5px] rounded-full bg-primary-foreground"})})})}function BE(e){const t=x.useRef(!0);t.current&&(t.current=!1,e())}const HE=x.createContext(void 0),UE=x.createContext(void 0),VE=x.createContext(void 0);function wo(){const e=x.useContext(HE);if(e===void 0)throw new Error(un(60));return e}function sj(){const e=x.useContext(UE);if(e===void 0)throw new Error(un(101));return e}function FE(){const e=x.useContext(VE);if(e===void 0)throw new Error(un(61));return e}function cF(e,t,a=Object.is){const{length:o}=e;if(o!==t.length)return!1;for(let c=0;cObject.is(e,t);function ca(e,t,a){return e==null||t==null?Object.is(e,t):a(e,t)}function $E(e,t,a){return Array.isArray(e)&&Array.isArray(t)?!cF(e,t,(o,c)=>ca(o,c,a)):e!==t}function zh(e,t,a){return e?e.some(o=>o===void 0?!1:ca(t,o,a)):!1}function uu(e,t,a){return e?e.findIndex(o=>o===void 0?!1:ca(o,t,a)):-1}function uF(e,t){if(t!==Lh)return o=>zh(e,o,t);const a=new Set(e);return a.delete(void 0),o=>a.has(o)&&(o!==0||e.some(c=>Object.is(o,c)))}function bf(e,t,a,o){const c=o&&Array.isArray(t)?e.findIndex(uF(t,a)):uu(e,t,a);return c===-1?null:c}function qE(e,t,a,o,c,d){return zh(o,t,c)?d!=null&&e>d&&zh(o,a[d],c)?d:e:e===d?bf(a,o,c,!0):d}function GE(e,t,a){return e.filter(o=>!ca(t,o,a))}function dF(e){return typeof e=="object"&&e!=null&&Array.isArray(e.items)}function rj(e){return dF(e?.[0])}function Bh(e){return rj(e)?e.flatMap(t=>t.items):e}function KE(e){if(!Array.isArray(e))return e!=null&&"null"in e;const t=e;if(rj(t)){for(const a of t)for(const o of a.items)if(o&&o.value==null&&o.label!=null)return!0;return!1}for(const a of t)if(a&&a.value==null&&a.label!=null)return!0;return!1}function So(e,t){if(t&&e!=null)return t(e)??"";if(e&&typeof e=="object"){if("label"in e&&e.label!=null)return String(e.label);if("value"in e)return String(e.value)}return Ph(e)}function Ca(e,t){return t&&e!=null?t(e)??"":e&&typeof e=="object"&&"value"in e&&"label"in e?Ph(e.value):Ph(e)}function YE(e,t,a){function o(){return So(e,a)}if(a&&e!=null)return a(e);if(e&&typeof e=="object"&&"label"in e&&e.label!=null)return e.label;if(t&&!Array.isArray(t))return(Object.hasOwn(t,e)?t[e]:void 0)??o();if(Array.isArray(t)){const d=Bh(t);if(e==null||typeof e!="object"){const f=d.find(p=>p.value===e);return f&&f.label!=null?f.label:o()}if("value"in e){const f=d.find(p=>p&&p.value===e.value);if(f&&f.label!=null)return f.label}}return o()}function fF(e,t,a){return e.reduce((o,c,d)=>(d>0&&o.push(", "),o.push(s.jsx(x.Fragment,{children:YE(c,t,a)},d)),o),[])}const pF={id:e=>e.id,labelId:e=>e.labelId,modal:e=>e.modal,items:e=>e.items,itemToStringLabel:e=>e.itemToStringLabel,isItemEqualToValue:e=>e.isItemEqualToValue,value:e=>e.value,hasSelectedValue:e=>{const{value:t,multiple:a,itemToStringValue:o}=e;return t==null?!1:a&&Array.isArray(t)?t.length>0:Ca(t,o)!==""},hasNullItemLabel:(e,t)=>t?KE(e.items):!1,open:e=>e.open,mounted:e=>e.mounted,forceMount:e=>e.forceMount,transitionStatus:e=>e.transitionStatus,openMethod:e=>e.openMethod,activeIndex:e=>e.activeIndex,selectedIndex:e=>e.selectedIndex,isActive:(e,t)=>e.activeIndex===t,isSelected:(e,t)=>{const a=e.isItemEqualToValue,o=e.value;return e.multiple?Array.isArray(o)&&o.some(c=>ca(t,c,a)):ca(t,o,a)},isSelectedByFocus:(e,t)=>e.selectedIndex===t,popupProps:e=>e.popupProps,triggerProps:e=>e.triggerProps,triggerElement:e=>e.triggerElement,positionerElement:e=>e.positionerElement,listElement:e=>e.listElement,popupSide:e=>e.popupSide,scrollUpArrowVisible:e=>e.scrollUpArrowVisible,scrollDownArrowVisible:e=>e.scrollDownArrowVisible,hasScrollArrows:e=>e.hasScrollArrows},Tl=1;function XE(e,t){return Math.max(0,e-t)}function mF(e,t){if(t<=0)return 0;const a=Li(e,0,t),o=a,c=t-a,d=o<=Tl,f=c<=Tl;return d&&f?o<=c?0:t:d?0:f?t:a}function hF(e){const{id:t,value:a,defaultValue:o=null,onValueChange:c,open:d,defaultOpen:f=!1,onOpenChange:p,name:h,form:b,autoComplete:y,disabled:v=!1,readOnly:j=!1,required:w=!1,modal:k=!0,actionsRef:S,inputRef:N,onOpenChangeComplete:R,items:P,multiple:T=!1,itemToStringLabel:C,itemToStringValue:E,isItemEqualToValue:D=Lh,highlightItemOnHover:I=!0,children:O}=e,{clearErrors:_}=Zc(),{setDirty:z,setTouched:H,setFocused:B,validityData:L,setFilled:F,name:$,disabled:X,validation:K,validationMode:q}=Na(),Q=co({id:t}),G=X||v,J=$??h,[Y,re]=Ka({controlled:a,default:T?o??Pr:o,name:"Select",state:"value"}),[M,U]=Ka({controlled:d,default:f,name:"Select",state:"open"}),Z=x.useRef([]),ae=x.useRef([]),ce=x.useRef(null),W=x.useRef(null),ue=x.useRef(0),ve=x.useRef(null),ee=x.useRef([]),he=x.useRef(!1),te=x.useRef(null),ke=x.useRef(null),le=x.useRef({allowSelectedMouseUp:!1,allowUnselectedMouseUp:!1,dragY:0}),de=x.useRef(!1),Se=x.useRef(Y),{mounted:Te,setMounted:Le,transitionStatus:Ae}=Oi(M),{openMethod:oe,triggerProps:me}=EE(M),pe=Ps(()=>new iu({id:Q,labelId:void 0,modal:k,multiple:T,itemToStringLabel:C,itemToStringValue:E,isItemEqualToValue:D,value:Y,open:M,mounted:Te,transitionStatus:Ae,items:P,forceMount:!1,openMethod:null,activeIndex:null,selectedIndex:null,popupProps:mn,triggerProps:mn,triggerElement:null,positionerElement:null,listElement:null,popupSide:null,scrollUpArrowVisible:!1,scrollDownArrowVisible:!1,hasScrollArrows:!1},{setValue:Kt,setOpen:Kt,handleScrollArrowVisibility:Kt,onOpenChangeComplete:Kt,listRef:Z,popupRef:ce,scrollHandlerRef:W,scrollArrowsMountedCountRef:ue,valueRef:ve,valuesRef:ee,labelsRef:ae,typingRef:he,selectionRef:le,firstItemTextRef:te,selectedItemTextRef:ke,alignItemWithTriggerActiveRef:de,initialValueRef:Se},pF)).current,Ce=pe.useState("activeIndex"),Ne=pe.useState("selectedIndex"),be=pe.useState("triggerElement"),De=pe.useState("positionerElement"),Ge=fV(oe),Ct=oe??Ge,Tt=x.useMemo(()=>T?"":Ca(Y,E),[T,Y,E]),Mt=x.useMemo(()=>T&&Array.isArray(Y)?Y.map(xt=>Ca(xt,E)):Ca(Y,E),[T,Y,E]),ot=Wn(be),Kn=Ie(()=>Mt);nu(ot,Q,Y,Kn,!G,h);const ms=T?Array.isArray(Y)&&Y.length>0:Y!=null&&Tt!=="";Me(()=>{F(ms)},[ms,F]),Me(function(){const jt=bf(ee.current,Y,D,T);jt===null&&(ke.current=null),!M&&pe.set("selectedIndex",jt)},[T,M,Y,D,pe]),ia(Y,()=>{_(J),z($E(Y,L.initialValue,D)),K.change(Y)});const Yn=Ie((xt,jt)=>{p?.(xt,jt),!jt.isCanceled&&(U(xt),!xt&&(jt.reason===bo||jt.reason===uh)&&(H(!0),B(!1),q==="onBlur"&&K.commit(Y)))}),vs=Ie(()=>{Le(!1),pe.update({activeIndex:null,openMethod:null,scrollUpArrowVisible:!1,scrollDownArrowVisible:!1}),R?.(!1)});oa({enabled:!S,open:M,ref:ce,onComplete(){M||vs()}}),x.useImperativeHandle(S,()=>({unmount:vs}),[vs]);const it=Ie((xt,jt)=>{c?.(xt,jt),!jt.isCanceled&&re(xt)}),$t=Ie(xt=>{const jt=XE(xt.scrollHeight,xt.clientHeight),wt=mF(xt.scrollTop,jt),Er=wt>0,ar=wtLE(Z.current[xt]),onMatch(xt){M?pe.set("activeIndex",xt):it(ee.current[xt],qe(Qn))},onTyping(xt){he.current=xt}}),ts=x.useMemo(()=>ta(qt.reference,Dt.reference,nt.reference,rn.reference,me),[rn.reference,qt.reference,Dt.reference,nt.reference,me]),Fn=x.useMemo(()=>ta(mf,qt.floating,Dt.floating,nt.floating),[qt.floating,Dt.floating,nt.floating]),$n=Dt.item??mn;pe.useContextCallback("setValue",it),pe.useContextCallback("setOpen",Yn),pe.useContextCallback("handleScrollArrowVisibility",$t),pe.useContextCallback("onOpenChangeComplete",R),BE(()=>{pe.update({popupProps:Fn,triggerProps:ts})}),pe.useSyncedValues({id:Q,modal:k,multiple:T,value:Y,open:M,mounted:Te,transitionStatus:Ae,popupProps:Fn,triggerProps:ts,items:P,itemToStringLabel:C,itemToStringValue:E,isItemEqualToValue:D,openMethod:Ct});const Dn=x.useMemo(()=>({disabled:G,readOnly:j,required:w,multiple:T,highlightItemOnHover:I,itemProps:$n}),[G,j,w,T,I,$n]),en=sa(N,K.inputRef),cs=T?void 0:J,Et=x.useMemo(()=>!T||!Array.isArray(Y)||!J?null:Y.map(xt=>{const jt=Ca(xt,E);return s.jsx("input",{type:"hidden",form:b,name:J,value:jt,disabled:G},jt)}),[T,Y,b,J,E,G]);return s.jsxs(HE.Provider,{value:pe,children:[s.jsx(UE.Provider,{value:Dn,children:s.jsx(VE.Provider,{value:Vn,children:O})}),s.jsx("input",{...K.getValidationProps(G,{onFocus(){pe.state.triggerElement?.focus({focusVisible:!0})},onChange(xt){if(xt.nativeEvent.defaultPrevented||G||j)return;const jt=xt.currentTarget.value,wt=qe(Qn,xt.nativeEvent);function Er(){if(T)return;const ar=jt.toLowerCase();let Fr=ee.current.findIndex(al=>Ca(al,E).toLowerCase()===ar||So(al,C).toLowerCase()===ar);Fr===-1&&(Fr=ee.current.findIndex((al,ln)=>{const gc=ae.current[ln];return gc!=null&&gc.toLowerCase()===ar}));const Nn=ee.current[Fr];Nn!=null&&it(Nn,wt)}pe.set("forceMount",!0),queueMicrotask(Er)}}),id:Q&&cs==null?`${Q}-hidden-input`:void 0,form:b,name:cs,autoComplete:y,value:Tt,disabled:G,required:w&&!(T&&ms),readOnly:j,ref:en,style:J?ru:_i,tabIndex:-1,"aria-hidden":!0,suppressHydrationWarning:!0}),Et]})}function QE(e,t){return e??t}const Hh=5;function ZE(e,t){const a=gF(t);return e.clientX>=a.left-Hh&&e.clientX<=a.right+Hh&&e.clientY>=a.top-Hh&&e.clientY<=a.bottom+Hh}function gF(e){const t=e.getBoundingClientRect(),a=Cn(e);if($v)return t;const o=a.getComputedStyle(e,"::before"),c=a.getComputedStyle(e,"::after");if(!(o.content!=="none"||c.content!=="none"))return t;const f=parseFloat(o.width)||0,p=parseFloat(o.height)||0,h=parseFloat(c.width)||0,b=parseFloat(c.height)||0,y=Math.max(t.width,f,h),v=Math.max(t.height,p,b),j=y-t.width,w=v-t.height;return{left:t.left-j/2,right:t.right+j/2,top:t.top-w/2,bottom:t.bottom+w/2}}const xF="data-popup-side",bF=400,vF={...Yv,...Ti,popupSide:e=>e?{[xF]:e}:null,value:()=>null},yF=x.forwardRef(function(t,a){const{render:o,className:c,id:d,disabled:f=!1,nativeButton:p=!0,style:h,...b}=t,{setTouched:y,setFocused:v,validationMode:j,validation:w,state:k,disabled:S}=Na(),{labelId:N}=yl(),R=wo(),{readOnly:P,required:T,disabled:C}=sj(),E=S||C||f,D=R.useState("open"),I=R.useState("mounted"),O=R.useState("value"),_=R.useState("triggerProps"),z=R.useState("positionerElement"),H=R.useState("listElement"),B=R.useState("popupSide"),L=R.useState("id"),F=R.useState("labelId"),$=R.useState("hasSelectedValue"),X=I&&z?B:null,K=d??L,q=QE(N,F);co({id:d});const Q=Wn(z),G=x.useRef(null),{getButtonProps:J,buttonRef:Y}=na({disabled:E,native:p}),re=R.useStateSetter("triggerElement"),M=er(),U=er(),Z=er();x.useEffect(()=>{if(D)return Z.start(bF,()=>{R.context.selectionRef.current.allowUnselectedMouseUp=!0,R.context.selectionRef.current.allowSelectedMouseUp=!0}),()=>{Z.clear()};R.context.selectionRef.current={allowSelectedMouseUp:!1,allowUnselectedMouseUp:!1,dragY:0},U.clear()},[D,R,U,Z]);const ae=ta(_,{id:K,role:"combobox","aria-expanded":D,"aria-haspopup":"listbox","aria-controls":D?H?.id??Jm(z)?.id:void 0,"aria-labelledby":q,"aria-readonly":P||void 0,"aria-required":T||void 0,tabIndex:E?-1:0,onFocus(ue){v(!0),D&&R.context.alignItemWithTriggerActiveRef.current&&R.context.setOpen(!1,qe(Qn,ue.nativeEvent)),M.start(0,()=>{R.set("forceMount",!0)})},onBlur(ue){Ze(z,ue.relatedTarget)||(y(!0),v(!1),j==="onBlur"&&w.commit(O))},onMouseDown(ue){if(D)return;const ve=Gt(ue.currentTarget);function ee(he){if(!G.current)return;const te=he.target;Ze(G.current,te)||Ze(Q.current,te)||ZE(he,G.current)||R.context.setOpen(!1,qe(_1,he))}U.start(0,()=>{ve.addEventListener("mouseup",ee,{once:!0})})}},b,J),ce=w.getValidationProps(E,ae);ce.role="combobox";const W={...k,open:D,disabled:E,value:O,readOnly:P,popupSide:X,placeholder:!$};return yt("button",t,{ref:[a,G,Y,re],state:W,stateAttributesMapping:vF,props:ce})}),jF={value:()=>null},wF=x.forwardRef(function(t,a){const{className:o,render:c,children:d,placeholder:f,style:p,...h}=t,b=wo(),y=b.useState("value"),v=b.useState("items"),j=b.useState("itemToStringLabel"),w=b.useState("hasSelectedValue"),k=!w&&f!=null&&d==null,S=b.useState("hasNullItemLabel",k),N={value:y,placeholder:!w};let R=null;return typeof d=="function"?R=d(y):d!=null?R=d:k&&!S?R=f:Array.isArray(y)?R=fF(y,v,j):R=YE(y,v,j),yt("span",t,{state:N,ref:[a,b.context.valueRef],props:[{children:R},h],stateAttributesMapping:jF})}),SF=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t,b={open:wo().useState("open")};return yt("span",t,{state:b,ref:a,props:[{"aria-hidden":!0,children:"▼"},f],stateAttributesMapping:Kv})}),NF=x.forwardRef(function(t,a){const o=wo(),c=o.useState("mounted"),d=o.useState("forceMount");return c||d?s.jsx(mh,{ref:a,...t}):null}),WE=x.createContext(void 0);function kF(){const e=x.useContext(WE);if(!e)throw new Error(un(59));return e}function Uh(e,t){e&&Object.assign(e.style,t)}const CF={position:"relative",maxHeight:"100%",overflowX:"hidden",overflowY:"auto"},TF=20;function aj(e,t,a,o){const[c,d]=x.useState(!1);Me(()=>{if(!e||!t||a==null){d(!1);return}const f=Gt(a).documentElement.clientWidth,p=a.offsetWidth;d(f>0&&p>0&&p>=f-TF)},[e,t,a]),NE(e&&(!t||c),o)}const EF={position:"fixed"},AF=x.forwardRef(function(t,a){const{anchor:o,className:c,render:d,positionMethod:f,side:p,align:h,sideOffset:b,alignOffset:y,collisionBoundary:v="clipping-ancestors",collisionPadding:j,arrowPadding:w,sticky:k,disableAnchorTracking:S,alignItemWithTrigger:N=!0,collisionAvoidance:R=rT,style:P,...T}=t,C=wo(),E=FE(),D=C.useState("open"),I=C.useState("mounted"),O=C.useState("modal"),_=C.useState("value"),z=C.useState("openMethod"),H=C.useState("positionerElement"),B=C.useState("triggerElement"),L=C.useState("isItemEqualToValue"),F=C.useState("transitionStatus"),$=x.useRef(null),X=x.useRef(null),[K,q]=x.useState(N),Q=I&&K&&z!=="touch";!I&&K!==N&&q(N),x.useImperativeHandle(C.context.alignItemWithTriggerActiveRef,()=>Q),aj((Q||O)&&D,z==="touch",H,B);const G=Eh({anchor:o,floatingRootContext:E,positionMethod:f,mounted:I,side:p,sideOffset:b,align:h,alignOffset:y,arrowPadding:w,collisionBoundary:v,collisionPadding:j,sticky:k,disableAnchorTracking:S??Q,collisionAvoidance:R,keepMounted:!0}),J=Q?"none":G.side,Y=Q?EF:G.positionerStyles,re={open:D,side:J,align:G.align,anchorHidden:G.anchorHidden};Me(()=>{C.set("popupSide",G.side)},[C,G.side]);const M=C.useStateSetter("positionerElement"),U=Ah(t,re,{styles:Y,transitionStatus:F,props:T,refs:[a,M],hidden:!I,inert:!D}),Z=x.useRef(0),ae=Ie(W=>{if(C.context.valuesRef.current.length===0)return;const ue=Z.current;Z.current=W.size;const ve=qe(Qn);if(ue!==0&&!C.state.multiple&&_!==null&&uu(C.context.valuesRef.current,_,L)===-1){const he=C.context.initialValueRef.current,ke=he!=null&&uu(C.context.valuesRef.current,he,L)!==-1?he:null;C.context.setValue(ke,ve),ke===null&&(C.set("selectedIndex",null),C.context.selectedItemTextRef.current=null)}if(ue!==0&&C.state.multiple&&Array.isArray(_)){const ee=_.filter(he=>uu(C.context.valuesRef.current,he,L)!==-1);ee.length!==_.length&&(C.context.setValue(ee,ve),ee.length===0&&(C.set("selectedIndex",null),C.context.selectedItemTextRef.current=null))}if(D&&Q){C.update({scrollUpArrowVisible:!1,scrollDownArrowVisible:!1});const ee={height:""};Uh(H,ee),Uh(C.context.popupRef.current,ee)}}),ce=x.useMemo(()=>({...G,side:J,alignItemWithTriggerActive:Q,setControlledAlignItemWithTrigger:q,scrollUpArrowRef:$,scrollDownArrowRef:X}),[G,J,Q,q]);return s.jsx(nj,{elementsRef:C.context.listRef,labelsRef:C.context.labelsRef,onMapChange:ae,children:s.jsxs(WE.Provider,{value:ce,children:[I&&O&&s.jsx(Dh,{inert:Rh(!D),cutout:B}),U]})})}),Vh="base-ui-disable-scrollbar",JE={className:Vh,getElement(e){return s.jsx("style",{nonce:e,href:Vh,precedence:"base-ui:low",children:`.${Vh}{scrollbar-width:none}.${Vh}::-webkit-scrollbar{display:none}`})}},RF=x.createContext(void 0);function eA(e){return x.useContext(RF)}const OF=x.createContext(void 0),MF={disableStyleElements:!1};function DF(){return x.useContext(OF)??MF}const tA="--transform-origin",IF={...Wc,...uo},PF=x.forwardRef(function(t,a){const{render:o,className:c,style:d,finalFocus:f,...p}=t,h=wo(),{multiple:b,readOnly:y,highlightItemOnHover:v}=sj(),j=FE(),{side:w,align:k,alignItemWithTriggerActive:S,isPositioned:N,setControlledAlignItemWithTrigger:R}=kF(),P=eA()!=null,T=gf(),{nonce:C,disableStyleElements:E}=DF(),D=h.useState("id"),I=h.useState("open"),O=h.useState("openMethod"),_=h.useState("mounted"),z=h.useState("popupProps"),H=h.useState("transitionStatus"),B=h.useState("triggerElement"),L=h.useState("positionerElement"),F=h.useState("listElement"),$=x.useRef(!1),X=x.useRef(!1),K=x.useRef({}),q=tu(),Q=Ie(re=>{if(!L||!h.context.popupRef.current||!X.current)return;const M=L.style.top==="0px",U=L.style.bottom==="0px";if($.current||!S||!M&&!U){h.context.handleScrollArrowVisibility(re);return}const Z=sA(L),ae=vf(L.getBoundingClientRect().height,"y",Z),ce=Gt(L),W=Cn(L),ue=W.getComputedStyle(L),ve=parseFloat(ue.marginTop),ee=parseFloat(ue.marginBottom),he=nA(W.getComputedStyle(h.context.popupRef.current)),te=Math.min(ce.documentElement.clientHeight-ve-ee,he),ke=re.scrollTop,le=Fh(re);let de=null;const Se=oe=>{L.style.height=`${oe}px`},Te=M?le-ke:ke,Le=Math.min(ae+Te,te);if(Te<=Tl){const oe=Li(Te,0,te-ae);oe>0&&Se(ae+oe),re.scrollTop=M?le:0,te-(ae+oe)<=Tl&&($.current=!0),h.context.handleScrollArrowVisibility(re);return}if(te-Le>Tl)de=M?1/0:0;else if(U&&keTl&&(re.scrollTop=oe)}Ae>=te-Tl&&($.current=!0),h.context.handleScrollArrowVisibility(re)});x.useImperativeHandle(h.context.scrollHandlerRef,()=>Q,[Q]),oa({open:I,ref:h.context.popupRef,onComplete(){I&&h.context.onOpenChangeComplete(!0)}});const G={open:I,transitionStatus:H,side:w,align:k};Me(()=>{!L||!h.context.popupRef.current||Object.keys(K.current).length||(K.current={top:L.style.top||"0",left:L.style.left||"0",right:L.style.right,height:L.style.height,bottom:L.style.bottom,minHeight:L.style.minHeight,maxHeight:L.style.maxHeight,marginTop:L.style.marginTop,marginBottom:L.style.marginBottom})},[h,L]),Me(()=>{I||S||(X.current=!1,$.current=!1,Uh(L,K.current))},[I,S,L]),Me(()=>{const re=h.context.popupRef.current;if(!I||!B||!L||!re||S&&!N||h.state.transitionStatus==="ending")return;if(X.current=!0,re.style.removeProperty(tA),!S){q.request(()=>h.context.handleScrollArrowVisibility(F||re));return}const M=_F(re);try{let U=h.context.selectedItemTextRef.current;U?.isConnected||(U=!h.select("hasSelectedValue")&&h.context.firstItemTextRef.current?.isConnected?h.context.firstItemTextRef.current:null);const Z=h.context.valueRef.current,ae=Cn(L),ce=ae.getComputedStyle(L),W=ae.getComputedStyle(re),ue=Gt(B),ve=sA(B),ee=$h(B.getBoundingClientRect(),ve),he=$h(L.getBoundingClientRect(),ve),te=ee.height,ke=F||re,le=ke.scrollHeight,de=parseFloat(W.borderBottomWidth),Se=parseFloat(ce.marginTop)||10,Te=parseFloat(ce.marginBottom)||10,Le=parseFloat(ce.minHeight)||100,Ae=nA(W),oe=5,me=5,pe=20,Ce=ue.documentElement.clientHeight-Se-Te,Ne=ue.documentElement.clientWidth,be=Ce-ee.bottom+te;let De,Ge=T==="rtl"?ee.right-he.width:ee.left,Ct=0;if(U&&Z){const rn=$h(Z.getBoundingClientRect(),ve);De=$h(U.getBoundingClientRect(),ve),Ge=he.left+(T==="rtl"?rn.right-De.right:rn.left-De.left);const nt=rn.top-ee.top+rn.height/2;Ct=De.top-he.top+De.height/2-nt}const Tt=be+Ct+Te+de;let Mt=Math.min(Ce,Tt);const ot=Ce-Se-Te,Kn=Tt-Mt,ms=Ne-me;L.style.left=`${Li(Ge,oe,ms-he.width)}px`,L.style.height=`${Mt}px`,L.style.maxHeight="none",L.style.marginTop=`${Se}px`,L.style.marginBottom=`${Te}px`,re.style.height="100%";const Yn=Fh(ke),vs=Kn>=Yn-Tl;vs&&(Mt=Math.min(Ce,he.height)-(Kn-Yn));const it=ee.topCe-pe||Math.ceil(Mt)+Tl=ot?"0":`${rn}px`,L.style.height=`${Mt}px`,ke.scrollTop=Fh(ke)}else L.style.bottom="0",ke.scrollTop=Kn;if(De){const rn=he.top,nt=he.height,Dt=De.top+De.height/2,qt=Li(nt>0?(Dt-rn)/nt*100:50,0,100);re.style.setProperty(tA,`50% ${qt}%`)}(Vn===Ce||Mt>=Ae)&&($.current=!0),h.context.handleScrollArrowVisibility(ke),v&&h.state.selectedIndex===null&&h.state.activeIndex===null&&h.context.listRef.current[0]!=null&&h.set("activeIndex",0)}finally{M()}},[h,I,L,B,S,R,q,F,v,T,N]),x.useEffect(()=>{if(!S||!L||!I)return;const re=Cn(L);function M(U){h.context.setOpen(!1,qe(T4,U))}return St(re,"resize",M)},[h,S,L,I]);const J={...F?{role:"presentation"}:{role:"listbox","aria-multiselectable":b||void 0,"aria-readonly":y||void 0,id:`${D}-list`},onKeyDown(re){P&&Oh.has(re.key)&&re.stopPropagation()},onScroll(re){F||Q(re.currentTarget)},...S&&{style:F?{height:"100%"}:CF},className:!F&&S?JE.className:void 0},Y=yt("div",t,{ref:[a,h.context.popupRef],state:G,stateAttributesMapping:IF,props:[z,J,xf(H),p]});return s.jsxs(x.Fragment,{children:[!E&&JE.getElement(C),s.jsx(hh,{context:j,modal:!1,disabled:!_,openInteractionType:O,returnFocus:f,restoreFocus:!0,children:Y})]})});function nA(e){const t=e.maxHeight;return t.endsWith("px")&&parseFloat(t)||1/0}function Fh(e){return XE(e.scrollHeight,e.clientHeight)}function sA(e){return kT.getScale(e)}function vf(e,t,a){return e/a[t]}function $h(e,t){return nf({x:vf(e.x,"x",t),y:vf(e.y,"y",t),width:vf(e.width,"x",t),height:vf(e.height,"y",t)})}const rA=[["transform","none"],["scale","1"],["translate","0 0"]];function _F(e){const{style:t}=e,a={};for(const[o,c]of rA)a[o]=t.getPropertyValue(o),t.setProperty(o,c,"important");return()=>{for(const[o]of rA){const c=a[o];c?t.setProperty(o,c):t.removeProperty(o)}}}const aA=x.createContext(void 0);function lj(){const e=x.useContext(aA);if(!e)throw new Error(un(57));return e}const LF=x.memo(x.forwardRef(function(t,a){const{render:o,className:c,style:d,value:f=null,label:p,disabled:h=!1,nativeButton:b=!1,...y}=t,v=x.useRef(null),j=tj({guess:!0,label:p,textRef:v}),w=wo(),{itemProps:k,multiple:S,disabled:N,readOnly:R}=sj(),P=N||h,T=w.useState("isActive",j.index),C=w.useState("open"),E=w.useState("isSelected",f),D=w.useState("isSelectedByFocus",j.index),I=w.useState("isItemEqualToValue"),O=j.index,_=x.useRef(null);Me(()=>{const G=w.context.valuesRef.current;return G[O]=f,()=>{delete G[O]}},[O,f,w]),Me(()=>{const G=w.state.value,J=w.state.selectedIndex;let Y=J,re;S&&Array.isArray(G)?(Y=qE(O,f,w.context.valuesRef.current,G,I,J),re=Y===O,O===J&&!re&&(w.context.selectedItemTextRef.current=null)):(re=G!==void 0&&ca(f,G,I),re&&(Y=O)),w.set("selectedIndex",Y),re&&v.current&&(w.context.selectedItemTextRef.current=v.current)},[O,S,I,w,f]);const z=x.useRef("mouse"),H=x.useRef(!1),{getButtonProps:B,buttonRef:L}=na({disabled:P,focusableWhenDisabled:!0,native:b,composite:!0}),F={disabled:P,selected:E,highlighted:T};function $(G){if(N||R)return;const J=w.state.value;if(S){const Y=Array.isArray(J)?J:[],re=E?GE(Y,f,I):[...Y,f];w.context.setValue(re,qe(af,G))}else w.context.setValue(f,qe(af,G)),w.context.setOpen(!1,qe(af,G))}function X(){w.context.selectionRef.current.dragY=0}const K={role:"option","aria-selected":E,tabIndex:C&&T?0:-1,onKeyDown(G){w.set("activeIndex",O),G.key===" "&&w.context.typingRef.current&&G.preventDefault()},onClick(G){const J=z.current!=="touch",Y=G.nativeEvent.pointerType,re=J&&eh(G.nativeEvent)&&(Y!==void 0||T),M=J&&!re&&!H.current;H.current=!1,!(P||M)&&$(G.nativeEvent)},onPointerEnter(G){z.current=G.pointerType},onPointerMove(G){if(G.pointerType==="mouse"&&G.buttons===1){const J=w.context.selectionRef.current;J.dragY+=G.movementY,J.dragY**2>=64&&(J.allowUnselectedMouseUp=!0)}},onPointerDown(G){z.current=G.pointerType,H.current=!0,X()},onMouseUp(){if(X(),P||z.current==="touch"||H.current)return;const G=!w.context.selectionRef.current.allowSelectedMouseUp&&E,J=!w.context.selectionRef.current.allowUnselectedMouseUp&&!E;G||J||(H.current=!0,_.current?.click(),H.current=!1)}},q=yt("div",t,{ref:[L,a,j.ref,_],state:F,props:[k,K,y,B]}),Q=x.useMemo(()=>({selected:E,index:O,textRef:v,selectedByFocus:D}),[E,O,v,D]);return s.jsx(aA.Provider,{value:Q,children:q})})),zF=x.forwardRef(function(t,a){const{selected:o}=lj();return t.keepMounted||o?s.jsx(BF,{...t,ref:a}):null}),BF=x.memo(x.forwardRef((e,t)=>{const{render:a,className:o,style:c,keepMounted:d,...f}=e,{selected:p}=lj(),h=x.useRef(null),{transitionStatus:b,setMounted:y}=Oi(p),j=yt("span",e,{ref:[t,h],state:{selected:p,transitionStatus:b},props:[{"aria-hidden":!0,children:"✔️"},f],stateAttributesMapping:uo});return oa({batch:!0,enabled:!p,open:p,ref:h,onComplete(){p||y(!1)}}),j})),HF=x.memo(x.forwardRef(function(t,a){const{index:o,textRef:c,selectedByFocus:d}=lj(),f=wo(),{render:p,className:h,style:b,...y}=t,v=x.useCallback(w=>{w&&(o===0&&(f.context.firstItemTextRef.current=w),d&&(f.context.selectedItemTextRef.current=w))},[f,o,d]);return yt("div",t,{ref:[v,a,c],props:y})})),dt=hF,ft=wF;function pt({className:e,children:t,...a}){return s.jsxs(yF,{"data-slot":"select-trigger",className:Ue("inline-flex h-[30px] min-w-0 cursor-pointer items-center justify-between gap-1.5 rounded-md border border-control-border bg-control px-2.5","[&>span]:min-w-0 [&>span]:truncate","text-[12.5px] font-normal text-foreground","transition-colors duration-150 ease-out","hover:border-control-border-hover hover:bg-control-hover","focus-visible:border-primary focus-visible:shadow-focus focus-visible:outline-none","data-disabled:cursor-not-allowed data-disabled:bg-control data-disabled:text-muted-foreground data-disabled:opacity-60",e),...a,children:[t,s.jsx(SF,{className:"flex flex-none text-muted-foreground transition-transform duration-[180ms] data-popup-open:rotate-180",children:s.jsx("svg",{viewBox:"0 0 10 6",className:"size-2.5","aria-hidden":"true",children:s.jsx("path",{d:"M1 1l4 4 4-4",stroke:"currentColor",strokeWidth:"1.4",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"})})})]})}function mt({className:e,sideOffset:t=4,children:a,...o}){return s.jsx(NF,{children:s.jsx(AF,{sideOffset:t,alignItemWithTrigger:!1,className:"z-[35]",children:s.jsx(PF,{"data-slot":"select-content",className:Ue("max-h-[260px] min-w-[var(--anchor-width)] overflow-y-auto overscroll-contain rounded-lg border border-border-strong bg-raised p-[5px] shadow-3","outline-none","data-open:animate-in data-open:fade-in-0","data-closed:animate-out data-closed:fade-out-0",e),...o,children:a})})})}function $e({className:e,children:t,...a}){return s.jsxs(LF,{"data-slot":"select-item",className:Ue("flex min-h-7 cursor-pointer items-center gap-2 rounded-sm px-[9px] text-[12.5px] leading-[1.4] text-foreground select-none","transition-colors duration-[120ms] ease-out","data-[highlighted]:bg-nav-hover","data-[selected]:bg-primary-soft data-[selected]:font-semibold data-[selected]:text-primary-fg","data-[highlighted]:data-[selected]:bg-primary-tint","data-disabled:pointer-events-none data-disabled:font-normal data-disabled:text-muted-foreground",e),...a,children:[s.jsx(HF,{className:"min-w-0 flex-1 truncate",children:t}),s.jsx(zF,{className:"flex flex-none text-primary",children:s.jsx("svg",{viewBox:"0 0 12 12",className:"size-3","aria-hidden":"true",children:s.jsx("path",{d:"M2.5 6.2 4.8 8.5 9.5 3.8",stroke:"currentColor",strokeWidth:"1.8",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"})})})]})}function En({options:e,value:t,onValueChange:a,disabled:o=!1,className:c,...d}){const f=x.useRef(null),p=x.useRef(new Map),[h,b]=x.useState({left:0,width:0,ready:!1}),[y,v]=x.useState(!1),j=x.useCallback(()=>{const w=f.current,k=p.current.get(t);if(!w||!k){b(T=>T.ready?{...T,ready:!1}:T);return}const S=w.getBoundingClientRect(),N=k.getBoundingClientRect(),R=N.left-S.left-w.clientLeft,P=N.width;b(T=>T.ready&&T.left===R&&T.width===P?T:{left:R,width:P,ready:!0})},[t]);return x.useLayoutEffect(()=>{j();const w=f.current;if(!w||typeof ResizeObserver>"u")return;const k=new ResizeObserver(()=>j());k.observe(w);for(const S of p.current.values())k.observe(S);return()=>k.disconnect()},[j,e]),x.useEffect(()=>{if(!h.ready||y)return;const w=requestAnimationFrame(()=>v(!0));return()=>cancelAnimationFrame(w)},[h.ready,y]),s.jsxs(zE,{ref:f,"data-slot":"segmented-control",className:Ue("relative inline-flex gap-0.5 rounded-md border border-control-border bg-control p-0.5",c),value:t,disabled:o,onValueChange:w=>a(w),...d,children:[s.jsx("span",{"aria-hidden":"true","data-slot":"segmented-thumb","data-ready":h.ready?"true":"false","data-animate":y?"true":"false",className:Ue("pointer-events-none absolute top-0.5 bottom-0.5 left-0 rounded-sm bg-primary-soft","data-[ready=false]:opacity-0","data-[animate=true]:transition-[transform,width] data-[animate=true]:duration-200 data-[animate=true]:ease-in-out"),style:{transform:`translateX(${h.left}px)`,width:h.width}}),e.map(w=>s.jsxs(PE,{value:w.value,"data-slot":"segmented-item",disabled:w.disabled,"data-zero":w.count===0?"true":void 0,className:Ue("group/seg relative z-[1] inline-flex h-6 items-center gap-[5px] rounded-sm border-0 bg-transparent px-2.5","text-xs font-medium whitespace-nowrap text-subtle select-none","transition-[background-color,color] duration-150 ease-out","hover:bg-nav-hover hover:text-foreground","data-checked:bg-transparent data-checked:text-primary-fg data-checked:hover:bg-transparent","data-disabled:cursor-not-allowed data-disabled:opacity-40","data-[zero=true]:data-unchecked:opacity-45"),ref:k=>{k?p.current.set(w.value,k):p.current.delete(w.value)},children:[w.label,w.count!==void 0&&s.jsx("span",{className:Ue("min-w-4 rounded-pill bg-surface-3 px-[5px] text-center text-[10.5px] font-semibold tabular-nums text-muted-foreground","group-data-checked/seg:bg-primary-tint group-data-checked/seg:text-primary-fg"),children:w.count})]},w.value))]})}const UF=x.createContext(void 0);function VF(){return x.useContext(UF)}const FF=x.forwardRef(function(t,a){const{className:o,defaultPressed:c=!1,disabled:d=!1,form:f,onPressedChange:p,pressed:h,render:b,type:y,value:v,nativeButton:j=!0,style:w,...k}=t,S=ka(v||void 0),N=VF(),R=N?.value??[],P=(d||N?.disabled)??!1,[T,C]=Ka({controlled:N?S!==void 0&&R.indexOf(S)>-1:h,default:c,name:"Toggle",state:"pressed"}),{getButtonProps:E,buttonRef:D}=na({disabled:P,native:j}),I={disabled:P,pressed:T},O=[D,a],_=[{"aria-pressed":T,onClick(B){const L=!T,F=qe(Qn,B.nativeEvent);p?.(L,F),!F.isCanceled&&(S&&N?.setGroupValue?.(S,L,F),!F.isCanceled&&C(L))}},k,E],z=yt("button",t,{enabled:!N,state:I,ref:O,props:_}),H=x.useMemo(()=>({disabled:P,focusableWhenDisabled:!1}),[P]);return N?s.jsx(ME,{tag:"button",render:b,className:o,style:w,metadata:H,state:I,refs:O,props:_}):z}),$F=Qc(["inline-flex shrink-0 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap border","font-medium transition-[background-color,border-color,color] duration-150 ease-out","outline-none select-none disabled:pointer-events-none disabled:opacity-45","[&_svg]:pointer-events-none [&_svg]:shrink-0","data-pressed:border-primary-bd data-pressed:bg-primary-soft data-pressed:font-semibold data-pressed:text-primary-fg","data-pressed:hover:bg-primary-tint"],{variants:{variant:{default:"border-transparent bg-transparent text-subtle hover:bg-nav-hover hover:text-foreground",outline:"border-control-border bg-control text-foreground shadow-1 hover:border-control-border-hover hover:bg-control-hover"},size:{default:"h-[30px] rounded-md px-3 text-[12.5px]",xs:"h-6 rounded-sm px-2 text-[11.5px]",sm:"h-[26px] rounded-sm px-2.5 text-[12px]",lg:"h-9 rounded-md px-4 text-[13px]"}},defaultVariants:{variant:"default",size:"default"}});function qF({className:e,variant:t,size:a,...o}){return s.jsx(FF,{"data-slot":"toggle",className:Ue($F({variant:t,size:a}),e),...o})}function GF(e,t,a,o,c,d,f,p,h,b=2){const y=u4(a.current,{event:e,orientation:o,loopFocus:c,rtl:d,cols:b,disabledIndices:f,minIndex:p,maxIndex:h,prevIndex:t>h?p:t,stopEvent:!0});return ho(a.current,y)?void 0:y}const lA=x.createContext(void 0),oA=x.createContext(void 0),iA=x.createContext(void 0),cA=x.createContext(!1),uA=x.createContext("");function Ta(){const e=x.useContext(lA);if(!e)throw new Error(un(22));return e}function qh(){const e=x.useContext(oA);if(!e)throw new Error(un(23));return e}function yf(){const e=x.useContext(iA);if(!e)throw new Error(un(24));return e}function dA(){return x.useContext(uA)}function KF(){return x.useContext(cA)}const YF={id:e=>e.id,labelId:e=>e.labelId,items:e=>e.items,selectedValue:e=>e.selectedValue,hasSelectionChips:e=>{const t=e.selectedValue;return Array.isArray(t)&&t.length>0},hasSelectedValue:e=>{const{selectedValue:t,selectionMode:a}=e;return t==null?!1:a==="multiple"&&Array.isArray(t)?t.length>0:!0},hasNullItemLabel:(e,t)=>t?KE(e.items):!1,open:e=>e.open,mounted:e=>e.mounted,forceMounted:e=>e.forceMounted,inline:e=>e.inline,activeIndex:e=>e.activeIndex,selectedIndex:e=>e.selectedIndex,isActive:(e,t)=>e.activeIndex===t,isSelected:(e,t)=>{const a=e.isItemEqualToValue,o=e.selectedValue;return Array.isArray(o)?o.some(c=>ca(t,c,a)):ca(t,o,a)},transitionStatus:e=>e.transitionStatus,popupProps:e=>e.popupProps,listProps:e=>e.listProps,inputProps:e=>e.inputProps,triggerProps:e=>e.triggerProps,itemProps:e=>e.itemProps,positionerElement:e=>e.positionerElement,listElement:e=>e.listElement,popupId:e=>e.popupId,triggerElement:e=>e.triggerElement,inputElement:e=>e.inputElement,inputGroupElement:e=>e.inputGroupElement,popupSide:e=>e.popupSide,openMethod:e=>e.openMethod,inputInsidePopup:e=>e.inputInsidePopup,inputOwnsFormValue:e=>e.inputOwnsFormValue,selectionMode:e=>e.selectionMode,name:e=>e.name,form:e=>e.form,disabled:e=>e.disabled,readOnly:e=>e.readOnly,required:e=>e.required,grid:e=>e.grid,virtualized:e=>e.virtualized,itemToStringLabel:e=>e.itemToStringLabel,isItemEqualToValue:e=>e.isItemEqualToValue,modal:e=>e.modal,autoHighlight:e=>e.autoHighlight};function fA(e){return e==null?void 0:`${e}-popup`}function XF(e,t){return(a,o)=>a==null?!1:e.contains(a,o,t)}const pA=new Map;function QF(e={}){const t={usage:"search",sensitivity:"base",ignorePunctuation:!0,...e},a=`${hy(e.locale)}|${JSON.stringify(t)}`,o=pA.get(a);if(o)return o;const c=new Intl.Collator(e.locale,t),d={contains(f,p,h){if(!p)return!0;const b=So(f,h);for(let y=0;y<=b.length-p.length;y+=1)if(c.compare(b.slice(y,y+p.length),p)===0)return!0;return!1},startsWith(f,p,h){if(!p)return!0;const b=So(f,h);return c.compare(b.slice(0,p.length),p)===0},endsWith(f,p,h){if(!p)return!0;const b=So(f,h),y=p.length;return b.length>=y&&c.compare(b.slice(b.length-y),p)===0}};return pA.set(a,d),d}const ZF=QF;function WF(e,t=!1){const{overflowY:a}=jr(e);return a!=="auto"&&a!=="scroll"?!1:t?e.clientHeight>0:e.scrollHeight>e.clientHeight}const mA=Symbol("none"),oj={value:mA,index:-1};function JF(e,t,a){const o=e.get(t);if(o!==void 0||a===Lh)return o;for(const[c,d]of e)if(ca(c,t,a))return d}function e6(e){const{id:t,onOpenChangeComplete:a,defaultSelectedValue:o=null,selectedValue:c,onSelectedValueChange:d,defaultInputValue:f,inputValue:p,open:h,defaultOpen:b=!1,selectionMode:y,onItemHighlighted:v,name:j,form:w,disabled:k=!1,readOnly:S=!1,required:N=!1,inputRef:R,grid:P=!1,items:T,filteredItems:C,filter:E,filterQuery:D,openOnInputClick:I=!0,autoHighlight:O=!1,keepHighlight:_=!1,highlightItemOnHover:z=!0,loopFocus:H=!0,itemToStringLabel:B,itemToStringValue:L,isItemEqualToValue:F=Lh,virtualized:$=!1,inline:X=!1,fillInputOnItemPress:K=!0,modal:q=!1,limit:Q=-1,autoComplete:G="list",formAutoComplete:J,locale:Y,submitOnItemClick:re=!1}=e,{clearErrors:M}=Zc(),{setDirty:U,validityData:Z,setFilled:ae,name:ce,disabled:W,setTouched:ue,setFocused:ve,validationMode:ee,validation:he}=Na(),te=gf(),ke=co({id:t}),le=ZF({locale:Y}),de=Array.isArray(T)?null:T;if(de&&typeof de.label!="function")throw new Error(un(100));const Se=de?de.data:T,Te=de?.value,Le=Te?void 0:Se,Ae=x.useMemo(()=>{if(!C||!Te)return;const Oe=Bh(C),Be=Oe.map(Te);let lt;return{values:Be,findItem(Qt,In){if(!lt){lt=new Map;for(let gn=0;gnde?Oe=>de.label(Oe,F,Be=>{const lt=Ae?.findItem(Be,F);return lt!=null?de.itemLabel(lt):So(Be,B)}):B,[de,B,Ae,F]),me=x.useMemo(()=>de?Object.assign(Oe=>de.itemLabel(Oe),{selected:Oe=>So(Oe,oe)}):B,[de,oe,B]);function pe(Oe){return So(Oe,oe)}const[Ce,Ne]=x.useState(!1),[be,De]=x.useState(null),Ge=x.useRef(be),Ct=x.useRef([]),Tt=x.useRef([]),Mt=x.useRef(null),ot=x.useRef(null),Kn=x.useRef(null),ms=x.useRef(null),Yn=x.useRef(null),vs=x.useRef(!0),it=x.useRef(!1),$t=x.useRef(null),Vn=x.useRef(null),rn=x.useRef(null),nt=x.useRef(oj),Dt=x.useRef(null),qt=x.useRef([]),ts=x.useRef(null),Fn=W||k,$n=ce??j,Dn=y==="multiple",en=y==="single",cs=p!==void 0||f!==void 0,Et=Se!==void 0,xt=C!==void 0;let jt;O==="always"?jt="always":jt=O?"input-change":!1;const[wt,Er]=Ka({controlled:c,default:Dn?o??Pr:o,name:"Combobox",state:"selectedValue"}),ar=x.useMemo(()=>E===null?()=>!0:E!==void 0?E:XF(le,me),[E,le,me]),Fr=Ps(()=>cs?f??"":en?pe(wt):"").current,[Nn,al]=Ka({controlled:p,default:Fr,name:"Combobox",state:"inputValue"}),[ln,gc]=Ka({controlled:h,default:b,name:"Combobox",state:"open"}),sb=rj(Se),hr=!ln&&be!==null?be:String(Nn).trim(),Pa=en?pe(wt):"",Go=en&&!Ce&&hr!==""&&Pa.length===hr.length&&le.contains(Pa,hr),Ko=Go?"":D??hr,$p=Et&&xt&&Go&&(!de||de.hasValue(wt,F)),xc=x.useMemo(()=>Se?Bh(Se):Pr,[Se]),Yo=x.useMemo(()=>{if(C&&!$p)return C;if(!Se)return Pr;if(sb){const Be=Se,lt=[];let Qt=0;for(const In of Be){if(Q>-1&&Qt>=Q)break;const gn=Q>-1?Q-Qt:1/0,Pn=Ko===""?In.items.slice(0,gn):[];if(Ko!=="")for(const hs of In.items){if(Pn.length>=gn)break;ar(hs,Ko,me)&&Pn.push(hs)}if(Pn.length>0){const hs={...In,items:Pn};lt.push(hs),Qt+=Pn.length}}return lt}if(Ko==="")return Q>-1?xc.slice(0,Q):xc;const Oe=[];for(const Be of xc){if(Q>-1&&Oe.length>=Q)break;ar(Be,Ko,me)&&Oe.push(Be)}return Oe},[C,$p,Se,sb,Ko,Q,ar,me,xc]),Os=x.useMemo(()=>{if(Ae&&Yo===C)return Ae.values;const Oe=Bh(Yo);return Te?Oe.map(Be=>Te(Be)):Oe},[Yo,C,Ae,Te]),et=Ps(()=>{let Oe=null;return X&&ln&&Et&&y!=="none"&&(Oe=bf(Os,wt,F,Dn)),new iu({id:ke,labelId:void 0,selectedValue:wt,open:ln,items:Le,selectionMode:y,name:$n,form:w,disabled:Fn,readOnly:S,required:N,grid:P,virtualized:$,openOnInputClick:I,itemToStringLabel:oe,isItemEqualToValue:F,modal:q,autoHighlight:jt,submitOnItemClick:re,hasInputValue:cs,mounted:!1,forceMounted:!1,transitionStatus:"idle",inline:X,activeIndex:null,selectedIndex:Oe,popupProps:{},listProps:{},inputProps:{},triggerProps:{},itemProps:mn,positionerElement:null,listElement:null,popupId:void 0,triggerElement:null,inputElement:null,inputGroupElement:null,popupSide:null,openMethod:null,inputInsidePopup:!0,inputOwnsFormValue:y==="none"},{onOpenChangeComplete:Kt,setOpen:Kt,setInputValue:Kt,setSelectedValue:Kt,setIndices:Kt,handleSelection:Kt,forceMount:Kt,requestSubmit:Kt,listRef:Ct,labelsRef:Tt,popupRef:Mt,emptyRef:Yn,inputRef:ot,startDismissRef:Kn,endDismissRef:ms,keyboardActiveRef:vs,chipsContainerRef:$t,clearRef:Vn,valuesRef:qt,pointerDownItemRef:ts,selectionEventRef:rn},YF)}).current,Bl=y==="none"?Nn:wt,rb=x.useMemo(()=>y==="none"?Bl:Array.isArray(wt)?wt.map(Oe=>Ca(Oe,L)):Ca(wt,L),[Bl,L,y,wt]),_a=Ie(v),Ms=Ie(a),Ys=et.useState("activeIndex"),Xo=et.useState("selectedIndex"),bc=et.useState("positionerElement"),ab=et.useState("listElement"),vc=et.useState("triggerElement"),yc=et.useState("inputElement"),jc=et.useState("inputGroupElement"),Ds=et.useState("inline"),lr=et.useState("inputInsidePopup"),Hl=et.useState("inputOwnsFormValue"),Ul=en&&!lr&&Nn===Pa,wc=Wn(vc),{mounted:Qo,setMounted:ys,transitionStatus:qp}=Oi(ln),{openMethod:lb,triggerProps:Gp}=EE(ln),Vl=Ie(()=>rb);nu(lr?wc:ot,ke,Bl,Vl,!Fn,j);const Fl=Ie(()=>{Se?Tt.current=Os.map(pe):et.set("forceMounted",!0)}),Zo=Ie((Oe,Be,lt)=>{if(Be===-1){if(nt.current===oj)return;nt.current=oj}else nt.current={value:Oe,index:Be};_a(Oe,E4(lt,void 0,{index:Be}))}),$r=Ie(Oe=>{const Be={};Oe.activeIndex!==void 0&&(Be.activeIndex=Oe.activeIndex),Oe.selectedIndex!==void 0&&(Be.selectedIndex=Oe.selectedIndex),et.update(Be);const lt=Oe.activeIndex;if(lt===void 0)return;const Qt=Oe.type||Qn;lt===null?Zo(void 0,-1,Qt):Zo(qt.current[lt],lt,Qt)}),qr=Ie((Oe,Be)=>{if(e.onInputValueChange?.(Oe,Be),!Be.isCanceled){if(it.current=Be.reason===Ya,Be.reason===lf){ln&&be!==null&&De(null);const lt=Be.event,Qt=lt.inputType;if(lt.type==="compositionend"||Qt!=null&&Qt!==""&&Qt!=="insertReplacementText"){const gn=Oe.trim()!=="";gn&&Ne(!0),Dt.current={hasQuery:gn};const Pn=et.state.listElement;if(!et.state.virtualized&&Pn){const hs=Mt.current;for(const Ar of Yc(Pn.firstElementChild??Pn)){if(!pn(Ar)||(hs?!Ze(hs,Ar):Ar.getAttribute("role")==="dialog"))break;if(WF(Ar)){Ar.scrollTop=0;break}}}gn&&jt&&et.state.activeIndex==null&&(ln||Ds)&&et.set("activeIndex",0)}}else Be.reason===Ya&&Oe===""&&et.state.inputInsidePopup&&(Dt.current={hasQuery:!1,selection:!0});al(Oe)}}),ob=Ie(Oe=>{const Be=!Oe&&lr&&!Ds&&Nn!==""&&(String(Nn).trim()===be||Nn===Pa);!Oe&&(Be||Nn===""||Ul)&&Ne(!1),De(null),Be&&qr("",qe(Ya))}),It=Ie((Oe,Be)=>{if(ln!==Oe&&(Be.reason===su&&Et&&Os.length===0&&!Yn.current&&Be.allowPropagation(),e.onOpenChange?.(Oe,Be),!Be.isCanceled&&(Oe&&be!==null&&ob(Be.reason===lf),!Oe&&Ce&&(en?(Ds||De(hr),hr===""&&Ne(!1)):Dn&&(Ds||De(hr),lr&&$r({activeIndex:null}),(!lr||Ds)&&qr("",qe(Ya,Be.event,void 0,{isItemPress:Be.reason===af})))),gc(Oe),!Oe&&lr&&(Be.reason===bo||Be.reason===uh)&&(ue(!0),ve(!1),ee==="onBlur")))){const lt=y==="none"?Nn:wt;he.commit(lt)}}),Sc=Ie((Oe,Be)=>{if(d?.(Oe,Be),Be.isCanceled)return;Er(Oe),(y==="none"&&Mt.current&&K||en&&!et.state.inputInsidePopup)&&qr(pe(Oe),qe(Be.reason,Be.event))}),od=Ie((Oe,Be)=>{const lt=fs(Oe),Qt=rn.current??Oe;rn.current=null;const In=qe(af,Qt),gn=lt?.closest("a")?.getAttribute("href");if(gn){gn.startsWith("#")&&It(!1,In);return}if(Dn){const Pn=Array.isArray(wt)?wt:[],hs=zh(Pn,Be,F),Ar=hs?GE(Pn,Be,F):[...Pn,Be];if(Sc(Ar,In),In.isCanceled||!(ot.current?ot.current.value.trim()!=="":!1))return;if(et.state.inputInsidePopup){qr("",qe(Ya,In.event,void 0,{isItemPress:!0}));const Kr=Dt.current;Kr&&!hs&&(Kr.toggledValue=Be)}else It(!1,In)}else{if(Sc(Be,In),In.isCanceled)return;It(!1,In)}}),id=Ie(()=>{const Oe=he.inputRef.current?.form??et.state.inputElement?.form;Oe&&typeof Oe.requestSubmit=="function"&&Oe.requestSubmit()}),Gr=Ie(()=>{if(ys(!1),Ms?.(!1),Ne(!1),De(null),$r(y==="none"?{activeIndex:null,selectedIndex:null}:{activeIndex:null}),Dn&&ot.current&&ot.current.value!==""&&!it.current&&qr("",qe(Ya)),en)if(et.state.inputInsidePopup)ot.current&&ot.current.value!==""&&qr("",qe(Ya));else{const Oe=pe(wt);ot.current&&ot.current.value!==Oe&&qr(Oe,qe(Oe===""?Ya:Qn))}}),gr=x.useMemo(()=>Ds&&bc?{current:bc.closest('[role="dialog"]')}:Mt,[Ds,bc]);oa({enabled:!e.actionsRef,open:ln,ref:gr,onComplete(){ln||Gr()}}),x.useImperativeHandle(e.actionsRef,()=>({unmount:Gr}),[Gr]),Me(function(){const Be=Ge.current!==null&&be===null;if(Ge.current=be,ln&&(!Be||!Et)||(ln||(ts.current=null),y==="none"))return;const lt=Et?Os:qt.current;$r({selectedIndex:bf(lt,wt,F,Dn)})},[ln,be,wt,y,Dn,Et,Os,F,$r]),Me(()=>{Se&&(qt.current=Os,Ct.current.length=Os.length)},[Se,Os]),Me(()=>{const Oe=Dt.current;if(Oe){const hs=ln||Ds||et.state.positionerElement?.hidden===!1;if(Oe.hasQuery)jt&&hs&&et.set("activeIndex",0),Dt.current=null;else if(String(Nn).trim()===""&&(Dt.current=null,hs)){const Ar=Oe.selection;jt==="always"&&!Ar&&et.state.selectionMode==="none"&&et.set("activeIndex",0),queueMicrotask(()=>{if(!et.state.open&&!et.state.inline||ot.current&&ot.current.value.trim()!=="")return;const ha=et.state.selectedValue,Kr=et.state.selectionMode==="multiple";if(Kr&&Array.isArray(ha)?ha.length>0:et.state.selectionMode!=="none"&&ha!=null){const Bs=Et||xt?Os:qt.current,za=uu(Bs,Oe.toggledValue,et.state.isItemEqualToValue);et.set("activeIndex",za!==-1?za:bf(Bs,ha,et.state.isItemEqualToValue,Kr))}else Ar?et.set("activeIndex",null):jt==="always"&&et.set("activeIndex",0)})}}if(!ln&&!Ds)return;const lt=Et||xt?Os:qt.current,Qt=et.state.activeIndex;if(Qt==null){if(jt==="always"&<.length>0){et.set("activeIndex",0);return}Zo(void 0,-1,Qn);return}if(Qt>=lt.length){Zo(void 0,-1,Qn),et.set("activeIndex",null);return}const In=lt[Qt],gn=nt.current.value,Pn=gn!==mA&&ca(In,gn,et.state.isItemEqualToValue);(nt.current.index!==Qt||!Pn)&&Zo(In,Qt,Qn)},[Ys,jt,Zo,xt,Et,Os,Ds,ln,et,Nn]),Me(()=>{if(y==="none"){ae(String(Nn)!=="");return}ae(Dn?Array.isArray(wt)&&wt.length>0:wt!=null)},[ae,y,Nn,wt,Dn]),x.useEffect(()=>{Et&&jt&&Os.length===0&&$r({activeIndex:null})},[Et,jt,Os.length,$r]);function ib(){ln&&hr!==""&&hr!==String(Fr)&&!Ul&&Ne(!0)}function WS(){ln&&be!==null&&ob(!1)}let cd=!1;function Kp(){!cd&&Nn!==Pa&&(cd=!0,qr(Pa,qe(Qn)))}function JS(){y!=="none"&&(M($n),U($E(wt,Z.initialValue,F)),he.change(wt),en&&!cs&&!lr&&Kp())}function xr(){en&&!cs&&!lr&&!Ce&&Kp()}function Yp(){y==="none"&&(M($n),U(Nn!==Z.initialValue),he.change(Nn))}ia(hr,ib),ia(ln,WS),ia(wt,JS),ia(Pa,xr),ia(Se,xr),ia(Nn,Yp);const Nc=$T({open:Ds?!0:ln,onOpenChange:It,elements:{reference:lr?vc:yc,floating:bc}}),ud=P?"grid":"listbox",La=ln||Ds,Xp=La?"true":"false",kc=x.useMemo(()=>{const Oe=yc?.tagName==="INPUT",Be=yc==null||Oe,lt=Be||La,Qt=Be?{autoComplete:"off",spellCheck:"false",autoCorrect:"off",autoCapitalize:"none"}:{};return lt&&(Qt.role="combobox",Qt["aria-expanded"]=Xp,Qt["aria-haspopup"]=ud,Qt["aria-controls"]=La?ab?.id:void 0,Qt["aria-autocomplete"]=S?"none":G),{reference:Qt,floating:{role:"presentation"}}},[yc,La,Xp,ud,ab?.id,G,S]),$l=gh(Nc,{enabled:!Fn&&I,event:"mousedown-only",toggle:!1,touchOpenDelay:lr?0:100,reason:k4}),dd=pf(Nc,{enabled:!Fn&&!Ds,outsidePressEvent:{mouse:"sloppy",touch:"intentional"},bubbles:Ds?!0:void 0,outsidePress(Oe){const Be=fs(Oe);return!Ze(vc,Be)&&!Ze(Vn.current,Be)&&!Ze($t.current,Be)&&!Ze(jc,Be)}}),ql=XT(Nc,{enabled:!Fn,id:ke,listRef:Ct,activeIndex:Ys,selectedIndex:Xo,virtual:!0,loopFocus:H,allowEscape:H&&!jt,focusItemOnOpen:Ce||y==="none"&&!jt?!1:"auto",focusItemOnHover:z,resetOnPointerLeave:!_,orientation:P?"horizontal":void 0,rtl:te==="rtl",disabledIndices:Pr,grid:P?GF:void 0,onNavigate(Oe,Be){!Be&&!ln||qp==="ending"||$r(Be?{activeIndex:Oe,type:vs.current?I1:P1}:{activeIndex:Oe})}}),Qp=x.useMemo(()=>ta(ql.reference,{onKeyDown(Oe){P&&et.state.activeIndex==null&&(Oe.key==="ArrowLeft"||Oe.key==="ArrowRight")&&Oe.preventBaseUIHandler()}},dd.reference,$l.reference,kc.reference),[ql.reference,dd.reference,$l.reference,kc.reference,P,et]),fd=x.useMemo(()=>ta(mf,dd.floating),[dd.floating]),cb=x.useMemo(()=>ta(ql.floating,kc.floating),[ql.floating,kc.floating]),ub=x.useMemo(()=>{const Oe=ql.item;return Oe?{...Oe,onFocus:void 0}:mn},[ql.item]);et.useContextCallback("setOpen",It),et.useContextCallback("setInputValue",qr),et.useContextCallback("setSelectedValue",Sc),et.useContextCallback("setIndices",$r),et.useContextCallback("handleSelection",od),et.useContextCallback("forceMount",Fl),et.useContextCallback("requestSubmit",id),et.useContextCallback("onOpenChangeComplete",a),BE(()=>{et.update({inline:X,popupProps:fd,listProps:cb,inputProps:Qp,triggerProps:Gp,itemProps:ub})});const Cc={id:ke,selectedValue:wt,open:ln,mounted:Qo,transitionStatus:qp,items:Le,inline:X,popupProps:fd,listProps:cb,inputProps:Qp,triggerProps:Gp,itemProps:ub,openMethod:lb,selectionMode:y,name:$n,form:w,disabled:Fn,readOnly:S,required:N,grid:P,virtualized:$,openOnInputClick:I,itemToStringLabel:oe,modal:q,autoHighlight:jt,isItemEqualToValue:F,submitOnItemClick:re,hasInputValue:cs};Me(()=>{et.update({...Cc,inputOwnsFormValue:y==="none"&&(X||!et.state.inputInsidePopup)})},[et,...Object.values(Cc)]);const ma=sa(R,he.inputRef),Zp=x.useMemo(()=>({query:hr,hasItems:Et,filteredItems:Yo,flatFilteredValues:Os}),[hr,Et,Yo,Os]),Wp=x.useMemo(()=>Array.isArray(Bl)?"":Ca(Bl,L),[Bl,L]),Wo=Dn&&Array.isArray(wt)&&wt.length>0,ll=Dn||y==="none"&&Hl?void 0:$n,db=x.useMemo(()=>!Dn||!Array.isArray(wt)||!$n?null:wt.map(Oe=>{const Be=Ca(Oe,L);return s.jsx("input",{type:"hidden",form:w,name:$n,value:Be,disabled:Fn},Be)}),[Dn,wt,w,$n,L,Fn]),Jp=s.jsxs(x.Fragment,{children:[e.children,s.jsx("input",{...he.getValidationProps(Fn,{onFocus(){if(lr){vc?.focus();return}(ot.current||vc)?.focus()},onChange(Oe){if(Oe.nativeEvent.defaultPrevented||Fn||S)return;const Be=Oe.currentTarget.value,lt=Be.toLowerCase(),Qt=qe(Qn,Oe.nativeEvent),In=()=>qt.current.findIndex(Pn=>Ca(Pn,L).toLowerCase()===lt||pe(Pn).toLowerCase()===lt);function gn(){if(Dn)return;if(y==="none"){qr(Be,Qt);return}let Pn=In();Pn===-1&&(Pn=qt.current.findIndex((Ar,ha)=>{const Kr=Tt.current[ha];return Kr!=null&&Kr.toLowerCase()===lt}));const hs=Pn===-1?void 0:qt.current[Pn];hs!=null&&Sc?.(hs,Qt)}en&&(Fl(),Se&&In()===-1&&et.set("forceMounted",!0)),queueMicrotask(gn)}}),id:ke&&ll==null?`${ke}-hidden-input`:void 0,form:w,name:ll,autoComplete:J,disabled:Fn,required:N&&!Wo,readOnly:S,value:Wp,ref:ma,style:ll?ru:_i,tabIndex:-1,"aria-hidden":!0,suppressHydrationWarning:!0}),db]});return s.jsx(lA.Provider,{value:et,children:s.jsx(oA.Provider,{value:Nc,children:s.jsx(cA.Provider,{value:Et,children:s.jsx(iA.Provider,{value:Zp,children:s.jsx(uA.Provider,{value:Nn,children:Jp})})})})})}function t6(e){const{multiple:t=!1,defaultValue:a,value:o,onValueChange:c,autoComplete:d,...f}=e;return s.jsx(e6,{...f,selectionMode:t?"multiple":"single",selectedValue:o,defaultSelectedValue:a,onSelectedValueChange:c,formAutoComplete:d})}const n6="data-popup-side",s6="data-list-empty",hA={...Yv,...Ti,popupSide:e=>e?{[n6]:e}:null,listEmpty:e=>e?{[s6]:""}:null},r6=x.createContext(void 0);function a6(){return x.useContext(r6)}const gA=x.createContext(void 0);function ij(e){const t=x.useContext(gA);if(t===void 0&&!e)throw new Error(un(21));return t}const xA=x.forwardRef(function(t,a){const o=Ta(),{buttonRef:c,getButtonProps:d}=na({native:!1}),f=sa(a,c);function p(b){o.context.setOpen(!1,qe(dy,b.nativeEvent,b.currentTarget))}const h=d({onClick:p});return s.jsx("span",{ref:f,...h,"aria-label":"Dismiss",tabIndex:void 0,style:ru})});function bA(e){const t=e.useState("mounted"),a=e.useState("popupSide"),o=e.useState("positionerElement");return t&&o?a:null}function Gh(){return yf().filteredItems.length===0}function l6(e){return e==="rtl"?["ArrowRight","ArrowLeft"]:["ArrowLeft","ArrowRight"]}function o6(e,t){const a=e>=t-1?t-2:e;return a>=0?a:void 0}function vA(e,t,a){const o=e.context.listRef.current[t];o&&(e.context.selectionEventRef.current=a,o.click(),e.context.selectionEventRef.current=null)}const i6=x.forwardRef(function(t,a){const{render:o,className:c,disabled:d=!1,id:f,style:p,...h}=t,{state:b,disabled:y,setTouched:v,setFocused:j,validationMode:w,validation:k}=Na(),{labelId:S}=yl(),N=a6(),P=!!ij(!0),T=Ta(),C=dA(),E=gf(),D=T.useState("required"),I=T.useState("disabled"),O=T.useState("readOnly"),_=T.useState("name"),z=T.useState("form"),H=T.useState("selectionMode"),B=T.useState("autoHighlight"),L=T.useState("inputProps"),F=T.useState("triggerProps"),$=T.useState("open"),X=T.useState("mounted"),K=T.useState("selectedValue"),q=T.useState("id"),Q=T.useState("inline"),G=T.useState("modal"),J=!!B,Y=bA(T),re=y||I||d,M=Gh(),U=P||Q,Z=!U||G,ae=ka(f??(U?void 0:q)),ce=P?n1:b,[W,ue]=x.useState(null),ve=x.useRef(!1),ee=x.useRef(null),he=x.useRef(!1),te=H==="none"&&!P,ke=Ie(me=>{const pe=P||T.state.inline;pe&&!T.state.hasInputValue&&T.context.setInputValue("",qe(Qn)),T.update({inputElement:me,inputInsidePopup:pe,inputOwnsFormValue:te})}),le=P?h:k.getValidationProps(re,h);function de(){T.context.setIndices({activeIndex:null,selectedIndex:null,type:T.context.keyboardActiveRef.current?I1:P1})}function Se(){T.context.keyboardActiveRef.current=!1}const Te={...ce,open:$,disabled:re,readOnly:O,popupSide:Y,listEmpty:M};function Le(me){if(!N)return;let pe;const{highlightedChipIndex:Ce}=N,Ne=N.chipsRef.current.length,[be,De]=l6(E);return Ce!==void 0?(me.key===be?(me.preventDefault(),Ce>0?pe=Ce-1:pe=void 0):me.key===De?(me.preventDefault(),Ce0&&(me.preventDefault(),pe=Ne>0?Ne-1:void 0),pe)}const Ae=yt("input",t,{state:Te,ref:[a,T.context.inputRef,ke],props:[L,F,{value:W??C,"aria-readonly":O||void 0,"aria-required":D||void 0,"aria-labelledby":S,disabled:re,readOnly:O,required:H==="none"?D:void 0,form:z,...te&&_&&{name:_},id:ae,onFocus(){if(j(!0),!Q||!he.current)return;he.current=!1;const me=ee.current;me==null||!Object.hasOwn(T.context.valuesRef.current,me)||T.context.setIndices({activeIndex:me})},onBlur(){v(!0),j(!1);const me=T.state.activeIndex;if(Q&&me!==null&&B!=="always"&&(ee.current=me,he.current=!0,T.context.setIndices({activeIndex:null})),w==="onBlur"){const pe=H==="none"?C:K;k.commit(pe)}},onCompositionStart(me){Xm||(ve.current=!0,ue(me.currentTarget.value))},onCompositionEnd(me){ve.current=!1;const pe=me.currentTarget.value;ue(null),T.context.setInputValue(pe,qe(lf,me.nativeEvent))},onChange(me){const pe=me.nativeEvent,Ce=pe.inputType,Ne=!Ce||Ce==="insertReplacementText",be=ve.current||!Ne;function De(Mt){O||re||!Mt||!be||(T.context.setOpen(!0,qe(lf,pe)),J||de())}if(ve.current){const Mt=me.currentTarget.value;ue(Mt),Mt===""&&!T.state.openOnInputClick&&!T.state.inputInsidePopup&&T.context.setOpen(!1,qe(Ya,pe));const ot=Mt.trim(),Kn=J&&ot!=="";De(ot),$&&T.state.activeIndex!==null&&!Kn&&de();return}const Ge=qe(lf,pe);if(T.context.setInputValue(me.currentTarget.value,Ge),Ge.isCanceled)return;const Ct=me.currentTarget.value==="",Tt=qe(Ya,pe);Ct&&!T.state.inputInsidePopup&&(H==="single"&&T.context.setSelectedValue(null,Tt),T.state.openOnInputClick||T.context.setOpen(!1,Tt)),De(me.currentTarget.value.trim()),$&&T.state.activeIndex!==null&&!J&&de()},onKeyDown(me){if(me.ctrlKey||me.shiftKey||me.altKey||me.metaKey)return;if(T.context.keyboardActiveRef.current=!0,re||O){O&&me.key==="Enter"&&$&&T.state.activeIndex!==null&&Cs(me);return}const pe=me.currentTarget,Ce=pe.scrollWidth-pe.clientWidth,Ne=E==="rtl";if(me.key==="Home"){Cs(me);const Ge=c1&&Ne?pe.value.length:0;pe.setSelectionRange(Ge,Ge),pe.scrollLeft=0;return}if(me.key==="End"){Cs(me);const Ge=c1&&Ne?0:pe.value.length;pe.setSelectionRange(Ge,Ge),pe.scrollLeft=Ne?-Ce:Ce;return}if(!X&&me.key==="Escape"){const Ge=H==="multiple"&&Array.isArray(K)?K.length===0:K===null,Ct=qe(su,me.nativeEvent),Tt=H==="multiple"?[]:null;T.context.setInputValue("",Ct),T.context.setSelectedValue(Tt,Ct),!Ge&&!T.state.inline&&!Ct.isPropagationAllowed&&me.stopPropagation();return}if(N&&me.key==="Backspace"&&pe.value===""&&N.highlightedChipIndex===void 0&&Array.isArray(K)&&K.length>0){const Ge=N.chipsRef.current.length,Ct=Ge>0?Ge-1:K.length-1,Tt=K.filter((Mt,ot)=>ot!==Ct);de(),T.context.setSelectedValue(Tt,qe(Qn,me.nativeEvent));return}const be=N?.highlightedChipIndex!==void 0,De=Le(me);if(N?.setHighlightedChipIndex(De),De!==void 0?N?.chipsRef.current[De]?.focus():be&&T.context.inputRef.current?.focus(),me.which!==229&&me.key==="Enter"&&$){const Ge=T.state.activeIndex,Ct=me.nativeEvent;if(Ge===null){if(Q)return;T.context.setOpen(!1,qe(Qn,Ct));return}Cs(me),vA(T,Ge,Ct)}},onPointerMove:Se,onPointerDown:Se},le],stateAttributesMapping:hA}),oe=P?s.jsx(r1.Provider,{value:s1,children:Ae}):Ae;return s.jsxs(x.Fragment,{children:[$&&Z&&s.jsx(xA,{ref:T.context.startDismissRef}),oe]})}),c6=x.forwardRef(function(t,a){const{render:o,className:c,nativeButton:d=!0,disabled:f=!1,id:p,style:h,...b}=t,{state:y,disabled:v,setTouched:j,setFocused:w,validationMode:k,validation:S}=Na(),{labelId:N}=yl(),R=Ta(),P=R.useState("selectionMode"),T=R.useState("disabled"),C=R.useState("readOnly"),E=R.useState("required"),D=R.useState("positionerElement"),I=R.useState("listElement"),O=R.useState("popupId"),_=R.useState("triggerProps"),z=R.useState("inputInsidePopup"),H=R.useState("id"),B=R.useState("labelId"),L=R.useState("open"),F=R.useState("selectedValue"),$=R.useState("activeIndex"),X=R.useState("selectedIndex"),K=R.useState("hasSelectedValue"),q=qh(),Q=dA(),G=er(),J=v||T||f,Y=Gh(),re=bA(R);co({id:z?p:void 0});const M=z?p??H:p,U=QE(N,B);let Z;L&&z?Z=O??fA(H):L&&(Z=I?.id);const ae=x.useRef("");function ce(le){ae.current=le.pointerType}const{reference:W}=QT(q,{enabled:!L&&!C&&!T&&P==="single",listRef:R.context.labelsRef,activeIndex:$,selectedIndex:X,onMatch(le){const de=R.context.valuesRef.current[le];de!==void 0&&R.context.setSelectedValue(de,qe(Qn))}}),{reference:ue}=gh(q,{enabled:!T,event:"mousedown"}),{buttonRef:ve,getButtonProps:ee}=na({native:d,disabled:J}),he={...y,readOnly:C,open:L,disabled:J,popupSide:re,listEmpty:Y,placeholder:P==="none"?!1:!K},te=Ie(le=>{R.set("triggerElement",le)});return yt("button",t,{ref:[a,ve,te],state:he,props:[_,ue,W,{id:M,tabIndex:z?0:-1,role:z?"combobox":void 0,"aria-expanded":L,"aria-haspopup":z?"dialog":"listbox","aria-controls":Z,"aria-required":z&&E||void 0,"aria-readonly":z&&C||void 0,"aria-labelledby":U,onPointerDown:ce,onPointerEnter:ce,onFocus(){w(!0),!J&&G.start(0,R.context.forceMount)},onBlur(le){if(!Ze(D,le.relatedTarget)&&(j(!0),w(!1),k==="onBlur")){const de=P==="none"?Q:F;S.commit(de)}},onMouseDown(le){if(J||(z||q.set("domReferenceElement",le.currentTarget),R.context.forceMount(),ae.current!=="touch"&&(R.context.inputRef.current?.focus(),z||le.preventDefault()),L))return;const de=Gt(le.currentTarget);function Se(Te){const Le=R.state.triggerElement;if(!Le)return;const Ae=fs(Te),oe=R.state.positionerElement,me=R.state.listElement;Ze(Le,Ae)||Ze(oe,Ae)||Ze(me,Ae)||ZE(Te,Le)||R.context.setOpen(!1,qe(_1,Te))}z&&de.addEventListener("mouseup",Se,{once:!0})},onKeyDown(le){(le.key==="ArrowDown"||le.key==="ArrowUp")&&(Cs(le),R.context.setOpen(!0,qe(fy,le.nativeEvent)),R.context.inputRef.current?.focus())}},S.getValidationProps(J,b),ee],stateAttributesMapping:hA})}),u6=x.createContext(null);function d6(){return x.useContext(u6)}function f6(e){const{children:t}=e,{filteredItems:a}=yf(),o=d6(),c=o?o.items:a;return s.jsx(x.Fragment,{children:c.map(t)})}const p6=x.forwardRef(function(t,a){var o;const{render:c,className:d,style:f,children:p,...h}=t,b=Ta(),y=qh(),v=!!ij(!0),{filteredItems:j,hasItems:w}=yf(),k=b.useState("selectionMode"),S=b.useState("grid"),N=b.useState("readOnly"),R=b.useState("listProps"),P=b.useState("virtualized"),T=b.useState("forceMounted"),C=k==="multiple",E=j.length===0,D=Ie(L=>{b.set("positionerElement",L)}),I=Ie(L=>{b.set("listElement",L)}),O=x.useMemo(()=>typeof p=="function"?o||(o=s.jsx(f6,{children:p})):p,[p]),_={empty:E},z=y.useState("floatingId"),H=yt("div",t,{state:_,ref:[a,I,v?null:D],props:[R,{children:O,tabIndex:-1,id:z,role:S?"grid":"listbox","aria-multiselectable":C?"true":void 0,"aria-readonly":!S&&N?!0:void 0,onKeyDown(L){if(!(b.state.disabled||b.state.readOnly)&&L.key==="Enter"){const F=b.state.activeIndex;if(F==null)return;Cs(L),vA(b,F,L.nativeEvent)}},onKeyDownCapture(){b.context.keyboardActiveRef.current=!0},onPointerMoveCapture(){b.context.keyboardActiveRef.current=!1}},h]});if(P)return H;const B=w&&!T?void 0:b.context.labelsRef;return s.jsx(nj,{elementsRef:b.context.listRef,labelsRef:B,children:H})}),m6="⁠",h6=200;function g6(e){const t=e.ownerDocument.createTreeWalker(e,NodeFilter.SHOW_TEXT);let a=null;for(;t.nextNode();){const o=t.currentNode;o.nodeValue!==""&&(a=o)}return a}function x6(){const e=er(),t=x.useRef(null);return x.useEffect(()=>{if(tf)return;const a=t.current;if(a==null)return;const o=g6(a);if(o==null)return;const c=o.data,d=`${c}${m6}`;return o.nodeValue=d,e.start(h6,()=>{o.nodeValue===d&&(o.nodeValue=c)}),()=>{e.clear(),o.nodeValue===d&&(o.nodeValue=c)}},[t,e]),t}const yA=x.createContext(void 0);function b6(){const e=x.useContext(yA);if(e===void 0)throw new Error(un(20));return e}const v6=x.forwardRef(function(t,a){const{keepMounted:o=!1,...c}=t,d=Ta(),f=d.useState("mounted"),p=d.useState("forceMounted");return f||o||p?s.jsx(yA.Provider,{value:o,children:s.jsx(mh,{ref:a,...c})}):null}),y6=x.forwardRef(function(t,a){const{render:o,className:c,anchor:d,positionMethod:f,side:p,align:h,sideOffset:b,alignOffset:y,collisionBoundary:v="clipping-ancestors",collisionPadding:j,arrowPadding:w,sticky:k,disableAnchorTracking:S=!1,collisionAvoidance:N=rT,style:R,...P}=t,T=Ta(),C=qh(),E=b6(),D=T.useState("modal"),I=T.useState("open"),O=T.useState("mounted"),_=T.useState("openMethod"),z=T.useState("positionerElement"),H=T.useState("triggerElement"),B=T.useState("inputElement"),L=T.useState("inputGroupElement"),F=T.useState("inputInsidePopup"),$=T.useState("transitionStatus"),X=Gh(),q=Eh({anchor:d??(F?H:L??B),floatingRootContext:C,positionMethod:f,mounted:O,side:p,sideOffset:b,align:h,alignOffset:y,arrowPadding:w,collisionBoundary:v,collisionPadding:j,sticky:k,disableAnchorTracking:S,keepMounted:E,collisionAvoidance:N,lazyFlip:!0});aj(I&&D,_==="touch",z,H);const Q={open:I,side:q.side,align:q.align,anchorHidden:q.anchorHidden,empty:X};Me(()=>{T.set("popupSide",q.side)},[T,q.side]);const G=Ie(Y=>{T.set("positionerElement",Y)}),J=Ah(t,Q,{styles:q.positionerStyles,transitionStatus:$,props:P,refs:[a,G],hidden:!O,inert:!I});return s.jsxs(gA.Provider,{value:q,children:[O&&D&&s.jsx(Dh,{inert:Rh(!I),cutout:L??B??H}),J]})}),j6={...Wc,...uo},w6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,initialFocus:f,finalFocus:p,...h}=t,b=Ta(),y=ij(),v=qh(),j=b.useState("mounted"),w=b.useState("open"),k=b.useState("openMethod"),S=b.useState("popupProps"),N=b.useState("transitionStatus"),R=b.useState("inputInsidePopup"),P=b.useState("inputElement"),T=b.useState("modal"),C=b.useState("id"),E=Gh(),D=h.id??(R?fA(C):void 0);Me(()=>(b.set("popupId",b.context.popupRef.current?.id||D),()=>{b.set("popupId",void 0)}),[b,D]),oa({open:w,ref:b.context.popupRef,onComplete(){w&&b.context.onOpenChangeComplete(!0)}});const I={open:w,side:y.side,align:y.align,anchorHidden:y.anchorHidden,transitionStatus:N,empty:E},O=yt("div",t,{state:I,ref:[a,b.context.popupRef],props:[S,{id:D,role:R?"dialog":"presentation",onFocus(L){const F=fs(L.nativeEvent);k!=="touch"&&(Ze(b.state.listElement,F)||F===L.currentTarget)&&b.context.inputRef.current?.focus()}},xf(N),h],stateAttributesMapping:j6}),z=f===void 0?R?L=>L==="touch"?b.context.popupRef.current:P:!1:f;let H;p!=null?H=p:H=R?void 0:!1;const B=!R||T;return s.jsx(hh,{context:v,disabled:!j,modal:B,openInteractionType:k,initialFocus:z,returnFocus:H,getInsideElements:()=>[b.context.startDismissRef.current,b.context.endDismissRef.current],children:s.jsxs(x.Fragment,{children:[O,B&&s.jsx(xA,{ref:b.context.endDismissRef})]})})}),S6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,...f}=t;return yt("span",t,{ref:a,props:[{"aria-hidden":!0,children:"▼"},f]})}),jA=x.createContext(void 0);function wA(){const e=x.useContext(jA);if(!e)throw new Error(un(19));return e}const N6=x.createContext(!1);function k6(){return x.useContext(N6)}function SA(e){const{componentProps:t,forwardedRef:a,virtualized:o,indexFromFilter:c}=e,{render:d,className:f,style:p,value:h=null,index:b,disabled:y=!1,nativeButton:v=!1,...j}=t,w=x.useRef(null),k=tj({guess:!0,index:b,textRef:w}),S=Ta(),N=k6(),R=KF(),P=S.useState("selectionMode"),T=S.useState("disabled"),C=S.useState("readOnly"),E=S.useState("isItemEqualToValue"),D=T||y,I=P!=="none",O=b??c??k.index,_=O!==-1,z=S.useState("id"),H=S.useState("isActive",O),B=S.useState("isSelected",h),L=S.useState("itemProps"),F=x.useRef(null),$=z!=null&&_?`${z}-${O}`:void 0,X=B&&I;Me(()=>{if(!(_&&(o||b!=null)))return;const U=S.context.listRef.current;return U[O]=F.current,()=>{delete U[O]}},[_,o,O,b,S]),Me(()=>{if(!_||R)return;const M=S.context.valuesRef.current;return M[O]=h,()=>{delete M[O]}},[_,R,O,h,S]),Me(()=>{if(!_||R)return;const M=S.state.selectedValue;let U=S.state.selectedIndex;S.state.selectionMode==="multiple"&&Array.isArray(M)?U=qE(O,h,S.context.valuesRef.current,M,E,U):ca(h,M,E)&&(U=O),S.set("selectedIndex",U)},[_,R,S,O,h,E]);const{getButtonProps:K,buttonRef:q}=na({disabled:D,focusableWhenDisabled:!0,native:v,composite:!0}),Q={disabled:D,selected:X,highlighted:H};function G(M){function U(){S.context.handleSelection(M,h)}S.state.submitOnItemClick?(Ts.flushSync(U),S.context.requestSubmit()):U()}const J={id:$,role:N?"gridcell":"option","aria-selected":I?X:void 0,tabIndex:void 0,onPointerDownCapture(M){M.isPrimary&&(S.context.pointerDownItemRef.current=M.currentTarget),M.preventDefault()},onMouseDown(M){M.preventDefault()},onClick(M){D||C||G(M.nativeEvent)},onMouseUp(M){const U=S.context.pointerDownItemRef.current===M.currentTarget;S.context.pointerDownItemRef.current=null,!(D||C||M.button!==0||U||!H)&&G(M.nativeEvent)}},Y=yt("div",t,{ref:[q,a,k.ref,F],state:Q,props:[L,J,j,K]}),re=x.useMemo(()=>({selected:X,textRef:w}),[X,w]);return s.jsx(jA.Provider,{value:re,children:Y})}function C6(e){const{componentProps:t,forwardedRef:a}=e,c=Ta().useState("isItemEqualToValue"),{flatFilteredValues:d}=yf(),f=t.value??null,p=uu(d,f,c);return s.jsx(SA,{componentProps:t,forwardedRef:a,virtualized:!0,indexFromFilter:p})}const T6=x.memo(x.forwardRef(function(t,a){const c=Ta().useState("virtualized");return c&&t.index==null?s.jsx(C6,{componentProps:t,forwardedRef:a}):s.jsx(SA,{componentProps:t,forwardedRef:a,virtualized:c,indexFromFilter:void 0})})),E6=x.forwardRef(function(t,a){const{selected:o}=wA();return t.keepMounted||o?s.jsx(A6,{...t,ref:a}):null}),A6=x.memo(x.forwardRef((e,t)=>{const{render:a,className:o,style:c,keepMounted:d,...f}=e,{selected:p}=wA(),h=x.useRef(null),{transitionStatus:b,setMounted:y}=Oi(p),j=yt("span",e,{ref:[t,h],state:{selected:p,transitionStatus:b},props:[{"aria-hidden":!0,children:"✔️"},f],stateAttributesMapping:uo});return oa({batch:!0,enabled:!p,open:p,ref:h,onComplete(){p||y(!1)}}),j})),R6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,children:f,...p}=t,{filteredItems:h}=yf(),b=Ta(),y=x6(),v=h.length===0?f:null;return yt("div",t,{ref:[a,b.context.emptyRef,y],props:[{children:v,role:"status","aria-live":"polite","aria-atomic":!0},p]})}),O6="、";function Kh({value:e,onValueChange:t,options:a,placeholder:o="",emptyHint:c=vo("没有匹配的选项"),searchPlaceholder:d=vo("搜索…"),disabled:f=!1,className:p,id:h,title:b,...y}){const v=x.useMemo(()=>a.filter(w=>e.includes(w.value)),[a,e]),j=v.length?v.map(w=>w.label).join(O6):o;return s.jsxs(t6,{items:a,multiple:!0,value:v,onValueChange:w=>t(w.map(k=>k.value)),isItemEqualToValue:(w,k)=>w?.value===k?.value,disabled:f,children:[s.jsxs(c6,{"data-slot":"multi-select-trigger",id:h,title:b,"aria-label":y["aria-label"],className:Ue("inline-flex h-[30px] min-w-0 cursor-pointer items-center justify-between gap-1.5 rounded-md border border-control-border bg-control px-2.5","text-[12.5px] font-normal text-foreground","transition-colors duration-150 ease-out","hover:border-control-border-hover hover:bg-control-hover","focus-visible:border-primary focus-visible:shadow-focus focus-visible:outline-none","data-disabled:cursor-not-allowed data-disabled:bg-control data-disabled:text-muted-foreground data-disabled:opacity-60",p),children:[s.jsx("span",{"data-slot":"multi-select-value",className:"min-w-0 flex-1 truncate text-left data-[placeholder]:text-muted-foreground","data-placeholder":v.length?void 0:"",title:j,children:j}),s.jsx(S6,{className:"flex flex-none text-muted-foreground transition-transform duration-[180ms] data-popup-open:rotate-180",children:s.jsx("svg",{viewBox:"0 0 10 6",className:"size-2.5","aria-hidden":"true",children:s.jsx("path",{d:"M1 1l4 4 4-4",stroke:"currentColor",strokeWidth:"1.4",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),s.jsx(v6,{children:s.jsx(y6,{sideOffset:4,className:"z-[35]",children:s.jsxs(w6,{"data-slot":"multi-select-content",className:Ue("flex max-h-[280px] w-[max(var(--anchor-width),220px)] flex-col overflow-hidden","rounded-lg border border-border-strong bg-raised shadow-3 outline-none","data-open:animate-in data-open:fade-in-0","data-closed:animate-out data-closed:fade-out-0"),children:[s.jsxs("div",{className:"flex flex-none items-center gap-1.5 border-b border-hairline px-2.5 py-1.5",children:[s.jsxs("svg",{viewBox:"0 0 12 12",className:"size-3 flex-none text-muted-foreground","aria-hidden":"true",children:[s.jsx("circle",{cx:"5",cy:"5",r:"3.4",stroke:"currentColor",strokeWidth:"1.3",fill:"none"}),s.jsx("path",{d:"M7.6 7.6 10.5 10.5",stroke:"currentColor",strokeWidth:"1.3",strokeLinecap:"round"})]}),s.jsx(i6,{placeholder:d,className:"min-w-0 flex-1 border-0 bg-transparent p-0 text-[12.5px] text-foreground outline-none placeholder:text-muted-foreground"})]}),s.jsx(R6,{children:s.jsx("div",{className:"px-2.5 py-3 text-[11.5px] leading-[1.5] text-muted-foreground",children:c})}),s.jsx(p6,{className:"min-h-0 flex-1 overflow-y-auto overscroll-contain p-[5px]",children:w=>s.jsxs(T6,{value:w,className:Ue("grid cursor-pointer grid-cols-[14px_minmax(0,1fr)] items-center gap-2 rounded-sm px-[9px] py-[5px]","text-[12.5px] leading-[1.4] text-foreground select-none outline-none","transition-colors duration-[120ms] ease-out","data-[highlighted]:bg-nav-hover","data-[selected]:bg-primary-soft data-[selected]:font-semibold data-[selected]:text-primary-fg","data-[highlighted]:data-[selected]:bg-primary-tint","data-disabled:pointer-events-none data-disabled:text-muted-foreground"),children:[s.jsx(E6,{className:"col-start-1 flex text-primary",children:s.jsx("svg",{viewBox:"0 0 12 12",className:"size-3","aria-hidden":"true",children:s.jsx("path",{d:"M2.5 6.2 4.8 8.5 9.5 3.8",stroke:"currentColor",strokeWidth:"1.8",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"})})}),s.jsx("span",{className:"col-start-2 min-w-0 truncate",children:w.label})]},w.value)})]})})})]})}const NA=x.createContext(void 0);function jf(e){const t=x.useContext(NA);if(t===void 0&&!e)throw new Error(un(47));return t}const M6={...Hy,disabled:e=>e.disabled,instantType:e=>e.instantType,openMethod:e=>e.openMethod,openChangeReason:e=>e.openChangeReason,modal:e=>e.modal,focusManagerModal:e=>e.focusManagerModal,stickIfOpen:e=>e.stickIfOpen,titleElementId:e=>e.titleElementId,descriptionElementId:e=>e.descriptionElementId,openOnHover:e=>e.openOnHover,closeDelay:e=>e.closeDelay,adaptiveOrigin:e=>e.adaptiveOrigin};class D6 extends iu{constructor(a,o,c){const d=new yh;super(I6(a,d,o,c),P6(d),M6);cn(this,"setOpen",(a,o)=>{const c=o.reason===qs,d=o.reason===xo&&o.event.detail===0,f=!a&&(o.reason===su||o.reason==null),p=zT(o),h=this.select("activeTriggerId");if(!a&&o.reason===dy&&o.trigger==null&&h!=null&&(o.trigger=this.context.triggerElements.getById(h)??this.select("activeTriggerElement")??void 0),this.context.onOpenChange?.(a,o),o.isCanceled)return;this.state.floatingRootContext.dispatchOpenChange(a,o);const b=()=>{const v=Iy(this.state,a,o.trigger,p());v.openChangeReason=o.reason,this.update(v)};c?(this.set("stickIfOpen",!0),this.context.stickIfOpenTimeout.start(xH,()=>{this.set("stickIfOpen",!1)}),Ts.flushSync(b)):b();let y;d?y="click":f?y="dismiss":o.reason===bo&&(y="focus"),this.set("instantType",y)})}}function I6(e,t,a,o=!1){const c={...zy(t,a,o),disabled:!1,modal:!1,focusManagerModal:!1,instantType:void 0,openMethod:null,openChangeReason:null,titleElementId:void 0,descriptionElementId:void 0,stickIfOpen:!0,openOnHover:!1,closeDelay:0,adaptiveOrigin:void 0,...e};return c.open&&e?.mounted===void 0&&(c.mounted=!0),c}function P6(e){return{popupRef:x.createRef(),onOpenChange:void 0,onOpenChangeComplete:void 0,triggerFocusTargetRef:x.createRef(),beforeContentFocusGuardRef:x.createRef(),stickIfOpenTimeout:new la,triggerElements:e}}const kA=dh(function({props:t}){const{children:a,open:o,defaultOpen:c=!1,onOpenChange:d,onOpenChangeComplete:f,modal:p=!1,handle:h,triggerId:b,defaultTriggerId:y=null}=t,v=L6(h,{modal:p,open:c,openProp:o,activeTriggerId:y,triggerIdProp:b});v.useControlledProp("openProp",o),v.useControlledProp("triggerIdProp",b);const j=v.useState("open"),w=v.useState("mounted"),k=v.useState("payload");v.useContextCallback("onOpenChange",d),v.useContextCallback("onOpenChangeComplete",f),HT(v,j),Py(v);const{forceUnmount:S}=_y(j,v,()=>{v.update({stickIfOpen:!0,openChangeReason:null})});v.useSyncedValues({modal:p}),x.useEffect(()=>{j||v.context.stickIfOpenTimeout.clear()},[v,j]),x.useImperativeHandle(t.actionsRef,()=>({unmount:S,close:()=>v.setOpen(!1,qe(py))}),[S,v]);const N=j||w;return s.jsxs(NA.Provider,{value:v,children:[h&&s.jsx(Dy,{handle:h,store:v}),N&&s.jsx(z6,{store:v,modal:p}),typeof a=="function"?a({payload:k}):a]})});function _6(e){return jf(!0)?s.jsx(kA,{props:e}):s.jsx(NH,{children:s.jsx(kA,{props:e})})}function L6(e,t){const a=My((o,c)=>new D6(t,o,c));return x.useEffect(()=>a.context.stickIfOpenTimeout.disposeEffect(),[a]),a}function z6({store:e,modal:t}){const a=e.useState("floatingRootContext"),o=pf(a,{outsidePressEvent:{mouse:t==="trap-focus"?"sloppy":"intentional",touch:"sloppy"}}),c=o.reference,d=o.floating;return Ly(e,{activeTriggerProps:c,inactiveTriggerProps:c,popupProps:d}),null}const B6=300;function H6(e,t){const a=x.useRef(null);function o(d){Ts.flushSync(()=>{e.setOpen(!1,qe(bo,d.nativeEvent,d.currentTarget))}),b4(a.current)?.focus()}function c(d){const f=e.select("positionerElement");if(f&&eu(d,f))e.context.beforeContentFocusGuardRef.current?.focus();else{Ts.flushSync(()=>{e.setOpen(!1,qe(bo,d.nativeEvent,d.currentTarget))});let p=x4(e.context.triggerFocusTargetRef.current||t.current);for(;p!==null&&Ze(f,p);){const h=p;if(p=iy(p),p===h)break}p?.focus()}}return{preFocusGuardRef:a,handlePreFocusGuardFocus:o,handleFocusTargetFocus:c}}const U6=G1(function(t,a){const{render:o,className:c,style:d,disabled:f=!1,nativeButton:p=!0,handle:h,payload:b,openOnHover:y=!1,delay:v=B6,closeDelay:j=0,id:w,...k}=t,S=jf(!0),R=FT(h)??S;if(!R)throw new Error(un(74));const P=ka(w),T=R.useState("isTriggerActive",P),C=R.useState("floatingRootContext"),E=R.useState("isOpenedByTrigger",P),D=R.useState("triggerPopupId",P),I=x.useRef(null),{registerTrigger:O,isMountedByThisTrigger:_}=BT(P,I,R,{payload:b,disabled:f,openOnHover:y,closeDelay:j}),z=R.useState("openChangeReason"),H=R.useState("stickIfOpen"),B=R.useState("openMethod"),L=R.useState("focusManagerModal"),F=KT(C,{enabled:!f&&y&&(B!=="touch"||z!==xo),mouseOnly:!0,move:!1,handleClose:WT(),restMs:v,delay:{close:j},triggerElementRef:I,isActiveTrigger:T,isClosing:()=>R.select("transitionStatus")==="ending"}),$=gh(C,{stickIfOpen:H}),X=TE(()=>R.select("open"),ae=>{R.set("openMethod",ae)}),K=R.useState("triggerProps",_),{getButtonProps:q,buttonRef:Q}=na({disabled:f,native:p}),G={open(ae){return ae&&z===xo?Yv.open(ae):Kv.open(ae)}},{preFocusGuardRef:J,handlePreFocusGuardFocus:Y,handleFocusTargetFocus:re}=H6(R,I),U=yt("button",t,{state:{disabled:f,open:E},ref:[Q,a,O,I],props:[$.reference,F,K,X,{[sT]:"",id:P,"aria-haspopup":"dialog","aria-expanded":E,"aria-controls":D},k,q],stateAttributesMapping:G}),Z=s.jsx(x.Fragment,{children:U},P);return _&&!L?s.jsxs(x.Fragment,{children:[s.jsx(au,{ref:J,onFocus:Y}),Z,s.jsx(au,{ref:R.context.triggerFocusTargetRef,onFocus:re})]}):Z}),CA=x.createContext(void 0);function V6(){const e=x.useContext(CA);if(e===void 0)throw new Error(un(45));return e}const F6=x.forwardRef(function(t,a){const{keepMounted:o=!1,...c}=t;return jf().useState("mounted")||o?s.jsx(CA.Provider,{value:o,children:s.jsx(mh,{ref:a,...c})}):null}),TA=x.createContext(void 0);function $6(){const e=x.useContext(TA);if(!e)throw new Error(un(46));return e}const q6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,anchor:f,positionMethod:p,side:h,align:b,sideOffset:y,alignOffset:v,collisionBoundary:j="clipping-ancestors",collisionPadding:w,arrowPadding:k,sticky:S,disableAnchorTracking:N=!1,collisionAvoidance:R=aT,...P}=t,T=jf(),C=V6(),E=wH(),D=T.useState("floatingRootContext"),I=T.useState("mounted"),O=T.useState("open"),_=T.useState("openChangeReason"),z=T.useState("activeTriggerElement"),H=T.useState("modal"),B=T.useState("openMethod"),L=T.useState("positionerElement"),F=T.useState("instantType"),$=T.useState("transitionStatus"),X=T.useState("adaptiveOrigin"),K=x.useRef(null),q=D1(L),Q=Eh({anchor:f,floatingRootContext:D,positionMethod:p,mounted:I,side:h,sideOffset:y,align:b,alignOffset:v,arrowPadding:k,collisionBoundary:j,collisionPadding:w,sticky:S,disableAnchorTracking:N,keepMounted:C,nodeId:E,collisionAvoidance:R,adaptiveOrigin:X}),G=D.useState("domReferenceElement");Me(()=>{const U=G,Z=K.current;if(U&&(K.current=U),Z&&U&&U!==Z){T.set("instantType",void 0);const ae=new AbortController;return q(()=>{T.set("instantType","trigger-change")},ae.signal),()=>{ae.abort()}}},[G,q,T]);const J=H===!0&&_!==qs;aj(O&&J,B==="touch",L,z);const Y=T.useStateSetter("positionerElement"),re={open:O,side:Q.side,align:Q.align,anchorHidden:Q.anchorHidden,instant:F},M=Ah(t,re,{styles:Q.positionerStyles,transitionStatus:$,props:P,refs:[a,Y],hidden:!I,inert:!O});return s.jsxs(TA.Provider,{value:Q,children:[I&&J&&s.jsx(Dh,{inert:Rh(!O),cutout:z}),s.jsx(SH,{id:E,children:M})]})}),G6=x.createContext(void 0);function K6(){const[e,t]=x.useState(0),a=Ie(()=>(t(c=>c+1),()=>{t(c=>Math.max(0,c-1))}));return{context:x.useMemo(()=>({register:a}),[a]),hasClosePart:e>0}}const Y6=x.forwardRef(function(t,a){const{render:o,className:c,style:d,initialFocus:f,finalFocus:p,...h}=t,b=jf(),y=$6(),v=eA()!=null,{context:j,hasClosePart:w}=K6(),k=b.useState("open"),S=b.useState("openMethod"),N=b.useState("instantType"),R=b.useState("transitionStatus"),P=b.useState("popupProps"),T=b.useState("titleElementId"),C=b.useState("descriptionElementId"),E=b.useState("modal"),D=b.useState("mounted"),I=b.useState("openChangeReason"),O=b.useState("activeTriggerElement"),_=b.useState("floatingRootContext"),z=_.useState("floatingId"),H=b.useState("disabled"),B=b.useState("openOnHover"),L=b.useState("closeDelay");oa({open:k,ref:b.context.popupRef,onComplete(){k&&b.context.onOpenChangeComplete?.(!0)}}),GT(_,{enabled:B&&!H,closeDelay:L});const F=f===void 0?_T(b.context.popupRef):f,$=E!==!1&&w;b.useSyncedValue("focusManagerModal",$);const X=b.useStateSetter("popupElement"),K={open:k,side:y.side,align:y.align,instant:N,transitionStatus:R},q=yt("div",t,{state:K,ref:[a,b.context.popupRef,X],props:[P,{id:z,role:"dialog",...mf,"aria-labelledby":T,"aria-describedby":C,onKeyDown(Q){v&&Oh.has(Q.key)&&Q.stopPropagation()}},xf(R),h],stateAttributesMapping:Xv});return s.jsx(hh,{context:_,openInteractionType:S,modal:$,disabled:!D||I===qs,initialFocus:F,returnFocus:p,restoreFocus:"popup",previousFocusableElement:pn(O)?O:void 0,nextFocusableElement:b.context.triggerFocusTargetRef,beforeContentFocusGuardRef:b.context.beforeContentFocusGuardRef,children:s.jsx(G6.Provider,{value:j,children:q})})});function wf(e){return s.jsx(_6,{"data-slot":"popover",...e})}function Yh(e){return s.jsx(U6,{"data-slot":"popover-trigger",...e})}function Sf({className:e,sideOffset:t=6,align:a="start",side:o,alignOffset:c,collisionPadding:d=8,anchor:f,children:p,...h}){return s.jsx(F6,{children:s.jsx(q6,{className:"z-[35] outline-none",sideOffset:t,align:a,side:o,alignOffset:c,collisionPadding:d,anchor:f,children:s.jsx(Y6,{"data-slot":"popover-content",className:Ue("flex max-h-[min(70vh,560px)] flex-col overflow-hidden rounded-lg border border-border-strong bg-raised text-foreground shadow-3","outline-none","data-open:animate-in data-open:fade-in-0 data-open:slide-in-from-top-1","data-closed:animate-out data-closed:fade-out-0",e),...h,children:p})})})}function X6({page:e,pageCount:t,onPageChange:a,disabled:o=!1,className:c,infoFirst:d=!1}){const f=Math.max(1,Number(t)||1),p=Math.min(Math.max(1,Number(e)||1),f),h=s.jsx("span",{"data-slot":"pager-info",className:"text-[11.5px] text-subtle [font-variant-numeric:tabular-nums]",children:vo("第 {current} / {total} 页",{current:p,total:f})});return s.jsxs("div",{"data-slot":"pager",className:Ue("flex items-center gap-2",c),children:[d&&h,s.jsx(ne,{type:"button",variant:"outline",size:"sm",disabled:o||p<=1,onClick:()=>a(p-1),children:vo("上一页")}),s.jsx(ne,{type:"button",variant:"outline",size:"sm",disabled:o||p>=f,onClick:()=>a(p+1),children:vo("下一页")}),!d&&h]})}const Q6=Qc(["relative flex w-full items-center gap-2.5 text-left","border border-transparent rounded-sm","shadow-none","transition-[background-color,border-color,color] duration-150 ease-out","outline-none focus-visible:shadow-focus","disabled:pointer-events-none disabled:opacity-45","[&_svg]:pointer-events-none [&_svg]:shrink-0"],{variants:{variant:{default:["cursor-pointer px-2.5 py-2","text-[12.5px] font-medium text-sidebar-fg","hover:bg-nav-hover hover:text-foreground","data-[active]:border-nav-selected-border data-[active]:bg-nav-selected-bg data-[active]:font-semibold data-[active]:text-nav-selected-fg"],add:["cursor-pointer justify-center px-2 py-1.5","border-dashed border-border-strong bg-transparent","text-[11.5px] text-muted-foreground","hover:border-primary hover:text-primary-fg"]}},defaultVariants:{variant:"default"}});function du({className:e,variant:t,active:a=!1,count:o,icon:c,trailing:d,children:f,...p}){return s.jsxs("button",{type:"button","data-slot":"nav-item","data-active":a?"":void 0,"aria-current":a?"true":void 0,className:Ue(Q6({variant:t}),e),...p,children:[c,s.jsx("span",{"data-slot":"nav-item-label",className:"min-w-0 flex-1 truncate",children:f}),d,o!=null&&s.jsx("span",{"data-slot":"nav-item-count",className:Ue("flex-none text-[10.5px] text-sidebar-muted [font-variant-numeric:tabular-nums]",a&&"text-inherit"),children:o})]})}function r(e,t){const a=typeof window<"u"?window.wbI18n:void 0;return a&&typeof a.t=="function"?a.t(e,t):e}function Xh(e){if(e.source==="subscription"&&(e.port===null||e.port===void 0))return r("未分配端口");const t=e.resolved;return t?.protocol&&t.host&&t.port?`${String(t.protocol).toUpperCase()} ${t.host}:${t.port}`:t?.label||""}function fu(e){const t=e.name||e.id,o=[e.resolveError?r("解析失败"):Xh(e),e.enabled===!1?r("已禁用"):""].filter(Boolean);return o.length?r("{name}({parts})",{name:t,parts:o.join(" · ")}):t}const Qa="pool:";function Pe(){return window}function _e(e,t){Pe().wbApp?.toast?.(e,t)}function Za(e){const t=Pe().wbApp?.esc;return t?t(e):String(e??"").replace(/[&<>"']/g,a=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[a]||a)}function Ls(e){const t=Pe().wbApp?.formatTime;if(t)return t(e);const a=Number(e);return!Number.isFinite(a)||a<=0?"":new Date(a).toLocaleString("zh-CN")}function ut(e){return e instanceof Error?e.message:String(e)}function ss(e){if(e==null||e==="")return"—";const t=Number(e);return Number.isFinite(t)?String(Number(t.toFixed(2))):String(e)}function pu(e){if(e==null||e==="")return null;const t=Number(e);return Number.isFinite(t)?t:null}function cj(e){const t=new Date(e);if(Number.isNaN(t.getTime()))return"";const a=o=>String(o).padStart(2,"0");return`${a(t.getMonth()+1)}-${a(t.getDate())} ${a(t.getHours())}:${a(t.getMinutes())}`}function Z6(e){return e==="积分"?r("积分"):e==="额度"?r("额度"):e}function W6(e){if(!e||typeof e!="object"||Array.isArray(e))return[];const t=e,a=Array.isArray(t.credits)?t.credits:[],o=Date.now();return a.map(c=>{const d=String(c?.name||"").trim()||r("积分包"),f=String(c?.unit||"").trim(),p=pu(c?.total),h=pu(c?.used),b=pu(c?.remain),y=c?.unlimited===!0,v=pu(c?.grantAt),j=pu(c?.startAt),w=pu(c?.expireAt),k=c?.daily===!0,S=String(c?.grantReason||"").trim(),N=w!==null&&w>0&&w<=o,R=p!==null&&p>0,P=y?r("不限"):b!==null?R?r("剩 {remaining} / {total}",{remaining:ss(b),total:ss(p)}):r("剩 {remaining}",{remaining:ss(b)}):h!==null?r("已用 {used}",{used:ss(h)}):"—",T=!y&&f&&P!=="—"?`${P} ${Z6(f)}`:P,C=R&&b!==null?Math.max(0,Math.min(100,b/p*100)):null,E=b!==null&&b<=0||b===null&&h!==null&&R&&h>=p,D=!y&&!k&&(E||N),I=[];v!==null&&v>0?I.push(r("{time} 领取",{time:cj(v)})):j!==null&&j>0&&I.push(r("{time} 生效",{time:cj(j)})),k?I.push(r("每日重置")):w!==null&&w>0&&I.push(N?r("已过期"):r("{time} 到期",{time:cj(w)})),S&&I.push(S);const O=N||b===0?"muted":C!==null&&C<20?"warn":b===null&&h===null&&!y?"muted":"ok",_=[d,T,v!==null&&v>0?r("领取 {time}",{time:Ls(v)}):j!==null&&j>0?r("生效 {time}",{time:Ls(j)}):"",w!==null&&w>0?N?r("已过期({time})",{time:Ls(w)}):r("到期 {time}",{time:Ls(w)}):"",k?r("每日重置(额度按周期回满,不是作废)"):"",S,C===null&&b!==null?r("上游未给总量,画不出剩余比例"):"",h!==null&&p!==null?r("已用 {used} / 共 {total}",{used:ss(h),total:ss(p)}):""].filter(Boolean).join(" · ");return{name:d,view:T,tone:O,percent:C,window:I.length?I.join(" · "):null,title:_,spent:D}})}function EA({row:e}){return s.jsxs("div",{className:"usage-pop-row",title:e.title,children:[s.jsxs("div",{className:"usage-pop-line",children:[s.jsx("span",{className:"usage-pop-name",children:e.name}),s.jsx("span",{className:`usage-pop-view ${e.tone}`,children:e.view})]}),e.window?s.jsx("div",{className:"usage-pop-window",children:e.window}):null,e.percent!==null?s.jsx("span",{className:"usage-pop-track",children:s.jsx("i",{style:{width:`${e.percent}%`},"aria-label":r("剩余 {percent}%",{percent:Math.round(e.percent)})})}):null]})}function AA({rows:e,subscriptionLine:t,variant:a,kind:o,title:c,children:d}){const[f,p]=x.useState(!1),[h,b]=x.useState(!1),y=e.filter(N=>!N.spent),v=e.filter(N=>N.spent),j=a==="pool"?`usage-toggle usage-pool-line ${o}`:`usage-toggle ${o}`,w=x.useRef(null),k=x.useCallback(N=>{w.current=N,N&&(N.scrollTop=0)},[]),S=x.useCallback(()=>w.current??null,[]);return x.useLayoutEffect(()=>{if(!h)return;const N=w.current?.querySelector(".usage-pop-spent .usage-pop-row");N instanceof HTMLElement&&N.scrollIntoView({block:"nearest"})},[h]),s.jsxs(wf,{open:f,onOpenChange:p,children:[s.jsxs(Yh,{render:s.jsx("button",{type:"button",className:j,title:c,"aria-label":r("积分明细")}),children:[a==="pool"?d:s.jsx("span",{className:"val",children:d}),s.jsx("span",{className:"caret","aria-hidden":!0,children:"▾"})]}),s.jsx(Sf,{align:"end",sideOffset:6,className:"w-[320px]",initialFocus:S,children:s.jsxs("div",{className:"usage-pop-credit",ref:k,tabIndex:-1,children:[t?s.jsx("div",{className:"usage-pop-sub",children:t}):null,s.jsx("div",{className:"usage-pop-group",children:r("积分明细")}),y.map((N,R)=>s.jsx(EA,{row:N},`${N.name}-${R}`)),v.length>0?s.jsxs("div",{className:"usage-pop-spent",children:[s.jsxs("button",{type:"button",className:"usage-pop-spent-head","aria-expanded":h,title:r("展开或收起(默认收起)"),onClick:()=>b(N=>!N),children:[s.jsx("span",{className:"caret","aria-hidden":!0,children:"▾"}),s.jsx("span",{children:r("已用完 / 已过期")}),s.jsx("span",{className:"n",children:r("{count} 份",{count:v.length})})]}),h?v.map((N,R)=>s.jsx(EA,{row:N},`spent-${N.name}-${R}`)):null]}):null]})})]})}const mu="workbuddy",J6="raccoon",e$={workbuddy:{usage:!0,creditDetail:!0,edition:!0,identifier:"uid",expiry:"expiresAt"},"workbuddy-intl":{usage:!0,creditDetail:!0,edition:!1,identifier:"uid",expiry:"expiresAt"},raccoon:{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:"tokenExpiresAt"},catpaw:{usage:!0,edition:!1,identifier:"uid",expiry:"tokenExpiresAt"},autoclaw:{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:"tokenExpiresAt"},"autoclaw-intl":{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:"tokenExpiresAt",emailAsName:!0},qoder:{usage:!0,creditDetail:!0,edition:!0,identifier:"userId",expiry:"expiresAt",emailAsName:!0},"qoder-intl":{usage:!0,creditDetail:!0,edition:!0,identifier:"userId",expiry:"expiresAt",emailAsName:!0},"cline-free":{usage:!0,edition:!1,identifier:"account",expiry:"expiresAt"},"cline-pass":{usage:!0,edition:!1,identifier:"account",expiry:"expiresAt"},accio:{usage:!0,edition:!0,identifier:"userId",expiry:"expiresAt",emailAsName:!0},"accio-cn":{usage:!0,edition:!0,identifier:"userId",expiry:"expiresAt",emailAsName:!0},zcode:{usage:!0,creditDetail:!0,claim:!0,planChannel:!0,edition:!0,identifier:"userId",expiry:"expiresAt"},"zcode-intl":{usage:!0,creditDetail:!0,claim:!0,planChannel:!0,edition:!0,identifier:"userId",expiry:"expiresAt"},codearts:{usage:!0,usageDetail:!0,edition:!1,identifier:"userId",expiry:"expiresAt",concurrencyDefault:3},trae:{usage:!0,creditDetail:!0,edition:!1,identifier:"uid",expiry:"expiresAt"},loomy:{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:"expiresAt"},kuku:{usage:!0,edition:!1,identifier:"uid",expiry:""},officeace:{usage:!0,creditDetail:!0,edition:!1,identifier:"id",expiry:"expiresAt"},antigravity:{usage:!0,edition:!1,identifier:"userId",expiry:""},modelscope:{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:""},"modelscope-intl":{usage:!0,creditDetail:!0,edition:!1,identifier:"userId",expiry:""},chatglm:{usage:!0,creditDetail:!0,edition:!1,identifier:"uid",expiry:""}},t$={usage:!1,edition:!1,identifier:"userId",expiry:"tokenExpiresAt",emailAsName:!1};function An(e){const t=e?.provider;return typeof t=="string"&&t?t:mu}function cr(e){return e&&e$[e]||t$}const n$="opencode",s$="https://opencode.ai/zen/go/v1";function RA(e,t){if(!e||e.clientEmulation!==n$)return!1;const o=((typeof t=="string"?t.trim():"")||String(e.baseUrl||"")).trim().replace(/\/+$/,"").toLowerCase();return o?o!==s$:!1}function r$(e){const t=e?An(e):"";return t.startsWith("custom-")&&(Pe().wbProviders?.customList?.()||[]).find(o=>o?.id===t)||null}function a$(e){return e?RA(r$(e),e.baseUrl):!1}function OA(e){const t=Array.isArray(e?.providers)?e.providers:[],a=Array.isArray(e?.accounts)?e.accounts:[],o=new Map;a.forEach(d=>{const f=An(d);o.set(f,(o.get(f)||0)+1)});const c=new Map;return t.forEach(d=>{d?.id&&c.set(String(d.id),{id:String(d.id),label:String(d.label||d.id),count:Number(d.count)||0})}),o.forEach((d,f)=>{c.has(f)||c.set(f,{id:f,label:Pe().wbProviders?.labelOf?.(f)||f,count:d})}),c.size||c.set(mu,{id:mu,label:Pe().wbProviders?.labelOf?.(mu)||"WorkBuddy 国内版",count:0}),[...c.values()]}function Qh(e){const t=cr(An(e)).identifier;return String(e?.[t]||"")}function MA(e){const t=Number(e)||0;return t<=0?0:t<1e11?t*1e3:t}function l$(e){const t=cr(An(e)).expiry;return MA(e?.[t])}function Ea(e){const t=An(e);return t.startsWith("custom-")?!!e?.balanceQuery?.scheme:cr(t).usage}const uj=30,DA=86400,IA=60,PA=1800,_A=86400,LA=1,o$=95e5;function i$(e){return e==="codearts"?[{type:"token",action:"skip",threshold:o$,reset:"daily",enabled:!0}]:e==="cline-free"?[]:[{type:"balance",action:"skip",threshold:LA,enabled:!0}]}function zA(e){const t=e?.usageQuery;if(!t||typeof t!="object")return{enabled:!0,interval:IA};const a=t.enabled===void 0?!0:t.enabled===!0,o=Number(t.interval)||0,c=o>=uj&&o<=DA;return{enabled:a,interval:a&&!c?IA:o}}function c$(e){if(!e||typeof e!="object")return!1;const t=e;if(t.type!=="balance"&&t.type!=="token"||t.action!=="skip"&&t.action!=="disable")return!1;const a=Number(t.threshold);if(!Number.isFinite(a)||a<=0)return!1;if(t.type==="token"&&t.reset!=="daily"){const o=Number(t.period);if(!Number.isInteger(o)||o_A)return!1}return!0}function u$(e){const t=e?.lowBalance;if(!t||typeof t!="object"||!t.mode)return i$(An(e));const a=Number(t.threshold),o=Number.isFinite(a)&&a>0?a:LA;return t.mode!=="skip"&&t.mode!=="disable"?[]:[{type:"balance",action:t.mode,threshold:o,enabled:!0}]}function hu(e){const t=e?.limiters;return Array.isArray(t)?t.filter(c$):u$(e)}function d$(e){return hu(e).filter(t=>t.type==="token")}function f$(e,t){const a=t*1e3;return e-e%a}function BA(e){return e.reset==="daily"?0:e.period??0}function dj(e,t=Date.now()){if(e===0){const a=new Date(t);return a.setHours(0,0,0,0),a.getTime()}return f$(t,e)}function Nf(e,t,a=Date.now()){if(e.type!=="token")return null;const o=BA(e),c=(t||[]).find(d=>Number(d.kind)===o);return c&&Number(c.windowStart)===dj(o,a)?c:null}function Zh(e,t){const a=hu(e).filter(f=>f.type==="balance"&&f.action==="skip"&&f.enabled!==!1&&f.threshold>0);if(!a.length||!t||typeof t!="object")return!1;const o=t;if(o.unlimited)return!1;const c=o.totalLeft??o.available;if(c==null||c==="")return!1;const d=Number(c);return Number.isFinite(d)&&a.some(f=>dc.type==="token"&&c.action==="skip"&&c.enabled!==!1);if(!a.length||!t?.length)return!1;const o=Date.now();return a.some(c=>{const d=Nf(c,t,o);return d!==null&&Number(d.used)>=c.threshold})}function p$(e,t){return hu(e).some(a=>{if(a.type!=="token"||a.action!=="disable"||a.enabled===!1)return!1;const o=Nf(a,t);return o!==null&&Number(o.used)>=a.threshold})}function pj(e,t=Date.now()){const a=BA(e),o=dj(a,t),c=a===0?Math.max(0,dj(0,o+864e5+36e5)-t):Math.max(0,o+a*1e3-t);return{kind:a,startMs:o,remainingMs:c,daily:a===0}}function Wh(e,t){if(e<=0)return"";const a=Math.ceil(e/6e4);if(t){const o=Math.ceil(e/36e5);return o>=1?r("今日剩 {n} 小时",{n:o}):r("今日剩 {n} 分钟",{n:a})}return a>=1?r("剩 {n} 分钟",{n:a}):r("剩不到 1 分钟")}function El(e){const t=Number(e);if(!Number.isFinite(t))return"—";const a=window.wbUnits;return a?.formatTokens?a.formatTokens(t):String(Math.round(t))}function HA(e){return e>0&&e%3600===0?r("{n} 小时",{n:e/3600}):e>0&&e%60===0?r("{n} 分钟",{n:e/60}):r("{n} 秒",{n:e})}function kf(e){return e?.desktop===!0}function UA(e){return e?.chatSupported!==!1}function m$(e){return typeof e=="string"&&e.startsWith("custom-")}function h$(e){return r(e==="enterprise"?"企业":e==="ultimate"?"旗舰":"个人")}function Jh(e,t){const a=Number(e?.priority??100)-Number(t?.priority??100);return a!==0?a:(Number(e?.addedAt)||0)-(Number(t?.addedAt)||0)}function ur(e){return e?.enabled!==!1}function Cf(e,t=""){const a=e?.rateLimits||{},o=Date.now();return t?Number(a[t]?.resetAt)>o:Object.values(a).some(c=>Number(c?.resetAt)>o)}function VA(e){return e?.edition==="intl"?"intl":"cn"}function FA(e){return cr(An(e)).claim?e?.canClaim!==!1:!1}const $A="coding-plan",No="start-plan";function eg(e){return!!cr(An(e)).planChannel}function mj(e){return eg(e)?String(e?.zcodePlan||"").trim()===No?No:$A:""}function g$(e){return r(e===No?"套餐池(Start Plan)":"编码套餐(Coding Plan)")}function qA(e){switch(String(e??"").trim()){case"pending":return r("待生效");case"active":return r("生效中");case"expired":return r("已过期");case"unknown":return r("状态未知");default:return String(e??"")}}function tg(e){const t=e?.claimPlans;if(!t||typeof t!="object"||Array.isArray(t))return[];const a=gj();return Object.entries(t).filter(([,o])=>Number(o)>0&&gj(Number(o))===a).map(([o])=>o)}function x$(e){return tg(e).length>0}function b$(e){const t=tg(e),a=t.length?r("({plans})",{plans:t.join(r("、"))}):"";return r("今天(北京时间 {day})已领取 {n} 份{names};还有其他可领套餐时,点这里可以继续领;活动按自然日发新套餐,明天可再领",{day:gj(),n:t.length,names:a})}function v$(e){return!!cr(An(e)).usageDetail}function GA(e){return!!cr(An(e)).creditDetail}function hj(e){return/^free$/i.test(String(e??"").trim())}function KA(e){const t=String(e??"").trim();return/^trial$/i.test(t)?r("试用版"):hj(t)?r("免费版"):t}function gj(e=Date.now()){return new Date(e+8*3600*1e3).toISOString().slice(0,10)}function Tf(e,t,a){return Cf(e)||Zh(e,t)||fj(e,a)}function YA(e,t){const a=String(t.q||"").trim().toLowerCase();return a?[gu(e),e?.name,e?.nickname,e?.email,Qh(e),e?.id].some(c=>String(c||"").toLowerCase().includes(a)):!0}function XA(e,t){return t.provider==="all"||An(e)===t.provider}function xj(e,t){return t.enabled==="all"?!0:t.enabled==="enabled"?ur(e):!ur(e)}function QA(e,t,a,o){if(t.limit==="all")return!0;if(!ur(e))return!1;const c=Tf(e,a?.(e),o?.(e));return t.limit==="limited"?c:!c}function ZA(e,t,a,o){return XA(e,t)&&xj(e,t)&&QA(e,t,a,o)&&YA(e,t)}function y$(e,t,a,o){return(e||[]).filter(c=>ZA(c,t,a,o))}function WA(e,t,a,o){const c=e||[],d=h=>c.filter(b=>XA(b,t)&&(h==="enabled"||xj(b,t))&&YA(b,t)),f=d("enabled"),p=d("limit");return{enabledAll:f.length,enabled:f.filter(ur).length,disabled:f.filter(h=>!ur(h)).length,limitAll:p.length,normal:p.filter(h=>ur(h)&&!Tf(h,a?.(h),o?.(h))).length,limited:p.filter(h=>ur(h)&&Tf(h,a?.(h),o?.(h))).length}}function bj(e){const t=e?.rateLimits;if(!t||typeof t!="object")return[];const a=Date.now();return Object.entries(t).map(([o,c])=>({model:o,...c&&typeof c=="object"?c:{}})).filter(o=>Number(o.resetAt)>a).sort((o,c)=>Number(o.resetAt)-Number(c.resetAt))}function vj(e){const t=(e||[]).slice().sort(Jh),a=new Map;return t.forEach((o,c)=>a.set(o.id,{position:c+1,total:t.length})),a}function j$(e,t,a,o){const c=(e||[]).slice().sort(Jh),d=[],f=new Map;for(const p of c){const h=An(p);f.has(h)||(f.set(h,[]),d.push(h)),f.get(h).push(p)}return d.map((p,h)=>{const b=f.get(p)||[];return{provider:p,label:Pe().wbProviders?.labelOf?.(p)||p,rank:h+1,members:b,accounts:t?b.filter(t):b,enabled:b.filter(ur).length,disabled:b.filter(y=>!ur(y)).length,limited:b.filter(y=>ur(y)&&Tf(y,a?.(y),o?.(y))).length}})}function gu(e){if(!e)return"";const t=String(e.name||"").trim();if(e.nameCustom===!0&&t)return t;const a=String(e.email||"").trim();return cr(An(e)).emailAsName&&a?a:e?.nickname||t||Qh(e)||e?.id||""}const yj="已限流",JA=e=>new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime();function jj(e){const t=Number(e);if(!Number.isFinite(t)||t<=0||t<=Date.now())return yj;const a=new Date(t),o=a.toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit",hour12:!1}),c=Math.round((JA(a)-JA(new Date))/864e5);return c===0?r("今天 {clock}",{clock:o}):c===1?r("明天 {clock}",{clock:o}):r("{month}月{day}日 {clock}",{month:a.getMonth()+1,day:a.getDate(),clock:o})}function w$(e){const t=An(e);if(!cr(t).edition)return"";const a=VA(e),o=e?.editionLabel,c=o||(a==="intl"?"国际版":"国内版");return(Pe().wbProviders?.labelOf?.(t)||"").includes(c)?"":o||r(a==="intl"?"国际版":"国内版")}function S$(e){return[UA(e)?null:{text:r("仅账号管理"),kind:"plain",title:r("该提供商的推理转发尚未接入,账号不参与转发")},m$(An(e))&&e.hasCredentials===!1?{text:r("未配置凭证"),kind:"bad",title:r("这条自定义账号既没有 API Key,也没有勾选「无需鉴权」:转发时会被跳过,该提供商下的模型也不会出现在模型列表里。去账号「设置」里补上 Key,或勾选「该上游无需鉴权」")}:null,e.proxy?.error?{text:r("代理异常"),kind:"bad",title:r("{error}(转发时会回退直连)",{error:e.proxy.error})}:null,mj(e)===No?{text:r("套餐池"),kind:"plain",title:r("转发走套餐池(Start Plan)通道(zcode.z.ai 的 Anthropic 端点,用账号里的体验额度 / 活动领取额度);在账号设置里可切回编码套餐")}:null].filter(t=>t!==null)}const eR="workbuddy-desktop-accounts-filters",tR="workbuddy-desktop-accounts-collapsed",nR="workbuddy-desktop-accounts-names-hidden";function N$(){const e={provider:"all",enabled:"all",limit:"all",q:""},t=Pe().wbFilterMemory?.load(eR,e)||e;return{provider:String(t.provider||"all"),enabled:String(t.enabled||"all"),limit:String(t.limit||"all"),q:""}}function k$(){try{const e=JSON.parse(localStorage.getItem(tR)||"[]");return new Set(Array.isArray(e)?e.map(t=>String(t)).filter(Boolean):[])}catch{return new Set}}function C$(){try{return localStorage.getItem(nR)==="1"}catch{return!1}}let hn={version:0,filter:N$(),collapsed:k$(),selected:new Set,panels:new Map,connections:new Map,clash:null,dialog:null,namesHidden:C$(),usageBusy:!1,usageInflight:new Set};const wj=new Set;function sR(e){return wj.add(e),()=>{wj.delete(e)}}function Gs(){return hn}function Rn(e){hn={...hn,...e,version:hn.version+1},wj.forEach(t=>t())}function wr(){Rn({})}function Sj(){return Pe().wbApp?.getState?.()?.accounts}function Al(){const e=Sj()?.accounts;return Array.isArray(e)?e:[]}function Aa(e){return Al().find(t=>t.id===e)||null}function T$(e,t){const a=j$(Al(),c=>ZA(c,hn.filter,e,t),e,t);return{groups:a.filter(c=>c.accounts.length>0),allGroups:a}}function rR(){return OA(Sj())}function E$(e,t){return WA(Al(),hn.filter,e,t)}function A$(){return vj(Al())}function ng(){Pe().wbFilterMemory?.save(eR,{provider:hn.filter.provider,enabled:hn.filter.enabled,limit:hn.filter.limit})}function R$(e){hn.filter.q!==e&&Rn({filter:{...hn.filter,q:e}})}function O$(e){const t=e||"all";hn.filter.provider!==t&&(Rn({filter:{...hn.filter,provider:t}}),ng())}function aR(e,t){const a={...hn.filter,[e]:t};a.enabled==="disabled"&&a.limit!=="all"&&(a.limit="all"),Rn({filter:a}),ng()}function sg(){return hn.filter.provider!=="all"||hn.filter.enabled!=="all"||hn.filter.limit!=="all"||hn.filter.q.trim()!==""}function lR(){Rn({filter:{provider:"all",enabled:"all",limit:"all",q:""}}),ng()}function M$(){const e=hn.filter.provider;e!=="all"&&(rR().some(t=>t.id===e)||(Rn({filter:{...hn.filter,provider:"all"}}),ng()))}function oR(e){try{localStorage.setItem(tR,JSON.stringify([...e]))}catch{}}function iR(e){const t=new Set(hn.collapsed);t.has(e)?t.delete(e):t.add(e),oR(t),Rn({collapsed:t})}function D$(e,t){const a=new Set(hn.collapsed);for(const o of e)t?a.add(o):a.delete(o);oR(a),Rn({collapsed:a})}function I$(e){return hn.selected.has(e)}function P$(e,t){const a=new Set(hn.selected);t?a.add(e):a.delete(e),Rn({selected:a})}function cR(e,t){const a=new Set(hn.selected);for(const o of e)t?a.add(o):a.delete(o);Rn({selected:a})}function _$(){Rn({selected:new Set})}function uR(e,t){return hn.panels.get(e)?.has(t)===!0}function dR(e,t,a){if(!e)return;const o=new Map(hn.panels),c=new Set(o.get(e)||[]);a?c.add(t):c.delete(t),c.size?o.set(e,c):o.delete(e),Rn({panels:o})}function L$(e,t){const a=new Map(hn.panels);for(const o of e){const c=new Set(a.get(o)||[]);c.add(t),a.set(o,c)}Rn({panels:a})}function z$(){const e=!hn.namesHidden;try{localStorage.setItem(nR,e?"1":"0")}catch{}Rn({namesHidden:e})}function B$(e){return"*".repeat(Math.min(Math.max(e.length,4),12))}const fR="usage_not_configured",ko=new Map,Ef=new Map;function ua(e,t,a){ko.set(e,t),t!=null&&xu(t)?Ef.set(e,a):Ef.delete(e)}function Wa(e){const t=ko.get(e.id);if(t===void 0)return;if(!xu(t))return t;const a=Math.max(Number(e.addedAt)||0,Number(e.updatedAt)||0);return(Ef.get(e.id)||0)>=a?t:void 0}const Af=new Map;let pR=0;function Rl(e){return e?Af.get(e.id)||[]:[]}function H$(e){const t=Number(e?.tokenAt)||0;if(!t||t===pR)return!1;const a=e?.tokenUsage;if(!a||typeof a!="object")return!1;pR=t;const o=new Map;for(const[d,f]of Object.entries(a)){if(!Array.isArray(f))continue;const p=[];for(const h of f){if(!h||typeof h!="object")continue;const b=Number(h.kind),y=Number(h.windowStart),v=Number(h.used);!Number.isFinite(b)||b<0||!Number.isFinite(y)||y<=0||!Number.isFinite(v)||v<0||p.push({kind:b,windowStart:y,used:v})}o.set(d,p)}const c=o.size!==Af.size||[...o].some(([d,f])=>{const p=Af.get(d);return!p||p.length!==f.length||f.some((h,b)=>h.used!==p[b]?.used||h.windowStart!==p[b]?.windowStart)});Af.clear();for(const[d,f]of o)Af.set(d,f);return c}let rg=null;async function mR(e={}){const t=Gs().clash;if(!e.force&&t)return t;rg||(rg=(async()=>{try{const o=await Pe().workbuddyDesktop?.getProxies?.();if(!o||typeof o!="object"||!o.clash)throw new Error(r("代理列表响应异常({type})",{type:typeof o}));return o.clash}finally{rg=null}})());const a=await rg;return Rn({clash:a}),a}function U$(){Rn({clash:null})}let Rf=null,ag=null;function V$(){return Rf}async function hR(e={}){if(!e.force&&Rf)return Rf;ag||(ag=(async()=>{try{const a=await Pe().workbuddyDesktop?.getProxyPool?.();if(!a||typeof a!="object"||!Array.isArray(a.items))throw new Error(r("代理池响应异常({type})",{type:typeof a}));return a.items}finally{ag=null}})());const t=await ag;return Rf=t,t}let Nj=null;function F$(){return Nj}let lg=0,gR=!1;function $$(){if(!(Rf||Date.now(){lg=0,Nj=null,wr()}).catch(e=>{Nj=ut(e),wr()})}}function og(e){if(!Aa(e)){_e(r("账号不存在,请刷新后重试"),"err");return}Rn({dialog:{kind:"settings",id:e}})}function ig(){Rn({dialog:null})}function kj(e,t="enable"){const a=(Array.isArray(e)?e:[]).filter(o=>Aa(o));if(!a.length){_e(r("请先勾选要操作的账号"),"err");return}Rn({dialog:{kind:"batch",ids:a,action:t}})}function q$(e){let t=!1;for(const f of[...ko.keys()])e.has(f)||(ko.delete(f),t=!0);for(const f of[...Ef.keys()])e.has(f)||Ef.delete(f);const a=new Map(Gs().panels);for(const f of[...a.keys()])e.has(f)||(a.delete(f),t=!0);const o=new Map(Gs().connections);for(const f of[...o.keys()])e.has(f)||(o.delete(f),t=!0);const c=new Set(Gs().usageInflight);for(const f of[...c])e.has(f)||(c.delete(f),t=!0);const d=new Set(Gs().selected);for(const f of[...d])e.has(f)||(d.delete(f),t=!0);t&&Rn({panels:a,connections:o,usageInflight:c,selected:d})}const G$=2e3;function xR(e){return Gs().connections.get(e)||0}async function bR(){try{const e=await Pe().workbuddyDesktop?.getAccountConnections?.(),t=e?.counts&&typeof e.counts=="object"?e.counts:{},a=new Map;for(const[o,c]of Object.entries(t)){const d=Number(c)||0;d>0&&a.set(o,d)}return K$(a,Gs().connections)||Rn({connections:a}),!0}catch{return!1}}function K$(e,t){if(e.size!==t.size)return!1;for(const[a,o]of e)if(t.get(a)!==o)return!1;return!0}let vR=null;function Y$(){vR||(vR=setInterval(()=>{document.hidden||Pe().wbApp?.currentPage!=="accounts"||bR()},G$))}function Cj(){return Al().filter(e=>Ea(e)&&e.available!==!1)}function xu(e){if(e==null)return null;if(typeof e=="string")return{message:e,notConfigured:!1};if(typeof e!="object")return null;const t=e.error;return t?{message:String(t),notConfigured:e.code===fR}:null}function yR(e){return e.usage?e.usage:{error:e.error?String(e.error):r("余额响应为空"),code:e.code}}function jR(e){const t=Array.isArray(e?.results)?e.results:[],a=Number(e?.at)||Date.now();let o=0;for(const c of t)c?.id&&(ua(String(c.id),yR(c),Number(c.at)||a),o++);return o&&(wr(),Pe().wbApp?.renderTopbarStatus?.()),o}let wR=!1;function X$(e){if(!GA(e))return!1;const t=Wa(e);return!t||typeof t!="object"||Array.isArray(t)||xu(t)?!1:!Array.isArray(t.credits)}async function Q$(){if(!wR){wR=!0;for(const e of Al().filter(X$)){const t=ko.get(e.id);try{await Of(e.id)}catch{}const a=ko.get(e.id);t!==void 0&&(!a||xu(a))&&ua(e.id,t,Date.now()),wr()}}}let SR=0;async function Z$(){try{const e=await Pe().workbuddyDesktop?.getBalancesSnapshot?.(),t=H$(e);t&&(wr(),Pe().wbApp?.renderTopbarStatus?.());const a=Number(e?.at)||0;return!a||a===SR||(SR=a,!jR(e))?t:(Q$(),!0)}catch{return!1}}async function Of(e){const t=await Pe().workbuddyDesktop?.getAllBalances?.(e||void 0),a=Array.isArray(t?.results)?t.results:[],o=Date.now(),c=new Set;for(const d of a){if(!d?.id)continue;const f=String(d.id);e&&f!==e||(c.add(f),ua(f,yR(d),o))}if(e)return c.has(e)||ua(e,r("未返回余额数据"),o),wr(),t;for(const d of Cj())c.has(d.id)||ua(d.id,r("未返回余额数据"),o);return wr(),t}async function NR(){if(Gs().usageBusy)return;const e=Cj();if(!e.length){_e(r("暂无可查询余额的账号"),"err");return}Rn({usageBusy:!0}),e.forEach(t=>ua(t.id,null,Date.now())),wr();try{const t=(await Of(null))?.results||[],a=t.filter(f=>f.usage).length,o=t.filter(f=>f.code===fR).length,c=o?r("({n} 个未配置查询凭证)",{n:o}):"",d=t.length-a-o;_e(a+o===t.length?r("✅ 已更新 {n} 个账号的余额{suffix}",{n:a,suffix:c}):r("已更新 {ok}/{total} 个账号,{failed} 个失败",{ok:a,total:t.length,failed:d}),d?"err":"ok")}catch(t){const a=ut(t);e.forEach(o=>ua(o.id,r("查询失败:{message}",{message:a}),Date.now())),wr(),_e(r("余额查询失败:{message}",{message:a}),"err")}finally{Rn({usageBusy:!1})}}async function kR(e){if(Gs().usageInflight.has(e))return;const t=new Set(Gs().usageInflight);t.add(e),ua(e,null,Date.now()),Rn({usageInflight:t});try{await Of(e)}finally{const a=new Set(Gs().usageInflight);a.delete(e),Rn({usageInflight:a})}}async function W$(e){if(!Gs().usageInflight.has(e))try{await kR(e);const t=xu(ko.get(e));t?.notConfigured?_e(t.message,"ok"):t?_e(r("余额查询失败:{message}",{message:t.message}),"err"):_e(r("✅ 已更新余额"))}catch(t){ua(e,r("查询失败:{message}",{message:ut(t)}),Date.now()),wr(),_e(r("余额查询失败:{message}",{message:ut(t)}),"err")}}async function cg(e){if(e){const a=Aa(e);if(!a||!Ea(a))return;try{await kR(e)}catch(o){ua(e,r("查询失败:{message}",{message:ut(o)}),Date.now()),wr()}return}if(Gs().usageBusy)return;const t=Cj();if(t.length){Rn({usageBusy:!0}),t.forEach(a=>ua(a.id,null,Date.now())),wr();try{await Of(null)}catch(a){const o=ut(a);t.forEach(c=>ua(c.id,r("查询失败:{message}",{message:o}),Date.now())),wr()}finally{Rn({usageBusy:!1})}}}async function CR(e,t){try{await Pe().workbuddyDesktop?.updateAccount?.(e,{enabled:t}),await Pe().wbApp?.refresh?.(),_e(r(t?"✅ 已启用":"✅ 已禁用"))}catch(a){_e(r("操作失败:{message}",{message:ut(a)}),"err"),Pe().wbApp?.refresh?.()}}async function TR(e,t){if(!e.length)return!1;try{return await Pe().workbuddyDesktop?.reorderAccounts?.(e),_e(t?r("✅ 已保存:{note}",{note:t}):r("✅ 顺序已保存")),await Pe().wbApp?.refresh?.(),!0}catch(a){return _e(r("顺序未保存:{message}",{message:ut(a)}),"err"),Pe().wbApp?.refresh?.(),!1}}async function ER(e,t){if(e.length)try{await Pe().workbuddyDesktop?.batchAccounts?.({action:t?"enable":"disable",ids:e}),_e(t?r("✅ 已启用 {n} 个账号",{n:e.length}):r("✅ 已禁用 {n} 个账号",{n:e.length})),await Pe().wbApp?.refresh?.()}catch(a){_e(r("操作失败:{message}",{message:ut(a)}),"err"),Pe().wbApp?.refresh?.()}}async function J$(e,t){try{await Pe().workbuddyDesktop?.clearRateLimits?.(e,t||null),_e(t?r("✅ 已清除 {model} 的限流标记",{model:t}):r("✅ 已清除该账号全部限流标记")),await Pe().wbApp?.refresh?.()}catch(a){_e(r("清除失败:{message}",{message:ut(a)}),"err")}}async function e8(e,t,a){if(t===AR){og(e);return}if(t!==ug&&t!==a)try{const o=t===""?null:{source:"pool",proxyId:t.slice(Qa.length)},d=(await Pe().workbuddyDesktop?.updateAccount?.(e,{proxy:o}))?.changes,f=Array.isArray(d)&&d.length?d[0]:r("代理已更新");_e(`✅ ${f}`)}catch(o){_e(r("保存失败:{message}",{message:ut(o)}),"err")}finally{await Pe().wbApp?.refresh?.()}}const ug="__proxy_custom__",AR="__proxy_custom_edit__";function RR(e,t){const a=Aa(e);if(!a){_e(r("账号不存在,请刷新后重试"),"err");return}const o=Pe().wbZcodePlans;if(!o?.open){_e(r("套餐明细弹窗未加载,请重启应用后重试"),"err");return}o.open({id:e,name:t||a.name})}function t8(e,t,a=1){return{seat:t.get(e.id)||{position:1,total:1},rank:a,picked:I$(e.id),usageEntry:ko.get(e.id),limitsOpen:uR(e.id,"limits"),connections:xR(e.id)}}const n8={DEFAULT_PROVIDER_ID:mu,RACCOON_PROVIDER_ID:J6,providerOf:An,providerFeatures:cr,providerSummaries:OA,identifierOf:Qh,tokenExpiryOf:l$,supportsUsage:Ea,isDesktopAccount:kf,supportsChat:UA,byPriorityOrder:Jh,typeLabel:h$,isEnabled:ur,isRateLimited:Cf,isLimited:e=>Tf(e,e?Wa(e):void 0,Rl(e)),accountEdition:VA,supportsClaim:FA,matchEnabled:xj,matchLimit:QA,visibleAccounts:y$,filterCounts:WA,positionMap:vj,activeLimits:bj,editionSuffix:w$,formatResetText:jj};function s8(){window.wbAccountsView={render:()=>wr(),refreshCaches:q$,openPanels:L$,syncConnections:bR,applyBalances:jR,syncBalancesSnapshot:Z$,queryUsageFor:Of,queryAllUsage:NR,refreshUsageAfterCheckin:cg,supportsUsage:Ea,isDesktopAccount:kf,isEnabled:ur,isRateLimited:Cf},window.wbAccountsModel=n8,window.wbAccountPanel={open:og,close:ig,openBatch:kj,closeBatch:ig,syncAddProvider:()=>Pe().wbAccountAddForms?.syncAddProvider?.(),invalidate:U$}}function r8(e){return e.type==="balance"?r("余额 < {threshold}",{threshold:e.threshold}):e.reset==="daily"?r("每日消耗 ≥ {count} Token(每天 0 点重置)",{count:El(e.threshold)}):r("每 {period}消耗 ≥ {count} Token",{period:HA(e.period??0),count:El(e.threshold)})}function a8(e){return e.action==="disable"?r("禁用该账号(需手动重新启用)"):r("跳过该账号(自动恢复)")}function l8(e){return`${Math.round(e.threshold).toLocaleString("en-US")} Token`}function o8(e,t){if(t.enabled===!1)return{text:r("已停用"),kind:"off"};if(t.type==="balance"){const b=Wa(e),y=Zh(e,b),v=b&&typeof b=="object"?b:null,j=v?v.totalLeft??v.available:void 0,w=j==null||j===""||v?.unlimited?"":r(" · 当前 {n}",{n:ss(j)});return y?{text:r("已跳过{current}",{current:w}),kind:"warn",title:r("余额低于阈值,转发时会跳过该账号(余额回升自动恢复)")}:{text:r("未触发{current}",{current:w}),kind:"ok"}}const a=Rl(e),o=Nf(t,a),c=o?o.used:0,d=El(t.threshold),f=t.reset==="daily"?r(" · 今日 {used} / {quota}",{used:El(c),quota:d}):r(" · 本周期 {used} / {quota}",{used:El(c),quota:d}),p=o?` · ${Wh(pj(t).remainingMs,t.reset==="daily")}`:"";return o!==null&&c>=t.threshold?t.action==="disable"?e.enabled===!1?{text:r("已触发 · 账号已禁用"),kind:"danger",title:r("重置也不恢复,需手动启用")}:{text:r("已达上限{usage}",{usage:f}),kind:"warn",title:r("稍后由后台判定自动禁用")}:{text:r("已跳过{usage}{countdown}",{usage:f,countdown:p}),kind:"warn",title:r("窗口内已用 {used} / {limit} Token,转发时会跳过该账号(重置后自动恢复)",{used:Math.round(c).toLocaleString("en-US"),limit:Math.round(t.threshold).toLocaleString("en-US")})}:{text:r("未触发{usage}{countdown}",{usage:f,countdown:p}),kind:"ok",title:l8(t)}}function i8(e){return e>0&&e%3600===0?{value:String(e/3600),unit:"hours"}:e>0&&e%60===0?{value:String(e/60),unit:"minutes"}:{value:"1",unit:"hours"}}function OR(e){const t={type:"balance",action:"skip",thresholdInput:"",tokenUnit:"wan",reset:"fixed",periodInput:"1",periodUnit:"hours"};if(!e)return t;if(e.type==="balance")return{...t,type:"balance",action:e.action,thresholdInput:String(e.threshold)};if(e.reset==="daily")return{...t,type:"token",action:e.action,reset:"daily",thresholdInput:String(e.threshold%1e4===0?e.threshold/1e4:e.threshold),tokenUnit:e.threshold%1e4===0?"wan":"unit"};const a=i8(e.period??0);return{...t,type:"token",action:e.action,reset:"fixed",thresholdInput:String(e.threshold%1e4===0?e.threshold/1e4:e.threshold),tokenUnit:e.threshold%1e4===0?"wan":"unit",periodInput:a.value,periodUnit:a.unit}}function MR(e){const t=Number(e.thresholdInput);if(!Number.isFinite(t)||t<=0)return{error:r("限制阈值必须是大于 0 的数字")};if(e.type==="balance")return{rule:{type:"balance",action:e.action,threshold:t,enabled:!0}};const a=Math.round(e.tokenUnit==="wan"?t*1e4:t);if(e.reset==="daily")return{rule:{type:"token",action:e.action,threshold:a,reset:"daily",enabled:!0}};const o=Number(e.periodInput)*(e.periodUnit==="hours"?3600:60);if(!Number.isFinite(o)||o<=0)return{error:r("请填写重置周期")};const c=Math.round(o);return c_A?{error:r("重置周期必须是 30 分钟 ~ 24 小时")}:{rule:{type:"token",action:e.action,threshold:a,period:c,reset:"fixed",enabled:!0}}}function c8({account:e,target:t,onClose:a,onSave:o}){const[c,d]=x.useState(""),[f,p]=x.useState(t?.draft??null);if(x.useEffect(()=>{p(t?.draft??null),d("")},[t]),!t||!f)return null;const h=v=>{d(""),p({...f,...v})},b=()=>{const v=MR(f);if("error"in v){d(v.error);return}o(v.rule,t.index)},y=()=>{if(f.type==="balance"){const P=Wa(e);if(P&&typeof P=="object"){const T=P;if(T.unlimited)return r("当前可用 ∞(不参与余额不足判定)");const C=T.totalLeft??T.available;if(C!=null&&C!=="")return r("当前余额 {n};与余额列同一数字口径,严格小于才触发(等于阈值仍可用)",{n:ss(C)})}return r("读数来自自动余额查询;与余额列同一数字口径,严格小于才触发(等于阈值仍可用)")}const v=MR(f);if(!("rule"in v))return"";const j=v.rule,w=Nf(j,Rl(e));if(!w)return j.reset==="daily"?r("窗口 = 今天 0 点起(本地时区),0 点重置即清零恢复;按账号在 requests 表聚合"):r("窗口对齐自然时间(整点 / 整 N 分钟一轮回),重置即清零恢复;按账号在 requests 表聚合");const k=pj(j),S=El(w.used),N=El(j.threshold),R=j.reset==="daily"?r("今日已用"):r("本周期已用");return r("{scope} {used} / {quota} Token,{countdown}重置",{scope:R,used:S,quota:N,countdown:Wh(k.remainingMs,k.daily)})};return s.jsx(Yt,{open:!0,onOpenChange:v=>{v||a()},children:s.jsxs(Xt,{className:"w-[min(580px,calc(100vw-48px))]",showCloseButton:!0,children:[s.jsx(Vt,{children:s.jsx(Ut,{children:t.index>=0?r("编辑限制"):r("添加限制")})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("限制类型")}),s.jsxs(dt,{value:f.type,onValueChange:v=>h({type:v,thresholdInput:""}),children:[s.jsx(pt,{className:"w-[150px]","aria-label":r("限制类型"),children:s.jsx(ft,{children:f.type==="balance"?r("余额"):r("Token 消耗")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"balance",children:r("余额")}),s.jsx($e,{value:"token",children:r("Token 消耗")})]})]}),s.jsx("span",{className:"detail",children:r("余额沿用现有口径;Token 按重置方式内的累计消耗判定(切换类型会清空阈值)")})]}),f.type==="balance"?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("触发条件")}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("余额低于")}),s.jsx(Fe,{type:"number",min:0,step:1,className:"max-w-[120px]",placeholder:r("阈值"),value:f.thresholdInput,onChange:v=>h({thresholdInput:v.currentTarget.value})}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("时")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("触发后")}),s.jsxs(dt,{value:f.action,onValueChange:v=>h({action:v}),children:[s.jsx(pt,{className:"min-w-[280px]","aria-label":r("触发动作"),children:s.jsx(ft,{children:f.action==="disable"?r("禁用该账号(需手动重新启用)"):r("跳过该账号(余额回升自动恢复)")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"skip",children:r("跳过该账号(余额回升自动恢复)")}),s.jsx($e,{value:"disable",children:r("禁用该账号(需手动重新启用)")})]})]})]})]}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("重置方式")}),s.jsxs(dt,{value:f.reset,onValueChange:v=>h({reset:v}),children:[s.jsx(pt,{className:"w-[190px]","aria-label":r("重置方式"),children:s.jsx(ft,{children:f.reset==="daily"?r("自然日(每天 0 点)"):r("固定周期")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"fixed",children:r("固定周期")}),s.jsx($e,{value:"daily",children:r("自然日(每天 0 点)")})]})]}),s.jsx("span",{className:"detail",children:r("有的账号过了 0 点额度就回来 —— 选「自然日」")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("触发条件")}),f.reset==="daily"?s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"detail",style:{fontSize:13},children:r("每日消耗 ≥")}),s.jsx(Fe,{type:"number",min:0,step:1,className:"max-w-[110px]",placeholder:r("阈值"),value:f.thresholdInput,onChange:v=>h({thresholdInput:v.currentTarget.value})}),s.jsxs(dt,{value:f.tokenUnit,onValueChange:v=>h({tokenUnit:v}),children:[s.jsx(pt,{className:"w-[92px]","aria-label":r("Token 单位"),children:s.jsx(ft,{children:f.tokenUnit==="wan"?r("万"):r("个")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"wan",children:r("万")}),s.jsx($e,{value:"unit",children:r("个")})]})]}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("Token 时")})]}):s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"detail",style:{fontSize:13},children:r("每")}),s.jsx(Fe,{type:"number",min:1,step:1,className:"max-w-[90px]",placeholder:r("周期"),value:f.periodInput,onChange:v=>h({periodInput:v.currentTarget.value})}),s.jsxs(dt,{value:f.periodUnit,onValueChange:v=>h({periodUnit:v}),children:[s.jsx(pt,{className:"w-[92px]","aria-label":r("周期单位"),children:s.jsx(ft,{children:f.periodUnit==="hours"?r("小时"):r("分钟")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"minutes",children:r("分钟")}),s.jsx($e,{value:"hours",children:r("小时")})]})]}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("内消耗 ≥")}),s.jsx(Fe,{type:"number",min:0,step:1,className:"max-w-[110px]",placeholder:r("阈值"),value:f.thresholdInput,onChange:v=>h({thresholdInput:v.currentTarget.value})}),s.jsxs(dt,{value:f.tokenUnit,onValueChange:v=>h({tokenUnit:v}),children:[s.jsx(pt,{className:"w-[92px]","aria-label":r("Token 单位"),children:s.jsx(ft,{children:f.tokenUnit==="wan"?r("万"):r("个")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"wan",children:r("万")}),s.jsx($e,{value:"unit",children:r("个")})]})]}),s.jsx("span",{className:"detail",style:{fontSize:13},children:r("Token 时")})]})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("触发后")}),s.jsxs(dt,{value:f.action,onValueChange:v=>h({action:v}),children:[s.jsx(pt,{className:"min-w-[280px]","aria-label":r("触发动作"),children:s.jsx(ft,{children:f.action==="disable"?r("禁用该账号(需手动重新启用)"):r("跳过该账号(重置后自动恢复)")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"skip",children:r("跳过该账号(重置后自动恢复)")}),s.jsx($e,{value:"disable",children:r("禁用该账号(需手动重新启用)")})]})]})]})]}),s.jsx("p",{className:"detail limiter-hint",children:y()}),c?s.jsx("p",{className:"detail text-destructive",children:c}):null]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",onClick:a,children:r("取消")}),s.jsx(ne,{variant:"default",onClick:b,children:t.index>=0?r("保存规则"):r("添加规则")})]})]})})}function u8({account:e,draft:t,onChange:a}){const[o,c]=x.useState(null),d=()=>c({index:-1,draft:OR(null)}),f=y=>c({index:y,draft:OR(t[y])}),p=(y,v)=>{const j=[...t];v>=0?j[v]=y:j.push(y),a(j),c(null)},h=y=>{a(t.filter((v,j)=>j!==y)),o&&c(null)},b=(y,v)=>{const j=[...t];j[y]={...j[y],enabled:v},a(j)};return s.jsxs(s.Fragment,{children:[t.length?s.jsx("div",{className:"limiter-rules mt-2.5",children:t.map((y,v)=>{const j=o8(e,y);return s.jsxs("div",{className:"limiter-rule","data-off":y.enabled===!1||void 0,children:[s.jsx(Zn,{checked:y.enabled!==!1,"aria-label":r("启用该规则"),onCheckedChange:w=>b(v,w===!0)}),s.jsx("div",{className:"limiter-rule-main",children:s.jsxs("span",{className:"limiter-rule-cond",children:[s.jsx(ze,{variant:"secondary",shape:"tag",children:y.type==="balance"?r("余额"):"Token"})," ",r("{cond} 时 → {action}",{cond:r8(y),action:a8(y)})]})}),s.jsx(ze,{variant:j.kind==="ok"?"success":j.kind==="warn"?"warning":j.kind==="danger"?"destructive":"secondary",shape:"tag",title:j.title,children:j.text}),s.jsxs("div",{className:"limiter-rule-ops",children:[s.jsx(ne,{variant:"ghost",onClick:()=>f(v),children:r("编辑")}),s.jsx(ne,{variant:"ghost",onClick:()=>h(v),children:r("删除")})]})]},v)})}):s.jsx("p",{className:"detail mt-2.5",children:r("还没有限制规则:账号照常参与转发,余额与 Token 消耗都不设上限。")}),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx(ne,{variant:"outline",onClick:d,children:r("+ 添加限制")}),s.jsx("span",{className:"detail",children:r("可添加多条;同类规则也允许并存(例如一条按余额、两条不同重置方式的 Token)")})]}),s.jsx(c8,{account:e,target:o,onClose:()=>c(null),onSave:p})]})}function d8(e,t){const a=hu(e);return JSON.stringify(t)===JSON.stringify(a)?null:{patch:{limiters:t}}}function f8(e){return hu(e).map(t=>({...t}))}const p8={seconds:1,minutes:60,hours:3600};function m8(e){return e>0&&e%3600===0?{value:String(e/3600),unit:"hours"}:e>0&&e%60===0?{value:String(e/60),unit:"minutes"}:e>0?{value:String(e),unit:"seconds"}:{value:"5",unit:"minutes"}}function h8(e){const{enabled:t,interval:a}=zA(e),o=m8(t?a:0);return{enabled:t,intervalInput:o.value,unit:o.unit}}function g8(e,t){const a=Math.round(Number(t.intervalInput)*p8[t.unit]);if(t.enabled){if(!Number.isFinite(Number(t.intervalInput))||Number(t.intervalInput)<=0)return{error:r("请填写查询间隔")};if(aDA)return{error:r("查询间隔必须是 {min} 秒 ~ 24 小时",{min:uj})}}const o={},c=zA(e);return(t.enabled!==c.enabled||t.enabled&&a!==c.interval)&&(o.usageQuery={enabled:t.enabled,interval:t.enabled?a:c.interval}),o.usageQuery?{patch:o}:null}function x8({account:e,draft:t,onChange:a}){const o=c=>a({...t,...c});return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"field-row mt-2.5",children:s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2.5 font-normal",children:[s.jsx(Zn,{checked:t.enabled,onCheckedChange:c=>o({enabled:c===!0}),"aria-label":r("自动查询余额")}),s.jsx("span",{className:"text-xs text-subtle",children:r("自动查询余额(按下面的间隔自动刷新余额列的读数)")})]})}),t.enabled?s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-usage-interval",children:r("查询间隔")}),s.jsx(Fe,{id:"account-usage-interval",type:"number",min:1,step:1,className:"max-w-[110px]",value:t.intervalInput,onChange:c=>o({intervalInput:c.currentTarget.value})}),s.jsxs(dt,{value:t.unit,onValueChange:c=>o({unit:c}),children:[s.jsx(pt,{className:"w-[92px]","aria-label":r("间隔单位"),children:s.jsx(ft,{children:t.unit==="hours"?r("小时"):t.unit==="minutes"?r("分钟"):r("秒")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"seconds",children:r("秒")}),s.jsx($e,{value:"minutes",children:r("分钟")}),s.jsx($e,{value:"hours",children:r("小时")})]})]}),s.jsx("span",{className:"detail",children:r("30 秒 ~ 24 小时;手动查询会顺延下一轮")})]}):null]})}const b8={sub2api:{label:"Sub2API",endpoint:"{base}/v1/usage",note:r("用这条账号的 API Key 查询,不需要额外配置。"),fields:[]},new_api:{label:"NewAPI",endpoint:"{base}/api/user/self + /api/status",note:r("用 NewAPI 站点的个人访问令牌查询账户余额(不是这条账号的上游 API Key)。令牌在站点的「个人设置」里生成,只有旧版 / 定制站点才需要额外填用户 ID。"),fields:[{key:"accessToken",label:r("NewAPI 个人访问令牌"),secret:!0,placeholder:r("在 NewAPI 站点「个人设置」里生成的访问令牌"),hint:r("必填;留空 = 不修改,清除用右边的按钮")},{key:"userId",label:r("NewAPI 用户 ID"),placeholder:r("旧版 / 定制站点才需要,新版可留空"),hint:r("可留空:新版请求头只认令牌;旧版会把用户 ID 放进 New-Api-User 头")}]},deepseek:{label:"DeepSeek",endpoint:"{base}/user/balance",note:r("用这条账号的 API Key 查询,不需要额外配置。"),fields:[]},opencode:{label:"OpenCode Go",endpoint:"{base}/v1/usage",note:r("用这条账号的 API Key 查询订阅用量,不需要额外配置;读数展开成 5 小时 / 每周 / 每月三个窗口。"),fields:[]},sensenova:{label:"商汤日日新",endpoint:"platform.sensenova.cn 控制台",note:r("用商汤日日新控制台的账号密码查询(与推理用的 API Key 不是同一套)。网关会自动换取登录票并缓存,过期后自动重登,不需要手动维护。"),fields:[{key:"username",label:r("账号"),placeholder:r("商汤日日新控制台的登录账号"),hint:r("必填")},{key:"password",label:r("密码"),secret:!0,placeholder:r("商汤日日新控制台的登录密码"),hint:r("留空 = 不修改,清除用右边的按钮")}]},zhipu:{label:"智谱",endpoint:"bigmodel.cn 控制台",note:r("用 bigmodel.cn 控制台的访问令牌查询账户余额(人民币元)。令牌是登录后浏览器 Cookie `bigmodel_token_production` 的值:开发者工具 → 应用(Application)→ Cookie 里复制。"),fields:[{key:"token",label:r("访问令牌"),secret:!0,placeholder:r("bigmodel_token_production 的值"),hint:r("必填;留空 = 不修改,清除用右边的按钮")}]},zhipu_zai:{label:"智谱(z.ai 国际)",endpoint:"api.z.ai 控制台",note:r("用这条账号的 API Key 生成签名后查询账户余额(美元),不需要额外配置。要求 API Key 是 z.ai 的「id.secret」形态(控制台生成的 Key 就是)。"),fields:[]}};function Mf(e){return e?b8[e]??null:null}function v8(e,t){return t.secret?t.key==="accessToken"?e?.hasAccessToken===!0:t.key==="password"?e?.hasPassword===!0:t.key==="token"?e?.hasToken===!0:!1:!1}function y8(e){const t=String(e?.scheme||"");return t==="new_api"?e?.hasAccessToken===!0:t==="sensenova"?String(e?.username||"").trim()!==""&&e?.hasPassword===!0:t==="zhipu"?e?.hasToken===!0:!0}function j8(e){return{userId:String(e?.userId||""),username:String(e?.username||""),accessToken:"",password:"",token:""}}function w8(e,t){const a=Mf(e);if(!a||!a.fields.length)return null;const o={};for(const c of a.fields){const d=String(t[c.key]??"").trim();if(c.secret){d&&(o[c.key]=d);continue}o[c.key]=d}return Object.keys(o).length?o:null}function S8({field:e,value:t,configured:a,onValue:o,onClear:c,clearBusy:d,idPrefix:f}){const p=`${f}-${e.key}`;return s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:p,children:e.label}),s.jsx(Fe,{id:p,className:"min-w-[220px]",type:e.secret?"password":"text",autoComplete:e.secret?"new-password":"off",placeholder:a?r("已配置,留空则不修改"):e.placeholder,title:e.hint,value:t,onChange:h=>o(h.currentTarget.value)}),a&&c?s.jsx(ne,{variant:"outline",size:"sm",disabled:d===!0,onClick:c,title:r("清除已配置的 {label}",{label:e.label}),children:r("清除")}):null]})}function N8({spec:e,values:t,configured:a,onValue:o,onClear:c,clearBusy:d,idPrefix:f}){return s.jsxs(s.Fragment,{children:[s.jsxs("p",{className:"detail mt-2.5",children:[r("余额查询方案:{label}",{label:e.label}),s.jsx("span",{className:"ml-1 text-subtle",children:e.endpoint})," — ",e.note]}),e.fields.map(p=>s.jsx(S8,{field:p,idPrefix:f,value:t[p.key]||"",configured:a[p.key]===!0,onValue:h=>o(p.key,h),onClear:c?()=>c(p.key):void 0,clearBusy:d},p.key))]})}const DR=64;function k8(e,t){const a=An(e);return t.filter(o=>o.id!==e.id&&An(o)===a)}const Ol=999,IR=8;function dg(e){return gu(e)||e?.id||""}function PR(e){const t=e?.config?.source||e?.source,a=e?.config||null,o=t==="rotate";return{mode:t==="pool"?"pool":o?"rotate":t==="clash"?"clash":t==="custom"?"custom":"none",proxyId:t==="pool"?String(a?.proxyId||""):"",rotateAll:o?a?.all!==!1:!0,rotateIds:o&&Array.isArray(a?.proxyIds)?a.proxyIds.map(String):[],listenerUid:a?.source==="clash"||t==="clash"?String(a?.listenerUid||""):"",protocol:a?.protocol==="socks5"?"socks5":"http",host:a?.host||"",port:a?.port===void 0||a?.port===null?"":String(a.port),username:a?.username||"",password:a?.password||""}}function Tj(e){if(e.mode==="none")return null;if(e.mode==="pool"){if(!e.proxyId)throw new Error(r("请先选择已保存的代理"));return{source:"pool",proxyId:e.proxyId}}if(e.mode==="rotate"){if(e.rotateAll)return{source:"rotate",all:!0};if(!e.rotateIds.length)throw new Error(r("轮询至少要选择一条代理(或改选「全部」)"));return{source:"rotate",all:!1,proxyIds:[...e.rotateIds]}}if(e.mode==="clash"){if(!e.listenerUid)throw new Error(r("请先选择 Clash Verge 出口"));return{source:"clash",listenerUid:e.listenerUid}}const t=e.host.trim(),a=Number(e.port);if(!t)throw new Error(r("请填写代理主机地址"));if(!Number.isInteger(a)||a<1||a>65535)throw new Error(r("代理端口必须是 1-65535 的整数"));return{source:"custom",protocol:e.protocol==="socks5"?"socks5":"http",host:t,port:a,username:e.username.trim(),password:e.password}}function _R(e){const t=e.profileActive===!1?r("(其他订阅,可能未生效)"):"",a=e.enabled===!1?r("(已在 Clash 中禁用)"):"";return`${e.name} :${e.port}${t}${a}`}function LR({draft:e,onChange:t,idPrefix:a,allowRotate:o=!1}){const d=Gs().clash,f=Array.isArray(d?.options)?d.options:[],p=e.mode==="clash",[h,b]=x.useState(!1),[y,v]=x.useState(null),[j,w]=x.useState(null),[k,S]=x.useState(""),N=C=>t({...e,...C});x.useEffect(()=>{p&&mR().catch(()=>{})},[p]);const R=x.useCallback((C=!1)=>{S(""),hR({force:C}).then(E=>w(E)).catch(E=>{w([]),S(ut(E))})},[]);x.useEffect(()=>{(e.mode==="pool"||e.mode==="rotate")&&j===null&&R()},[e.mode,j,R]);function P(){return e.rotateAll?(j??[]).filter(C=>C.enabled!==!1).map(C=>C.id):[...e.rotateIds]}async function T(){if(h)return;if(e.mode==="rotate"){const E=P();if(!E.length){_e(r("轮询至少要选择一条代理(或改选「全部」)"),"err");return}const D=E.slice(0,IR);b(!0),v(r("正在连接上游…"));let I=0;const O=[];for(const H of D){const B=j?.find(L=>L.id===H)?.name||H;try{const L=await Pe().workbuddyDesktop?.testProxyPoolItem?.(H);L?.success?I+=1:O.push(`${B}(${L?.error||r("连接失败")})`)}catch(L){O.push(`${B}(${ut(L)})`)}}const _=E.length-D.length,z=r("✅ {ok}/{total} 个出口可用",{ok:I,total:D.length})+(_>0?r("(只测了前 {limit} 个,还有 {rest} 个未测)",{limit:IR,rest:_}):"");v(s.jsxs("span",{className:O.length?"text-destructive":"text-success",children:[z,O.length?` ${Za(O.join(r(";")))}`:""]})),b(!1);return}if(e.mode==="pool"){if(!e.proxyId){_e(r("请先选择已保存的代理"),"err");return}b(!0),v(r("正在连接上游…"));try{const E=await Pe().workbuddyDesktop?.testProxyPoolItem?.(e.proxyId);v(E?.success?s.jsxs("span",{className:"text-success",children:[r("✅ 出口可用"),E.ip?r(" 出口 IP {ip}",{ip:Za(E.ip)}):"",E.durationMs!==void 0&&E.durationMs!==""?` ${Za(String(E.durationMs))}ms`:""]}):s.jsxs("span",{className:"text-destructive",children:["❌ ",Za(E?.error||r("连接失败"))]}))}catch(E){v(s.jsxs("span",{className:"text-destructive",children:["❌ ",Za(ut(E))]}))}finally{b(!1)}return}let C;try{C=Tj(e)}catch(E){_e(ut(E),"err");return}b(!0),v(r("正在连接上游…"));try{const E=await Pe().workbuddyDesktop?.testProxy?.({proxy:C});E?.success?v(s.jsxs("span",{className:"text-success",children:[r("✅ 出口可用"),E.status!==void 0&&E.status!==""?` HTTP ${Za(String(E.status))}`:"",E.ip?r(" 出口 IP {ip}",{ip:Za(E.ip)}):"",E.durationMs!==void 0&&E.durationMs!==""?` ${Za(String(E.durationMs))}ms`:""]})):v(s.jsxs("span",{className:"text-destructive",children:["❌ ",Za(E?.error||r("连接失败"))]}))}catch(E){v(s.jsxs("span",{className:"text-destructive",children:["❌ ",Za(ut(E))]}))}finally{b(!1)}}return s.jsxs("div",{className:"flex flex-col",children:[s.jsxs(_h,{value:e.mode,onValueChange:C=>N({mode:C}),className:"flex-row flex-wrap items-center gap-5","aria-label":r("代理方式"),children:[s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(jo,{value:"none"}),r("无代理(直连)")]}),s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(jo,{value:"pool"}),r("已保存的代理")]}),o?s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",title:r("逐请求轮换出口(换 IP):OpenCode Zen 免费档按 IP 限流,单个 IP 的额度用完会对它一律 429"),children:[s.jsx(jo,{value:"rotate"}),r("轮询(换 IP)")]}):null,p?s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(jo,{value:"clash"}),"Clash Verge"]}):null,s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(jo,{value:"custom"}),r("自定义")]})]}),e.mode==="pool"?s.jsxs("div",{className:"mt-3",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:`${a}-pool-exit`,children:r("代理")}),s.jsxs(dt,{value:e.proxyId,disabled:!j?.length,onValueChange:C=>N({proxyId:String(C)}),children:[s.jsx(pt,{id:`${a}-pool-exit`,className:"min-w-[220px]",children:s.jsx(ft,{children:j?.find(C=>C.id===e.proxyId)?fu(j.find(C=>C.id===e.proxyId)):j===null?r("正在读取…"):j.length?r("请选择代理"):r("还没有保存的代理")})}),s.jsx(mt,{children:(j??[]).map(C=>s.jsx($e,{value:C.id,children:fu(C)},C.id))})]}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>R(!0),children:r("重新读取")})]}),s.jsx("div",{className:"detail mt-1.5",children:k?r("读取失败:{error}",{error:k}):j===null?r("正在读取代理列表…"):j.length?r("地址与端口由「网络代理」页管理:那边改一次、测一次,所有引用它的账号一起生效"):r("「网络代理」页还没有出口 —— 去那里新增,或在「订阅管理」里点「同步 Clash Verge」把 Clash 的出口导进来")})]}):null,e.mode==="rotate"?s.jsxs("div",{className:"mt-3",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-x-2.5 gap-y-1",children:[s.jsx(_r,{id:`${a}-rotate-all`,checked:e.rotateAll,"aria-label":r("轮询全部代理节点"),onCheckedChange:C=>N({rotateAll:C===!0})}),s.jsx("label",{htmlFor:`${a}-rotate-all`,className:"cursor-pointer text-xs text-subtle",children:r("全部代理节点(推荐)")}),s.jsx("span",{className:"detail",children:r("「网络代理」页里每个启用的出口轮流使用;之后新加的出口自动加入")})]}),e.rotateAll?null:s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:`${a}-rotate-exits`,children:r("轮询的代理")}),s.jsx(Kh,{id:`${a}-rotate-exits`,value:e.rotateIds,onValueChange:C=>N({rotateIds:C.map(String)}),options:(j??[]).map(C=>({value:C.id,label:fu(C)})),placeholder:r("选择要轮询的代理(可多选)"),"aria-label":r("轮询的代理")}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>R(!0),children:r("重新读取")})]}),s.jsx("div",{className:"detail mt-1.5",children:k?r("读取失败:{error}",{error:k}):j===null?r("正在读取代理列表…"):j.length?r("每条请求换一个出口(按顺序轮流),上游看到的 IP 因此是变化的;出口的地址与端口由「网络代理」页管理"):r("「网络代理」页还没有出口 —— 去那里新增,或在「订阅管理」里点「同步 Clash Verge」把 Clash 的出口导进来")})]}):null,e.mode==="clash"?s.jsxs("div",{className:"mt-3",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:`${a}-clash-exit`,children:r("出口")}),s.jsxs(dt,{value:e.listenerUid,disabled:!f.length,onValueChange:C=>N({listenerUid:String(C)}),children:[s.jsx(pt,{id:`${a}-clash-exit`,className:"min-w-[220px]",children:s.jsx(ft,{children:f.find(C=>String(C.uid)===e.listenerUid)?_R(f.find(C=>String(C.uid)===e.listenerUid)):d?.available===!1?r("未检测到 Clash Verge"):f.length?r("请选择出口"):r("没有可用出口")})}),s.jsx(mt,{children:f.map(C=>s.jsx($e,{value:String(C.uid),children:_R(C)},String(C.uid)))})]}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>{mR({force:!0}).then(()=>_e(r("✅ 已重新读取 Clash Verge 配置"))).catch(C=>_e(r("读取失败:{error}",{error:ut(C)}),"err"))},children:r("重新读取")})]}),s.jsx("div",{className:"detail mt-1.5",children:d===null?r("正在读取 Clash Verge 配置…"):d.available===!1?d.error?r("不可用:{error}",{error:d.error}):r("未检测到 Clash Verge 配置"):f.length?r("读取自 {dir};端口由 Clash Verge 管理,这里实时同步",{dir:d.dir||"Clash Verge"}):r("Clash Verge 里还没有配置混合监听器或节点端口")}),s.jsxs("p",{className:"detail mt-1.5",children:[r("这是既有配置(直接引用 Clash 出口,不经过代理池)。推荐改用上面的"),s.jsx("b",{children:r("「已保存的代理」")}),r(":到「网络代理」页的「订阅管理」里点「同步 Clash Verge」把出口导进池后即可选 —— 那样能集中测试、也能被多个账号共用。")]})]}):null,e.mode==="custom"?s.jsxs("div",{className:"mt-3",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:`${a}-protocol`,children:r("协议")}),s.jsxs(dt,{value:e.protocol,onValueChange:C=>N({protocol:C}),children:[s.jsx(pt,{id:`${a}-protocol`,className:"min-w-[110px]",children:s.jsx(ft,{children:e.protocol==="socks5"?"SOCKS5":"HTTP"})}),s.jsxs(mt,{children:[s.jsx($e,{value:"http",children:"HTTP"}),s.jsx($e,{value:"socks5",children:"SOCKS5"})]})]}),s.jsx("label",{htmlFor:`${a}-host`,className:"ml-2",children:r("主机")}),s.jsx(Fe,{id:`${a}-host`,className:"min-w-[140px]",placeholder:"127.0.0.1",value:e.host,onChange:C=>N({host:C.currentTarget.value})}),s.jsx("label",{htmlFor:`${a}-port`,children:r("端口")}),s.jsx(Fe,{id:`${a}-port`,type:"number",min:1,max:65535,className:"max-w-[110px]",placeholder:"7890",value:e.port,onChange:C=>N({port:C.currentTarget.value})})]}),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:`${a}-user`,children:r("用户名")}),s.jsx(Fe,{id:`${a}-user`,placeholder:r("可选"),autoComplete:"off",value:e.username,onChange:C=>N({username:C.currentTarget.value})}),s.jsx("label",{htmlFor:`${a}-pass`,children:r("密码")}),s.jsx(Fe,{id:`${a}-pass`,type:"password",placeholder:r("可选"),autoComplete:"new-password",value:e.password,onChange:C=>N({password:C.currentTarget.value})})]})]}):null,s.jsxs("div",{className:"field-row mt-3",children:[s.jsx(ne,{variant:"outline",size:"sm",disabled:h,onClick:()=>{T()},children:r(h?"测试中…":"测试出口")}),s.jsx("span",{className:"detail",children:y})]})]})}function C8({plan:e,hasJwt:t,onChange:a}){const o=g$(e),[c,d]=x.useState(null);return x.useEffect(()=>{if(e!==No)return()=>{};let f=!0;const p=()=>{Promise.resolve(Pe().workbuddyDesktop?.zcodeCaptchaStats?.()).then(b=>{f&&b&&d({ready:Number(b.ready)||0,target:Number(b.target)||0})}).catch(()=>{})};p();const h=window.setInterval(p,5e3);return()=>{f=!1,window.clearInterval(h)}},[e]),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-plan-channel",children:r("使用套餐")}),s.jsxs(dt,{value:e,onValueChange:f=>a(String(f)),children:[s.jsx(pt,{id:"account-plan-channel",className:"min-w-[220px]",children:s.jsx(ft,{children:o})}),s.jsxs(mt,{children:[s.jsx($e,{value:$A,children:r("编码套餐(Coding Plan)— 走开放平台端点,消耗开放平台的额度(订阅套餐 / 资源包 / 充值余额)")}),s.jsx($e,{value:No,children:r("套餐池(Start Plan)— 走 zcode.z.ai 端点,消耗 ZCode 套餐池的额度(新用户体验额度 / 活动领取)")})]})]}),e===No&&!t?s.jsx("span",{className:"detail text-destructive",children:r("该账号没有套餐登录态(jwt),套餐池通道会失败:请重新登录该账号")}):null,e===No?s.jsxs("span",{className:"detail",title:r("套餐池的推理端点要求每条请求带一个阿里云验证码令牌;令牌由本应用在后台静默铸造,界面关闭时无法铸造"),children:[r("验证码令牌:{counts}",{counts:c?`${c.ready} / ${c.target||3}`:r("读取中…")}),c&&c.ready===0?r("(库存为空,正在补;补不上时转发会失败)"):""]}):null]})}function T8({configured:e,value:t,onChange:a,onClear:o,clearBusy:c}){return s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-balance-token-input",children:r("余额查询凭证")}),s.jsx(Fe,{id:"account-balance-token-input",className:"min-w-[220px]",placeholder:r(e?"已配置,留空则不修改":"一般不用填"),title:r("积分查询已复用转发用的登录凭证,这里通常留空即可。只有旧版本填过、或从旧代理导入过凭证时才有值"),value:t,onChange:d=>a(d.currentTarget.value)}),e?s.jsx(ne,{variant:"outline",size:"sm",disabled:c,onClick:o,title:r("清除已配置的余额查询凭证"),children:r("清除")}):null]})}function E8({hasApiKey:e,noAuth:t,value:a,onValue:o,onToggleNoAuth:c,onClear:d,clearBusy:f}){return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-api-key-input",children:r("API Key")}),s.jsx(Fe,{id:"account-api-key-input",type:"password",autoComplete:"new-password",className:"min-w-[220px]",disabled:t,placeholder:e?r("已配置,留空则不修改"):"sk-…",title:r("上游的 API Key。留空 = 不修改(改凭证不会换账号 id);要清掉已配的凭证用右边的「清除」"),value:a,onChange:p=>o(p.currentTarget.value)}),e&&!t?s.jsx(ne,{variant:"outline",size:"sm",disabled:f,onClick:d,title:r("清除已配置的 API Key(转发时会因缺少凭证被跳过)"),children:r("清除")}):null]}),s.jsx("div",{className:"field-row mt-2.5",children:s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2.5 font-normal",children:[s.jsx(_r,{checked:t,"aria-label":r("该上游无需鉴权"),onCheckedChange:p=>c(p===!0)}),s.jsx("span",{className:"text-xs text-subtle",children:r("该上游无需鉴权(转发与拉取模型都不发送鉴权头)")})]})}),s.jsxs("p",{className:"detail",children:[r("上游本来不要凭证时(本地 Ollama、OpenCode Zen 的免费档)勾上这一项:账号会被正常选路;只把 Key 留空"),s.jsx("strong",{children:r("又不勾")}),r("会被当成「未配置凭证」而跳过。")]})]})}function A8({provider:e,name:t,protocol:a,baseUrl:o,count:c,emulation:d,onName:f,onProtocol:p,onBaseUrl:h,onEmulation:b,onRemove:y}){const v=Pe().wbProviders?.PROTOCOL_OPTIONS||[{value:"openai",label:r("OpenAI 兼容")},{value:"anthropic",label:"Anthropic"}],j=v.find(w=>w.value===a)?.label||a;return s.jsxs(dn,{children:[s.jsx("h3",{children:r("提供商")}),s.jsxs("p",{children:[r("这一栏改的是"),s.jsx("strong",{children:r("「{name}」本身",{name:e.name||e.id})}),r("(名下 {count} 个账号共用)",{count:c}),r("改协议 / Base URL 会改变它们的转发方式,正在进行的请求可能失败;模型清单与映射在「模型管理」页。")]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"account-provider-name",children:r("名称")}),s.jsx(Fe,{id:"account-provider-name",maxLength:DR,className:"min-w-[220px]",placeholder:r("提供商显示名,1~{max} 个字符",{max:DR}),value:t,onChange:w=>f(w.currentTarget.value)})]}),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-provider-protocol",children:r("协议")}),s.jsxs(dt,{value:a,onValueChange:w=>p(String(w)),children:[s.jsx(pt,{id:"account-provider-protocol",className:"min-w-[180px]",children:s.jsx(ft,{children:j})}),s.jsx(mt,{children:v.map(w=>s.jsx($e,{value:w.value,children:w.label},w.value))})]})]}),s.jsxs("div",{className:"field-row mt-2.5",children:[s.jsx("label",{htmlFor:"account-provider-baseurl",children:r("Base URL")}),s.jsx(Fe,{id:"account-provider-baseurl",className:"min-w-[260px]",placeholder:r("OpenAI 兼容填到 /v1;Anthropic 填根地址"),value:o,onChange:w=>h(w.currentTarget.value)})]}),s.jsx("div",{className:"field-row mt-2.5",children:s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2.5 font-normal",children:[s.jsx(_r,{checked:d==="opencode","aria-label":r("伪装 OpenCode 官方客户端"),onCheckedChange:w=>b(w===!0?"opencode":"")}),s.jsx("span",{className:"text-xs text-subtle",children:r("伪装 OpenCode 官方客户端(OpenCode Zen 免费档要它才放行)")})]})}),s.jsxs("p",{className:"detail",children:[r("开启后,网关按 OpenCode 官方 CLI 的形状发请求:没填 Key 的账号用匿名凭证"),s.jsx("code",{children:"public"}),r("、补官方会话头、请求体补两个占位工具(上游免费档的三道校验)。"),s.jsx("strong",{children:r("它会改写请求体")}),r(",只对 OpenCode Zen 这类上游有意义,别的家请关掉。")]}),s.jsxs("div",{className:"field-row mt-3",children:[s.jsx(ne,{variant:"destructive",onClick:y,children:r("删除提供商")}),s.jsx("span",{className:"detail",children:r("级联删除名下全部账号,不可恢复")})]})]})}function R8({id:e,onClose:t}){const a=Aa(e),[o,c]=x.useState(a?.enabled!==!1),[d,f]=x.useState(a?.name||""),[p,h]=x.useState(()=>PR(a?.proxy)),[b,y]=x.useState(""),[v,j]=x.useState(()=>mj(a)),[w,k]=x.useState(!1),[S,N]=x.useState(""),[R,P]=x.useState(null),[T,C]=x.useState(""),[E,D]=x.useState("chat_completions"),[I,O]=x.useState(""),[_,z]=x.useState(""),[H,B]=x.useState(""),[L,F]=x.useState(a?.noAuth===!0),[$,X]=x.useState(()=>h8(a)),[K,q]=x.useState(()=>j8(a?.balanceQuery)),[Q,G]=x.useState(()=>f8(a)),[J,Y]=x.useState("basic"),[re,M]=x.useState(()=>String(Number(a?.maxConcurrent)||0));if(x.useEffect(()=>{let Ae=!0;P(null);const oe=Aa(e);return oe?(Promise.resolve(Pe().wbCustomProvidersUi?.find?.(An(oe))).then(me=>{!Ae||!me||(P(me),C(me.name||""),D(me.protocol||"chat_completions"),O(me.baseUrl||""),z(typeof me.clientEmulation=="string"?me.clientEmulation:""))}).catch(()=>{}),()=>{Ae=!1}):()=>{Ae=!1}},[e]),!a)return s.jsx(Yt,{open:!0,onOpenChange:Ae=>{Ae||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("账号设置")})}),s.jsx(Lt,{children:s.jsx("p",{className:"detail",children:r("账号不存在,请刷新后重试。")})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")})]})]})});const U=a,Z=k8(U,Al()),ae=An(U)==="catpaw",ce=An(U).startsWith("custom-"),W=RA(R,U.baseUrl)||p.mode==="rotate",ue=Mf(U.balanceQuery?.scheme),ve={};for(const Ae of ue?.fields??[])ve[Ae.key]=v8(U.balanceQuery,Ae);const ee=!!(ue&&ue.fields.length)&&!y8(U.balanceQuery);async function he(){if(!w){k(!0);try{await Pe().workbuddyDesktop?.updateAccount?.(e,{balanceToken:null}),y(""),_e(r("✅ 已清除余额查询凭证")),await Pe().wbApp?.refresh?.()}catch(Ae){_e(r("清除失败:{error}",{error:ut(Ae)}),"err")}finally{k(!1)}}}async function te(){if(!w){k(!0);try{await Pe().workbuddyDesktop?.updateAccount?.(e,{apiKey:null}),B(""),_e(r("✅ 已清除 API Key(该账号现在没有凭证,转发会被跳过)")),await Pe().wbApp?.refresh?.()}catch(Ae){_e(r("清除失败:{error}",{error:ut(Ae)}),"err")}finally{k(!1)}}}async function ke(Ae){if(!w){k(!0);try{await Pe().workbuddyDesktop?.updateAccount?.(e,{balanceQuery:{[Ae]:null}}),q(oe=>({...oe,[Ae]:""})),_e(r("✅ 已清除查询凭证")),await Pe().wbApp?.refresh?.()}catch(oe){_e(r("清除失败:{error}",{error:ut(oe)}),"err")}finally{k(!1)}}}function le(){if(!ce)return null;const Ae=H.trim(),oe={};return Ae?oe.apiKey=Ae:L!==(U.noAuth===!0)&&(oe.noAuth=L),Object.keys(oe).length?oe:null}function de(){if(!R)return null;const Ae=T.trim(),oe=I.trim();if(!Ae)return{error:r("请填写提供商名称")};if(!oe)return{error:r("请填写提供商的 Base URL")};const me=typeof R.clientEmulation=="string"?R.clientEmulation:"";return R.name===Ae&&R.protocol===E&&R.baseUrl===oe&&me===_?null:{id:R.id,name:Ae,protocol:E,baseUrl:oe,clientEmulation:_}}async function Se(){if(w)return;let Ae;try{Ae=Tj(p)}catch(Tt){_e(ut(Tt),"err");return}const oe=de();if(oe&&"error"in oe){N(s.jsx("span",{className:"text-destructive",children:oe.error}));return}const me=Ea(U)?g8(U,$):null;if(me&&"error"in me){N(s.jsx("span",{className:"text-destructive",children:me.error}));return}const pe=d8(U,Q),Ce=w8(U.balanceQuery?.scheme,K),Ne=le()||{},be=Number(re);if(!Number.isFinite(be)||be<0){_e(r("并发上限必须是 0~{max} 的整数",{max:Ol}),"err");return}const De=Math.min(Ol,Math.round(be)),Ge=Number(U.maxConcurrent)||0,Ct=De!==Ge?{maxConcurrent:De}:{};k(!0);try{const Tt=ae&&b.trim()?{balanceToken:b.trim()}:{},Mt=eg(U)&&v!==mj(U)?{zcodePlan:v}:{};if(await Pe().workbuddyDesktop?.updateAccount?.(e,{name:d.trim()||U.name,enabled:o,proxy:Ae,...Tt,...Mt,...Ne,...Ct,...Ce?{balanceQuery:Ce}:{},...me&&"patch"in me?me.patch:{},...pe&&"patch"in pe?pe.patch:{}}),oe)try{await Pe().wbCustomProvidersUi?.update?.(oe)}catch(ot){N(s.jsx("span",{className:"text-destructive",children:r("账号已保存,但提供商未更新:{error}",{error:ut(ot)})})),await Pe().wbApp?.refresh?.(),k(!1);return}t(),_e(r("✅ 账号设置已保存"));try{await Pe().wbApp?.refresh?.()}catch{}}catch(Tt){N(s.jsx("span",{className:"text-destructive",children:ut(Tt)})),_e(r("保存失败:{error}",{error:ut(Tt)}),"err")}finally{k(!1)}}const Te=Number(cr(An(U)).concurrencyDefault)||0,Le=ae||ce||eg(U);return s.jsx(Yt,{open:!0,onOpenChange:Ae=>{Ae||w||t()},children:s.jsxs(Xt,{className:"w-[min(900px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("账号设置 · {name}",{name:dg(a)})})}),s.jsx(Lt,{className:"p-0",children:s.jsxs("div",{className:"acct-dlg",children:[s.jsx("aside",{className:"prov-rail acct-dlg-rail","aria-label":r("账号设置分组"),children:s.jsxs("div",{className:"rail-scroll",children:[s.jsx("div",{className:"rail-label",children:r("账号设置")}),[["basic",r("基本")],...Le?[["credential",r("凭证与套餐")]]:[],...Ea(U)?[["query",r("查询设置")],["limiter",r("限制器")]]:[],["network",r("网络")]].map(([Ae,oe])=>s.jsx(du,{active:J===Ae,title:oe,className:"shadow-none",onClick:()=>Y(Ae),children:oe},Ae))]})}),s.jsxs("div",{className:"acct-dlg-main",children:[J==="basic"?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("基本")}),s.jsx("p",{children:r("这条账号是谁、排第几、能不能接请求。")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("启用")}),s.jsx(Zn,{checked:o,onCheckedChange:c,"aria-label":r("启用该账号")}),s.jsx("span",{className:"detail",children:r("关闭则不参与转发(余额查询照常,见「查询设置」)")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"account-name-input",children:r("备注名")}),s.jsx(Fe,{id:"account-name-input",maxLength:100,placeholder:r("账号显示名称"),className:"max-w-[280px]",value:d,onChange:Ae=>f(Ae.currentTarget.value)})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{children:r("转发顺序")}),s.jsx("span",{className:"detail",children:r("在列表里拖:拖分组带调整整组顺位,拖行首把手调整组内先后(顺序由拖拽表达,不再填数字)")})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"account-conc-input",children:r("并发上限")}),s.jsx(Fe,{id:"account-conc-input",type:"number",min:0,max:Ol,step:1,className:"max-w-[110px]",value:re,onChange:Ae=>M(Ae.currentTarget.value)}),s.jsx("span",{className:"detail",children:Te>0?r("0 = 按本家默认 {default}",{default:Te}):r("0 = 不限")})]}),s.jsx("p",{className:"detail acct-dlg-hint",children:Te>0?r("并发上限 受上游硬顶约束,达到上限的账号跳过、请求转给其他账号(原列表 ⋯ 菜单的「并发上限」入口已并入这里)"):r("并发上限 0~{max};达到上限的账号跳过、请求转给其他账号(原列表 ⋯ 菜单的「并发上限」入口已并入这里)",{max:Ol})})]}):null,J==="credential"&&Le?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("凭证与套餐")}),s.jsx("p",{children:r("这一段按提供商出现:有什么配什么。")})]}),ae?s.jsx(T8,{configured:a.hasBalanceToken===!0,value:b,onChange:y,clearBusy:w,onClear:()=>{he()}}):null,ce?s.jsx(E8,{hasApiKey:U.hasApiKey===!0,noAuth:L,value:H,onValue:B,onToggleNoAuth:F,onClear:()=>{te()},clearBusy:w}):null,eg(U)?s.jsx(C8,{plan:v,hasJwt:a.canClaim===!0,onChange:j}):null,R?s.jsx(A8,{provider:R,count:Z.length+1,name:T,protocol:E,baseUrl:I,emulation:_,onName:C,onProtocol:D,onBaseUrl:O,onEmulation:z,onRemove:()=>{w||Promise.resolve(Pe().wbCustomProvidersUi?.remove?.(R.id)).then(Ae=>{Ae&&t()})}}):null]}):null,J==="query"&&Ea(U)?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("查询设置")}),s.jsx("p",{children:r("余额列读数的自动刷新;也是「限制器」余额规则的数据来源。")})]}),ue?s.jsx(N8,{spec:ue,values:K,configured:ve,onValue:(Ae,oe)=>q(me=>({...me,[Ae]:oe})),onClear:Ae=>{ke(Ae)},clearBusy:w,idPrefix:"account-balance-query"}):null,ee?s.jsx("p",{className:"detail mt-2.5 text-subtle",children:r("查询凭证还没配齐:填好后余额列才有读数,在此之前会显示「未配置」。")}):null,s.jsx(x8,{account:U,draft:$,onChange:X})]}):null,J==="limiter"&&Ea(U)?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("限制器")}),s.jsx("p",{children:r("按规则限制该账号参与转发:没有规则(或全部停用)= 不限制;跳过档自动恢复,禁用档需手动启用。")})]}),s.jsx(u8,{account:U,draft:Q,onChange:G})]}):null,J==="network"?s.jsxs("div",{children:[s.jsxs("div",{className:"acct-dlg-pane-head",children:[s.jsx("h3",{children:r("网络")}),s.jsx("p",{children:r("这条账号访问上游走哪条线路。")})]}),s.jsx(LR,{draft:p,onChange:h,idPrefix:"account-proxy",allowRotate:W}),a.proxy?.error?s.jsx("p",{className:"detail text-destructive",children:r("当前代理不可用:{error}(转发时会回退直连)",{error:a.proxy.error})}):null]}):null]})]})}),s.jsxs(tn,{children:[s.jsx("div",{className:"detail mr-auto",style:{minHeight:18},children:S}),s.jsx(ne,{variant:"outline",disabled:w,onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:w,onClick:()=>{Se()},children:r(w?"保存中…":"保存")})]})]})})}const O8=[{value:"enable",label:r("启用")},{value:"disable",label:r("禁用")},{value:"proxy",label:r("修改代理")},{value:"concurrency",label:r("设置并发上限")},{value:"remove",label:r("删除")}];function M8({ids:e,action:t,onClose:a}){const[o,c]=x.useState(t),[d,f]=x.useState(()=>PR(null)),[p,h]=x.useState(""),[b,y]=x.useState(!1),[v,j]=x.useState(""),w=e.map(T=>Aa(T)).filter(T=>T!==null),k=w.reduce((T,C)=>Math.max(T,Number(cr(An(C)).concurrencyDefault)||0),0),S=w.length>0&&w.every(T=>a$(T));function N(T){return Promise.resolve(Pe().wbConfirm?.ask?.({title:r("删除选中的账号"),html:r("确定删除选中的 {count} 个账号?此操作不可恢复,账号的登录态会一并移除。",{count:T}),okText:r("删除"),okClass:"danger"})??!1)}async function R(){if(b)return;if(!e.length){_e(r("没有选中的账号"),"err");return}let T;if(o==="proxy")try{T=Tj(d)}catch(E){_e(ut(E),"err");return}let C;if(o==="concurrency"){const E=Number(p.trim());if(!p.trim()||!Number.isFinite(E)||E<0){_e(r("并发上限必须是 0~{max} 的整数",{max:Ol}),"err");return}C=Math.min(Ol,Math.round(E))}if(!(o==="remove"&&!await N(e.length))){if(o==="disable"||o==="remove"){const E=new Set(e);if(!Al().filter(I=>I.enabled!==!1&&!E.has(I.id)).length){const I=r(o==="remove"?"删除":"禁用");if(!await Promise.resolve(Pe().wbConfirm?.ask?.({title:r("全部启用中的账号将被{what}",{what:I}),html:r("这会{what}所有启用中的账号,转发将不可用。确定继续?",{what:I}),okText:I,okClass:o==="remove"?"danger":"primary"})??!1))return}}y(!0),j("");try{const E={action:o,ids:e};o==="proxy"&&(E.proxy=T),o==="concurrency"&&(E.maxConcurrent=C);const D=await Pe().workbuddyDesktop?.batchAccounts?.(E),I=(D?.ok||[]).filter(B=>B.changes?.length).length,O=(D?.removed||[]).length,_=D?.failed||[],z=o==="remove"?O:I,H={enable:r("启用"),disable:r("禁用"),proxy:r("修改代理"),concurrency:r("设置并发上限"),remove:r("删除")}[o]||o;if(_.length){const B=_.slice(0,3).map(L=>dg(Aa(String(L.id)))||L.id).join(r("、"));_e(r("{verb}完成:成功 {ok} 个,失败 {fail} 个({detail}{more})",{verb:H,ok:z,fail:_.length,detail:B,more:_.length>3?r(" 等"):""}),"err"),j(s.jsxs("span",{className:"text-destructive",children:[r("失败 {count} 个:",{count:_.length}),_.map(L=>`${dg(Aa(String(L.id)))||L.id}(${L.error})`).join(r(";"))]}))}else _e(r("✅ {verb}完成:共 {count} 个账号",{verb:H,count:z})),a();await Pe().wbApp?.refresh?.()}catch(E){j(s.jsx("span",{className:"text-destructive",children:ut(E)})),_e(r("批量操作失败:{error}",{error:ut(E)}),"err")}finally{y(!1)}}}const P={enable:r("启用"),disable:r("禁用"),proxy:r("修改代理"),concurrency:r("设置并发上限"),remove:r("删除")}[o]||o;return s.jsx(Yt,{open:!0,onOpenChange:T=>{T||b||a()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("批量操作 · 已选 {count} 个账号",{count:e.length})})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("将作用于以下账号")}),s.jsx("p",{style:{maxHeight:84,overflowY:"auto"},children:w.map(T=>dg(T)).join(r("、"))})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("操作")}),s.jsx(_h,{value:o,onValueChange:c,className:"flex-row flex-wrap items-center gap-5","aria-label":r("批量动作"),children:O8.map(T=>s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(jo,{value:T.value}),T.label]},T.value))}),o==="proxy"?s.jsx("div",{className:"mt-2.5",children:s.jsx(LR,{draft:d,onChange:f,idPrefix:"batch-proxy",allowRotate:S})}):null,o==="concurrency"?s.jsxs("div",{className:"mt-2.5",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"batch-conc-input",children:r("并发上限")}),s.jsx(Fe,{id:"batch-conc-input",type:"number",min:0,max:Ol,step:1,className:"max-w-[110px]",placeholder:r("不限"),value:p,onChange:T=>h(T.currentTarget.value)}),s.jsx("span",{className:"detail",children:r("0 = 不限")})]}),s.jsx("p",{className:"detail acct-dlg-hint",children:k>0?r("并发上限 0~{max};有上游硬顶的家(如 CodeArts)以它的硬顶为准;达到上限的账号会被跳过、请求转给其他账号",{max:Ol}):r("并发上限 0~{max};达到上限的账号会被跳过、请求转给其他账号",{max:Ol})})]}):null]}),s.jsx("div",{className:"detail",style:{minHeight:18},children:v})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:b,onClick:a,children:r("取消")}),s.jsx(ne,{variant:o==="remove"?"destructive":"default",disabled:b,onClick:()=>{R()},children:b?r("执行中…"):r("执行({action})",{action:P})})]})]})})}function D8(){const e=Gs();return e.dialog?e.dialog.kind==="settings"?s.jsx(R8,{id:e.dialog.id,onClose:ig},e.dialog.id):s.jsx(M8,{ids:e.dialog.ids,action:e.dialog.action,onClose:ig},e.dialog.ids.join(",")):null}var Ej={exports:{}},Df={},Aj={exports:{}},Rj={};var zR;function I8(){return zR||(zR=1,(function(e){function t(X,K){var q=X.length;X.push(K);e:for(;0>>1,G=X[Q];if(0>>1;Qc(re,q))Mc(U,re)?(X[Q]=U,X[M]=q,Q=M):(X[Q]=re,X[Y]=q,Q=Y);else if(Mc(U,q))X[Q]=U,X[M]=q,Q=M;else break e}}return K}function c(X,K){var q=X.sortIndex-K.sortIndex;return q!==0?q:X.id-K.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var d=performance;e.unstable_now=function(){return d.now()}}else{var f=Date,p=f.now();e.unstable_now=function(){return f.now()-p}}var h=[],b=[],y=1,v=null,j=3,w=!1,k=!1,S=!1,N=!1,R=typeof setTimeout=="function"?setTimeout:null,P=typeof clearTimeout=="function"?clearTimeout:null,T=typeof setImmediate<"u"?setImmediate:null;function C(X){for(var K=a(b);K!==null;){if(K.callback===null)o(b);else if(K.startTime<=X)o(b),K.sortIndex=K.expirationTime,t(h,K);else break;K=a(b)}}function E(X){if(S=!1,C(X),!k)if(a(h)!==null)k=!0,D||(D=!0,B());else{var K=a(b);K!==null&&$(E,K.startTime-X)}}var D=!1,I=-1,O=5,_=-1;function z(){return N?!0:!(e.unstable_now()-_X&&z());){var Q=v.callback;if(typeof Q=="function"){v.callback=null,j=v.priorityLevel;var G=Q(v.expirationTime<=X);if(X=e.unstable_now(),typeof G=="function"){v.callback=G,C(X),K=!0;break t}v===a(h)&&o(h),C(X)}else o(h);v=a(h)}if(v!==null)K=!0;else{var J=a(b);J!==null&&$(E,J.startTime-X),K=!1}}break e}finally{v=null,j=q,w=!1}K=void 0}}finally{K?B():D=!1}}}var B;if(typeof T=="function")B=function(){T(H)};else if(typeof MessageChannel<"u"){var L=new MessageChannel,F=L.port2;L.port1.onmessage=H,B=function(){F.postMessage(null)}}else B=function(){R(H,0)};function $(X,K){I=R(function(){X(e.unstable_now())},K)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(X){X.callback=null},e.unstable_forceFrameRate=function(X){0>X||125Q?(X.sortIndex=q,t(b,X),a(h)===null&&X===a(b)&&(S?(P(I),I=-1):S=!0,$(E,q-Q))):(X.sortIndex=G,t(h,X),k||w||(k=!0,D||(D=!0,B()))),X},e.unstable_shouldYield=z,e.unstable_wrapCallback=function(X){var K=j;return function(){var q=j;j=K;try{return X.apply(this,arguments)}finally{j=q}}}})(Rj)),Rj}var BR;function P8(){return BR||(BR=1,Aj.exports=I8()),Aj.exports}var HR;function _8(){if(HR)return Df;HR=1;var e=P8(),t=Xd(),a=M1();function o(n){var l="https://react.dev/errors/"+n;if(1ke||(n.current=te[ke],te[ke]=null,ke--)}function Se(n,l){ke++,te[ke]=n.current,n.current=l}var Te=le(null),Le=le(null),Ae=le(null),oe=le(null);function me(n,l){switch(Se(Ae,l),Se(Le,n),Se(Te,null),l.nodeType){case 9:case 11:n=(n=l.documentElement)&&(n=n.namespaceURI)?i5(n):0;break;default:if(n=l.tagName,l=l.namespaceURI)l=i5(l),n=c5(l,n);else switch(n){case"svg":n=1;break;case"math":n=2;break;default:n=0}}de(Te),Se(Te,n)}function pe(){de(Te),de(Le),de(Ae)}function Ce(n){var l=n.memoizedState;l!==null&&(qd._currentValue=l.memoizedState,Se(oe,n)),l=Te.current;var i=c5(l,n.type);l!==i&&(Se(Le,n),Se(Te,i))}function Ne(n){Le.current===n&&(de(Te),de(Le)),oe.current===n&&(de(oe),qd._currentValue=he)}var be,De;function Ge(n){if(be===void 0)try{throw Error()}catch(i){var l=i.stack.trim().match(/\n( *(at )?)/);be=l&&l[1]||"",De=-1)":-1m||se[u]!==xe[m]){var we=` `+se[u].replace(" at new "," at ");return n.displayName&&we.includes("")&&(we=we.replace("",n.displayName)),we}while(1<=u&&0<=m);break}}}finally{Ct=!1,Error.prepareStackTrace=i}return(i=n?n.displayName||n.name:"")?Ge(i):""}function Mt(n,l){switch(n.tag){case 26:case 27:case 5:return Ge(n.type);case 16:return Ge("Lazy");case 13:return n.child!==l&&l!==null?Ge("Suspense Fallback"):Ge("Suspense");case 19:return Ge("SuspenseList");case 0:case 15:return Tt(n.type,!1);case 11:return Tt(n.type.render,!1);case 1:return Tt(n.type,!0);case 31:return Ge("Activity");case 30:return Ge("ViewTransition");default:return""}}function ot(n){try{var l="",i=null;do l+=Mt(n,i),i=n,n=n.return;while(n);return l}catch(u){return` Error generating stack: `+u.message+` -`+u.stack}}var Kn=Object.prototype.hasOwnProperty,ms=e.unstable_scheduleCallback,Yn=e.unstable_cancelCallback,vs=e.unstable_shouldYield,it=e.unstable_requestPaint,$t=e.unstable_now,Vn=e.unstable_getCurrentPriorityLevel,rn=e.unstable_ImmediatePriority,nt=e.unstable_UserBlockingPriority,Dt=e.unstable_NormalPriority,qt=e.unstable_LowPriority,es=e.unstable_IdlePriority,Fn=e.log,$n=e.unstable_setDisableYieldValue,Dn=null,en=null;function cs(n){if(typeof Fn=="function"&&$n(n),en&&typeof en.setStrictMode=="function")try{en.setStrictMode(Dn,n)}catch{}}var Et=Math.clz32?Math.clz32:wt,xt=Math.log,jt=Math.LN2;function wt(n){return n>>>=0,n===0?32:31-(xt(n)/jt|0)|0}var Tr=256,ar=262144,Fr=4194304;function Nn(n){var l=n&42;if(l!==0)return l;switch(n&-n){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return n&-n;case 262144:case 524288:case 1048576:case 2097152:return n&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return n&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return n}}function al(n,l,i){var u=n.pendingLanes;if(u===0)return 0;var m=0,g=n.suspendedLanes,T=n.pingedLanes;n=n.warmLanes;var V=u&134217727;return V!==0?(u=V&~g,u!==0?m=Nn(u):(T&=V,T!==0?m=Nn(T):i||(i=V&~n,i!==0&&(m=Nn(i))))):(V=u&~g,V!==0?m=Nn(V):T!==0?m=Nn(T):i||(i=u&~n,i!==0&&(m=Nn(i)))),m===0?0:l!==0&&l!==m&&(l&g)===0&&(g=m&-m,i=l&-l,g>=i||g===32&&(i&4194048)!==0)?l:m}function ln(n,l){return(n.pendingLanes&~(n.suspendedLanes&~n.pingedLanes)&l)===0}function hc(n,l){(l&8)!==0&&(l|=l&32);var i=n.entangledLanes;if(i!==0)for(n=n.entanglements,i&=l;0i;i++)l.push(n);return l}function Go(n,l){n.pendingLanes|=l,l!==268435456&&(n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0)}function Ko(n,l,i,u,m,g){var T=n.pendingLanes;n.pendingLanes=i,n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0,n.expiredLanes&=i,n.entangledLanes&=i,n.errorRecoveryDisabledLanes&=i,n.shellSuspendCounter=0;var V=n.entanglements,se=n.expirationTimes,xe=n.hiddenUpdates;for(i=T&~i;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Qt=!1;if(lt)try{var In={};Object.defineProperty(In,"passive",{get:function(){Qt=!0}}),window.addEventListener("test",In,In),window.removeEventListener("test",In,In)}catch{Qt=!1}var gn=null,Pn=null,hs=null;function Er(){if(hs)return hs;var n,l=Pn,i=l.length,u,m="value"in gn?gn.value:gn.textContent,g=m.length;for(n=0;n=tm),i_=" ",c_=!1;function u_(n,l){switch(n){case"keyup":return sne.indexOf(l.keyCode)!==-1;case"keydown":return l.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function d_(n){return n=n.detail,typeof n=="object"&&"data"in n?n.data:null}var pd=!1;function ane(n,l){switch(n){case"compositionend":return d_(l);case"keypress":return l.which!==32?null:(c_=!0,i_);case"textInput":return n=l.data,n===i_&&c_?null:n;default:return null}}function lne(n,l){if(pd)return n==="compositionend"||!aN&&u_(n,l)?(n=Er(),hs=Pn=gn=null,pd=!1,n):null;switch(n){case"paste":return null;case"keypress":if(!(l.ctrlKey||l.altKey||l.metaKey)||l.ctrlKey&&l.altKey){if(l.char&&1"u")return null;try{return n.activeElement||n.body}catch{return n.body}}function v_(n){for(;n&&n.firstChild;)n=n.firstChild;return n}function y_(n,l){var i=v_(n);n=0;for(var u;i;){if(i.nodeType===3){if(u=n+i.textContent.length,n<=l&&u>=l)return{node:i,offset:l-n};n=u}e:{for(;i;){if(i.nextSibling){i=i.nextSibling;break e}i=i.parentNode}i=void 0}i=v_(i)}}function j_(n,l){return n&&l?n===l?!0:n&&n.nodeType===3?!1:l&&l.nodeType===3?j_(n,l.parentNode):"contains"in n?n.contains(l):n.compareDocumentPosition?!!(n.compareDocumentPosition(l)&16):!1:!1}function w_(n){n=n!=null&&n.ownerDocument!=null&&n.ownerDocument.defaultView!=null?n.ownerDocument.defaultView:window;for(var l=iN(n.document);l instanceof n.HTMLIFrameElement;){try{var i=typeof l.contentWindow.location.href=="string"}catch{i=!1}if(i)n=l.contentWindow;else break;l=iN(n.document)}return l}function cN(n){var l=n&&n.nodeName&&n.nodeName.toLowerCase();return l&&(l==="input"&&(n.type==="text"||n.type==="search"||n.type==="tel"||n.type==="url"||n.type==="password")||l==="textarea"||n.contentEditable==="true")}var mne=lt&&"documentMode"in document&&11>=document.documentMode,md=null,uN=null,am=null,dN=!1;function S_(n,l,i){var u=i.window===i?i.document:i.nodeType===9?i:i.ownerDocument;dN||md==null||md!==iN(u)||(u=md,"selectionStart"in u&&cN(u)?u={start:u.selectionStart,end:u.selectionEnd}:(u=(u.ownerDocument&&u.ownerDocument.defaultView||window).getSelection(),u={anchorNode:u.anchorNode,anchorOffset:u.anchorOffset,focusNode:u.focusNode,focusOffset:u.focusOffset}),am&&rm(am,u)||(am=u,u=mv(uN,"onSelect"),0>=T,m-=T,ol=1<<32-Et(l)+m|i<rt?(Ns=st,st=null):Ns=st.sibling;var Zt=fe(ge,st,ye[rt],Ee);if(Zt===null){st===null&&(st=Ns);break}n&&st&&Zt.alternate===null&&l(ge,st),ie=g(Zt,ie,rt),Ht===null?Ke=Zt:Ht.sibling=Zt,Ht=Zt,st=Ns}if(rt===ye.length)return i(ge,st),At&&Yl(ge,rt),Ke;if(st===null){for(;rtrt?(Ns=st,st=null):Ns=st.sibling;var wi=fe(ge,st,Zt.value,Ee);if(wi===null){st===null&&(st=Ns);break}n&&st&&wi.alternate===null&&l(ge,st),ie=g(wi,ie,rt),Ht===null?Ke=wi:Ht.sibling=wi,Ht=wi,st=Ns}if(Zt.done)return i(ge,st),At&&Yl(ge,rt),Ke;if(st===null){for(;!Zt.done;rt++,Zt=ye.next())Zt=Re(ge,Zt.value,Ee),Zt!==null&&(ie=g(Zt,ie,rt),Ht===null?Ke=Zt:Ht.sibling=Zt,Ht=Zt);return At&&Yl(ge,rt),Ke}for(st=u(st);!Zt.done;rt++,Zt=ye.next())Zt=je(st,ge,rt,Zt.value,Ee),Zt!==null&&(n&&(Ns=Zt.alternate,Ns!==null&&st.delete(Ns.key===null?rt:Ns.key)),ie=g(Zt,ie,rt),Ht===null?Ke=Zt:Ht.sibling=Zt,Ht=Zt);return n&&st.forEach(function(are){return l(ge,are)}),At&&Yl(ge,rt),Ke}function vt(ge,ie,ye,Ee){if(typeof ye=="object"&&ye!==null&&ye.type===H&&ye.key===null&&ye.props.ref===void 0&&(ye=ye.props.children),typeof ye=="object"&&ye!==null){switch(ye.$$typeof){case _:e:{for(var Ke=ye.key;ie!==null;){if(ie.key===Ke){if(Ke=ye.type,Ke===H){if(ie.tag===7){i(ge,ie.sibling),Ee=m(ie,ye.props.children),si(Ee,ye),Ee.return=ge,ge=Ee;break e}}else if(ie.elementType===Ke||typeof Ke=="object"&&Ke!==null&&Ke.$$typeof===G&&_c(Ke)===ie.type){i(ge,ie.sibling),Ee=m(ie,ye.props),si(Ee,ye),Ee.return=ge,ge=Ee;break e}i(ge,ie);break}else l(ge,ie);ie=ie.sibling}ye.type===H?(Ee=Ac(ye.props.children,ge.mode,Ee,ye.key),si(Ee,ye),Ee.return=ge,ge=Ee):(Ee=vb(ye.type,ye.key,ye.props,null,ge.mode,Ee),si(Ee,ye),Ee.return=ge,ge=Ee)}return T(ge);case z:e:{for(Ke=ye.key;ie!==null;){if(ie.key===Ke)if(ie.tag===4&&ie.stateNode.containerInfo===ye.containerInfo&&ie.stateNode.implementation===ye.implementation){i(ge,ie.sibling),Ee=m(ie,ye.children||[]),Ee.return=ge,ge=Ee;break e}else{i(ge,ie);break}else l(ge,ie);ie=ie.sibling}Ee=bN(ye,ge.mode,Ee),Ee.return=ge,ge=Ee}return T(ge);case G:return ye=_c(ye),vt(ge,ie,ye,Ee)}if(ue(ye))return He(ge,ie,ye,Ee);if(ae(ye)){if(Ke=ae(ye),typeof Ke!="function")throw Error(o(150));return ye=Ke.call(ye),We(ge,ie,ye,Ee)}if(typeof ye.then=="function")return vt(ge,ie,Ab(ye),Ee);if(ye.$$typeof===$)return vt(ge,ie,kb(ge,ye),Ee);Rb(ge,ye)}return typeof ye=="string"&&ye!==""||typeof ye=="number"||typeof ye=="bigint"?(ye=""+ye,ie!==null&&ie.tag===6?(i(ge,ie.sibling),Ee=m(ie,ye),Ee.return=ge,ge=Ee):(i(ge,ie),Ee=xN(ye,ge.mode,Ee),Ee.return=ge,ge=Ee),T(ge)):i(ge,ie)}return function(ge,ie,ye,Ee){try{dm=0;var Ke=vt(ge,ie,ye,Ee);return Sd=null,Ke}catch(st){if(st===wd||st===Tb)throw st;var Ht=Ar(29,st,null,ge.mode);return Ht.lanes=Ee,Ht.return=ge,Ht}}}var zc=K_(!0),Y_=K_(!1),ri=!1;function EN(n){n.updateQueue={baseState:n.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function AN(n,l){n=n.updateQueue,l.updateQueue===n&&(l.updateQueue={baseState:n.baseState,firstBaseUpdate:n.firstBaseUpdate,lastBaseUpdate:n.lastBaseUpdate,shared:n.shared,callbacks:null})}function ai(n){return{lane:n,tag:0,payload:null,callback:null,next:null}}function li(n,l,i){var u=n.updateQueue;if(u===null)return null;if(u=u.shared,(on&2)!==0){var m=u.pending;return m===null?l.next=l:(l.next=m.next,m.next=l),u.pending=l,l=bb(n),O_(n,null,i),l}return xb(n,u,l,i),bb(n)}function fm(n,l,i){if(l=l.updateQueue,l!==null&&(l=l.shared,(i&4194048)!==0)){var u=l.lanes;u&=n.pendingLanes,i|=u,l.lanes=i,gc(n,i)}}function RN(n,l){var i=n.updateQueue,u=n.alternate;if(u!==null&&(u=u.updateQueue,i===u)){var m=null,g=null;if(i=i.firstBaseUpdate,i!==null){do{var T={lane:i.lane,tag:i.tag,payload:i.payload,callback:null,next:null};g===null?m=g=T:g=g.next=T,i=i.next}while(i!==null);g===null?m=g=l:g=g.next=l}else m=g=l;i={baseState:u.baseState,firstBaseUpdate:m,lastBaseUpdate:g,shared:u.shared,callbacks:u.callbacks},n.updateQueue=i;return}n=i.lastBaseUpdate,n===null?i.firstBaseUpdate=l:n.next=l,i.lastBaseUpdate=l}var ON=!1;function pm(){if(ON){var n=jd;if(n!==null)throw n}}function mm(n,l,i,u){ON=!1;var m=n.updateQueue;ri=!1;var g=m.firstBaseUpdate,T=m.lastBaseUpdate,V=m.shared.pending;if(V!==null){m.shared.pending=null;var se=V,xe=se.next;se.next=null,T===null?g=xe:T.next=xe,T=se;var we=n.alternate;we!==null&&(we=we.updateQueue,V=we.lastBaseUpdate,V!==T&&(V===null?we.firstBaseUpdate=xe:V.next=xe,we.lastBaseUpdate=se))}if(g!==null){var Re=m.baseState;T=0,we=xe=se=null,V=g;do{var fe=V.lane&-536870913,je=fe!==V.lane;if(je?(Bt&fe)===fe:(u&fe)===fe){fe!==0&&fe===Ic&&(ON=!0),we!==null&&(we=we.next={lane:0,tag:V.tag,payload:V.payload,callback:null,next:null});e:{var He=n,We=V;fe=l;var vt=i;switch(We.tag){case 1:if(He=We.payload,typeof He=="function"){Re=He.call(vt,Re,fe);break e}Re=He;break e;case 3:He.flags=He.flags&-65537|128;case 0:if(He=We.payload,fe=typeof He=="function"?He.call(vt,Re,fe):He,fe==null)break e;Re=I({},Re,fe);break e;case 2:ri=!0}}fe=V.callback,fe!==null&&(n.flags|=64,je&&(n.flags|=8192),je=m.callbacks,je===null?m.callbacks=[fe]:je.push(fe))}else je={lane:fe,tag:V.tag,payload:V.payload,callback:V.callback,next:null},we===null?(xe=we=je,se=Re):we=we.next=je,T|=fe;if(V=V.next,V===null){if(V=m.shared.pending,V===null)break;je=V,V=je.next,je.next=null,m.lastBaseUpdate=je,m.shared.pending=null}}while(!0);we===null&&(se=Re),m.baseState=se,m.firstBaseUpdate=xe,m.lastBaseUpdate=we,g===null&&(m.shared.lanes=0),pi|=T,n.lanes=T,n.memoizedState=Re}}function X_(n,l){if(typeof n!="function")throw Error(o(191,n));n.call(l)}function Q_(n,l){var i=n.callbacks;if(i!==null)for(n.callbacks=null,n=0;ng?g:8;var T=ve.T,V={};V.types=T!==null?T.types:null,ve.T=V,ZN(n,!1,l,i);try{var se=m(),xe=ve.S;if(xe!==null&&xe(V,se),se!==null&&typeof se=="object"&&typeof se.then=="function"){var we=kne(se,u);bm(n,l,we,Jr(n))}else bm(n,l,u,Jr(n))}catch(Re){bm(n,l,{then:function(){},status:"rejected",reason:Re},Jr())}finally{ee.p=g,T!==null&&V.types!==null&&(T.types=V.types),ve.T=T}}function One(){}function XN(n,l,i,u){if(n.tag!==5)throw Error(o(476));var m=EL(n).queue;TL(n,m,l,he,i===null?One:function(){return AL(n),i(u)})}function EL(n){var l=n.memoizedState;if(l!==null)return l;l={memoizedState:he,baseState:he,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Wl,lastRenderedState:he},next:null};var i={};return l.next={memoizedState:i,baseState:i,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Wl,lastRenderedState:i},next:null},n.memoizedState=l,n=n.alternate,n!==null&&(n.memoizedState=l),l}function AL(n){var l=EL(n);l.next===null&&(l=n.alternate.memoizedState),bm(n,l.next.queue,{},Jr())}function QN(){return Xs(qd)}function RL(){return gs().memoizedState}function OL(){return gs().memoizedState}function Mne(n){for(var l=n.return;l!==null;){switch(l.tag){case 24:case 3:var i=Jr();n=ai(i);var u=li(l,n,i);u!==null&&(Dr(u,l,i),fm(u,l,i)),l={cache:NN()},n.payload=l;return}l=l.return}}function Dne(n,l,i){var u=Jr();i={lane:u,revertLane:0,gesture:null,action:i,hasEagerState:!1,eagerState:null,next:null},Hb(n)?DL(l,i):(i=hN(n,l,i,u),i!==null&&(Dr(i,n,u),IL(i,l,u)))}function ML(n,l,i){var u=Jr();bm(n,l,i,u)}function bm(n,l,i,u){var m={lane:u,revertLane:0,gesture:null,action:i,hasEagerState:!1,eagerState:null,next:null};if(Hb(n))DL(l,m);else{var g=n.alternate;if(n.lanes===0&&(g===null||g.lanes===0)&&(g=l.lastRenderedReducer,g!==null))try{var T=l.lastRenderedState,V=g(T,i);if(m.hasEagerState=!0,m.eagerState=V,Yr(V,T))return xb(n,l,m,0),_n===null&&gb(),!1}catch{}if(i=hN(n,l,m,u),i!==null)return Dr(i,n,u),IL(i,l,u),!0}return!1}function ZN(n,l,i,u){if(u={lane:2,revertLane:Uk(),gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null},Hb(n)){if(l)throw Error(o(479))}else l=hN(n,i,u,2),l!==null&&Dr(l,n,2)}function Hb(n){var l=n.alternate;return n===bt||l!==null&&l===bt}function DL(n,l){Nd=Db=!0;var i=n.pending;i===null?l.next=l:(l.next=i.next,i.next=l),n.pending=l}function IL(n,l,i){if((i&4194048)!==0){var u=l.lanes;u&=n.pendingLanes,i|=u,l.lanes=i,gc(n,i)}}var Ub={readContext:Xs,use:_b,useCallback:us,useContext:us,useEffect:us,useImperativeHandle:us,useLayoutEffect:us,useInsertionEffect:us,useMemo:us,useReducer:us,useRef:us,useState:us,useDebugValue:us,useDeferredValue:us,useTransition:us,useSyncExternalStore:us,useId:us,useHostTransitionStatus:us,useFormState:us,useActionState:us,useOptimistic:us,useMemoCache:us,useCacheRefresh:us,useEffectEvent:us},PL={readContext:Xs,use:_b,useCallback:function(n,l){return xr().memoizedState=[n,l===void 0?null:l],n},useContext:Xs,useEffect:bL,useImperativeHandle:function(n,l,i){i=i!=null?i.concat([n]):null,zb(4194308,4,wL.bind(null,l,n),i)},useLayoutEffect:function(n,l){return zb(4194308,4,n,l)},useInsertionEffect:function(n,l){zb(4,2,n,l)},useMemo:function(n,l){var i=xr();l=l===void 0?null:l;var u=n();if(Bc){cs(!0);try{n()}finally{cs(!1)}}return i.memoizedState=[u,l],u},useReducer:function(n,l,i){var u=xr();if(i!==void 0){var m=i(l);if(Bc){cs(!0);try{i(l)}finally{cs(!1)}}}else m=l;return u.memoizedState=u.baseState=m,n={pending:null,lanes:0,dispatch:null,lastRenderedReducer:n,lastRenderedState:m},u.queue=n,n=n.dispatch=Dne.bind(null,bt,n),[u.memoizedState,n]},useRef:function(n){var l=xr();return n={current:n},l.memoizedState=n},useState:function(n){n=$N(n);var l=n.queue,i=ML.bind(null,bt,l);return l.dispatch=i,[n.memoizedState,i]},useDebugValue:KN,useDeferredValue:function(n,l){var i=xr();return YN(i,n,l)},useTransition:function(){var n=$N(!1);return n=TL.bind(null,bt,n.queue,!0,!1),xr().memoizedState=n,[!1,n]},useSyncExternalStore:function(n,l,i){var u=bt,m=xr();if(At){if(i===void 0)throw Error(o(407));i=i()}else{if(i=l(),_n===null)throw Error(o(349));(Bt&127)!==0||nL(u,l,i)}m.memoizedState=i;var g={value:i,getSnapshot:l};return m.queue=g,bL(rL.bind(null,u,g,n),[n]),u.flags|=2048,Cd(9,{destroy:void 0},sL.bind(null,u,g,i,l),null),i},useId:function(){var n=xr(),l=_n.identifierPrefix;if(At){var i=il,u=ol;i=(u&~(1<<32-Et(u)-1)).toString(32)+i,l="_"+l+"R_"+i,i=Ib++,0<\/script>",g=g.removeChild(g.firstChild);break;case"select":g=typeof u.is=="string"?T.createElement("select",{is:u.is}):T.createElement("select"),u.multiple?g.multiple=!0:u.size&&(g.size=u.size);break;default:g=typeof u.is=="string"?T.createElement(m,{is:u.is}):T.createElement(m)}}g[Ms]=l,g[Ys]=u;e:for(T=l.child;T!==null;){if(T.tag===5||T.tag===6)g.appendChild(T.stateNode);else if(T.tag!==4&&T.tag!==27&&T.child!==null){T.child.return=T,T=T.child;continue}if(T===l)break e;for(;T.sibling===null;){if(T.return===null||T.return===l)break e;T=T.return}T.sibling.return=T.return,T=T.sibling}l.stateNode=g;e:switch(Js(g,m,u),m){case"button":case"input":case"select":case"textarea":u=!!u.autoFocus;break e;case"img":u=!0;break e;default:u=!1}u&&eo(l)}}return Hn(l),l.subtreeFlags&=-33554433,uk(l,l.type,n===null?null:n.memoizedProps,l.pendingProps,i),null;case 6:if(n&&l.stateNode!=null)n.memoizedProps!==u&&eo(l);else{if(typeof u!="string"&&l.stateNode===null)throw Error(o(166));if(n=Ae.current,yd(l)){if(n=l.stateNode,i=l.memoizedProps,u=null,m=Hs,m!==null)switch(m.tag){case 27:case 5:u=m.memoizedProps}n[Ms]=l,n=!!(n.nodeValue===i||u!==null&&u.suppressHydrationWarning===!0||r5(n.nodeValue,i)),n||ti(l,!0)}else n=Om(n).createTextNode(u),n[Ms]=l,l.stateNode=n}return Hn(l),null;case 31:if(i=l.memoizedState,n===null||n.memoizedState!==null){if(u=yd(l),i!==null){if(n===null){if(!u)throw Error(o(318));if(n=l.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(o(557));n[Ms]=l}else Rc(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Hn(l),n=!1}else i=jN(),n!==null&&n.memoizedState!==null&&(n.memoizedState.hydrationErrors=i),n=!0;if(!n)return l.flags&256?(Xr(l),l):(Xr(l),null);if((l.flags&128)!==0)throw Error(o(558))}return Hn(l),null;case 13:if(u=l.memoizedState,n===null||n.memoizedState!==null&&n.memoizedState.dehydrated!==null){if(m=yd(l),u!==null&&u.dehydrated!==null){if(n===null){if(!m)throw Error(o(318));if(m=l.memoizedState,m=m!==null?m.dehydrated:null,!m)throw Error(o(317));m[Ms]=l}else Rc(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Hn(l),m=!1}else m=jN(),n!==null&&n.memoizedState!==null&&(n.memoizedState.hydrationErrors=m),m=!0;if(!m)return l.flags&256?(Xr(l),l):(Xr(l),null)}return Xr(l),(l.flags&128)!==0?(l.lanes=i,l):(i=u!==null,n=n!==null&&n.memoizedState!==null,i&&(u=l.child,m=null,u.alternate!==null&&u.alternate.memoizedState!==null&&u.alternate.memoizedState.cachePool!==null&&(m=u.alternate.memoizedState.cachePool.pool),g=null,u.memoizedState!==null&&u.memoizedState.cachePool!==null&&(g=u.memoizedState.cachePool.pool),g!==m&&(u.flags|=2048)),i!==n&&i&&(l.child.flags|=8192),Kb(l,l.updateQueue),Hn(l),null);case 4:return pe(),n===null&&qk(l.stateNode.containerInfo),l.flags|=67108864,Hn(l),null;case 10:return Ql(l.type),Hn(l),null;case 19:if(PN(l),u=l.memoizedState,u===null)return Hn(l),null;if(m=(l.flags&128)!==0,g=u.rendering,g===null)if(m)ym(u,!1);else{if(ds!==0||n!==null&&(n.flags&128)!==0)for(n=l.child;n!==null;){if(g=Mb(n),g!==null){for(l.flags|=128,ym(u,!1),n=g.updateQueue,l.updateQueue=n,Kb(l,n),l.subtreeFlags=0,n=i,i=l.child;i!==null;)M_(i,n),i=i.sibling;return hm(l,Zs.current&1|2),At&&Yl(l,u.treeForkCount),l.child}n=n.sibling}u.tail!==null&&$t()>av&&(l.flags|=128,m=!0,ym(u,!1),l.lanes=4194304)}else{if(!m)if(n=Mb(g),n!==null){if(l.flags|=128,m=!0,n=n.updateQueue,l.updateQueue=n,Kb(l,n),ym(u,!0),u.tail===null&&u.tailMode!=="collapsed"&&u.tailMode!=="visible"&&!g.alternate&&!At)return Hn(l),null}else 2*$t()-u.renderingStartTime>av&&i!==536870912&&(l.flags|=128,m=!0,ym(u,!1),l.lanes=4194304);u.isBackwards?(g.sibling=l.child,l.child=g):(n=u.last,n!==null?n.sibling=g:l.child=g,u.last=g)}if(u.tail!==null){n=u.tail;e:{for(i=n;i!==null;){if(i.alternate!==null){i=!1;break e}i=i.sibling}i=!0}return u.rendering=n,u.tail=n.sibling,u.renderingStartTime=$t(),n.sibling=null,g=Zs.current,g=m?g&1|2:g&1,u.tailMode==="visible"||u.tailMode==="collapsed"||!i||At?hm(l,g):(i=g,Se(Qs,l),Se(Zs,i),or===null&&(or=l)),At&&Yl(l,u.treeForkCount),n}return Hn(l),null;case 22:case 23:return Xr(l),DN(),u=l.memoizedState!==null,n!==null?n.memoizedState!==null!==u&&(l.flags|=8192):u&&(l.flags|=8192),u?(i&536870912)!==0&&(l.flags&128)===0&&(Hn(l),l.subtreeFlags&6&&(l.flags|=8192)):Hn(l),i=l.updateQueue,i!==null&&Kb(l,i.retryQueue),i=null,n!==null&&n.memoizedState!==null&&n.memoizedState.cachePool!==null&&(i=n.memoizedState.cachePool.pool),u=null,l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(u=l.memoizedState.cachePool.pool),u!==i&&(l.flags|=2048),n!==null&&de(Pc),null;case 24:return i=null,n!==null&&(i=n.memoizedState.cache),l.memoizedState.cache!==i&&(l.flags|=2048),Ql(js),Hn(l),null;case 25:return null;case 30:return l.flags|=33554432,Hn(l),null}throw Error(o(156,l.tag))}function Hne(n,l){switch(vN(l),l.tag){case 1:return n=l.flags,n&65536?(l.flags=n&-65537|128,l):null;case 3:return Ql(js),pe(),n=l.flags,(n&65536)!==0&&(n&128)===0?(l.flags=n&-65537|128,l):null;case 26:case 27:case 5:return Ne(l),null;case 31:if(l.memoizedState!==null){if(Xr(l),l.alternate===null)throw Error(o(340));Rc()}return n=l.flags,n&65536?(l.flags=n&-65537|128,l):null;case 13:if(Xr(l),n=l.memoizedState,n!==null&&n.dehydrated!==null){if(l.alternate===null)throw Error(o(340));Rc()}return n=l.flags,n&65536?(l.flags=n&-65537|128,l):null;case 19:return PN(l),n=l.flags,n&65536?(l.flags=n&-65537|128,n=l.memoizedState,n!==null&&(n.rendering=null,n.tail=null),l.flags|=4,l):null;case 4:return pe(),null;case 10:return Ql(l.type),null;case 22:case 23:return Xr(l),DN(),n!==null&&de(Pc),n=l.flags,n&65536?(l.flags=n&-65537|128,l):null;case 24:return Ql(js),null;case 25:return null;default:return null}}function l3(n,l){switch(vN(l),l.tag){case 3:Ql(js),pe();break;case 26:case 27:case 5:Ne(l);break;case 4:pe();break;case 31:l.memoizedState!==null&&Xr(l);break;case 13:Xr(l);break;case 19:PN(l);break;case 10:Ql(l.type);break;case 22:case 23:Xr(l),DN(),n!==null&&de(Pc);break;case 24:Ql(js)}}function jm(n,l){try{var i=l.updateQueue,u=i!==null?i.lastEffect:null;if(u!==null){var m=u.next;i=m;do{if((i.tag&n)===n){u=void 0;var g=i.create,T=i.inst;u=g(),T.destroy=u}i=i.next}while(i!==m)}}catch(V){bn(l,l.return,V)}}function ui(n,l,i){try{var u=l.updateQueue,m=u!==null?u.lastEffect:null;if(m!==null){var g=m.next;u=g;do{if((u.tag&n)===n){var T=u.inst,V=T.destroy;if(V!==void 0){T.destroy=void 0,m=l;var se=i,xe=V;try{xe()}catch(we){bn(m,se,we)}}}u=u.next}while(u!==g)}}catch(we){bn(l,l.return,we)}}function o3(n){var l=n.updateQueue;if(l!==null){var i=n.stateNode;try{Q_(l,i)}catch(u){bn(n,n.return,u)}}}function i3(n,l,i){i.props=Hc(n.type,n.memoizedProps),i.state=n.memoizedState;try{i.componentWillUnmount()}catch(u){bn(n,l,u)}}function cl(n,l){try{var i=n.ref;if(i!==null){switch(n.tag){case 26:case 27:case 5:var u=n.stateNode;break;case 30:var m=n.stateNode,g=ql(n.memoizedProps,m);(m.ref===null||m.ref.name!==g)&&(m.ref=h5(g)),u=m.ref;break;case 7:if(n.stateNode===null){var T=new ea(n);v(n.child,!1,Rse,T,void 0,void 0),n.stateNode=T}u=n.stateNode;break;default:u=n.stateNode}typeof i=="function"?n.refCleanup=i(u):i.current=u}}catch(V){bn(n,l,V)}}function Ws(n,l){var i=n.ref,u=n.refCleanup;if(i!==null)if(typeof u=="function")try{u()}catch(m){bn(n,l,m)}finally{n.refCleanup=null,n=n.alternate,n!=null&&(n.refCleanup=null)}else if(typeof i=="function")try{i(null)}catch(m){bn(n,l,m)}else i.current=null}function Yb(n,l){if((n.tag===5||n.tag===27||n.tag===6)&&n.alternate===null&&l!==null)for(var i=0;i title"))),Js(u,l,i),u[Ms]=n,ys(u),l=u;break e;case"link":if(g=M5("link","href",m).get(l+(i.href||""))){for(T=0;Tvt&&(T=vt,vt=We,We=T);var ge=y_(V,We),ie=y_(V,vt);if(ge&&ie&&(je.rangeCount!==1||je.anchorNode!==ge.node||je.anchorOffset!==ge.offset||je.focusNode!==ie.node||je.focusOffset!==ie.offset)){var ye=Re.createRange();ye.setStart(ge.node,ge.offset),je.removeAllRanges(),We>vt?(je.addRange(ye),je.extend(ie.node,ie.offset)):(ye.setEnd(ie.node,ie.offset),je.addRange(ye))}}}}for(Re=[],je=V;je=je.parentNode;)je.nodeType===1&&Re.push({element:je,left:je.scrollLeft,top:je.scrollTop});for(typeof V.focus=="function"&&V.focus(),V=0;Vi?32:i,ve.T=null,i=Ok,Ok=null;var g=Fa,T=hl;if(ts=0,$c=Fa=null,hl=0,(on&6)!==0)throw Error(o(331));var V=on;if(on|=4,O3(g.current),E3(g,g.current,T,i),on=V,Em(0,!1),en&&typeof en.onPostCommitFiberRoot=="function")try{en.onPostCommitFiberRoot(Dn,g)}catch{}return!0}finally{ee.p=m,ve.T=u,G3(n,l)}}function K3(n,l,i){l=xa(i,l),l=ek(n.stateNode,l,2),n=li(n,l,2),n!==null&&(Go(n,2),gl(n))}function bn(n,l,i){if(n.tag===3)K3(n,n,i);else for(;l!==null;){if(l.tag===3){K3(l,n,i);break}else if(l.tag===1){var u=l.stateNode;if(typeof l.type.getDerivedStateFromError=="function"||typeof u.componentDidCatch=="function"&&(mi===null||!mi.has(u))){n=xa(i,n),i=FL(2),u=li(l,i,2),u!==null&&($L(i,u,l,n),Go(u,2),gl(u));break}}l=l.return}}function zk(n,l,i){var u=n.pingCache;if(u===null){u=n.pingCache=new $ne;var m=new Set;u.set(l,m)}else m=u.get(l),m===void 0&&(m=new Set,u.set(l,m));m.has(i)||(Ek=!0,m.add(i),n=Wne.bind(null,n,l,i),l.then(n,n))}function Wne(n,l,i){var u=n.pingCache;u!==null&&u.delete(l),n.pingedLanes|=n.suspendedLanes&i,n.warmLanes&=~i,_n===n&&(Bt&i)===i&&((ds===4||ds===3&&(Bt&62914560)===Bt&&300>$t()-rv)&&(on&2)===0?Ld(n,0):sv|=i,Md===Bt&&(Md=0)),gl(n)}function Y3(n,l){l===0&&(l=mr()),n=Ec(n,l),n!==null&&(Go(n,l),gl(n))}function Jne(n){var l=n.memoizedState,i=0;l!==null&&(i=l.retryLane),Y3(n,i)}function ese(n,l){var i=0;switch(n.tag){case 31:case 13:var u=n.stateNode,m=n.memoizedState;m!==null&&(i=m.retryLane);break;case 19:u=n.stateNode;break;case 22:u=n.stateNode._retryCache;break;default:throw Error(o(314))}u!==null&&u.delete(l),Y3(n,i)}function tse(n,l){return ms(n,l)}var Bd=null,Hd=null,Bk=!1,fv=!1,Hk=!1,gi=0;function gl(n){n!==Hd&&n.next===null&&(Hd===null?Bd=Hd=n:Hd=Hd.next=n),fv=!0,Bk||(Bk=!0,sse())}function Em(n,l){if(!Hk&&fv){Hk=!0;do for(var i=!1,u=Bd;u!==null;){if(n!==0){var m=u.pendingLanes;if(m===0)var g=0;else{var T=u.suspendedLanes,V=u.pingedLanes;g=(1<<31-Et(42|n)+1)-1,g&=m&~(T&~V),g=g&201326741?g&201326741|1:g?g|2:0}g!==0&&(i=!0,W3(u,g))}else g=Bt,g=al(u,u===_n?g:0,u.cancelPendingCommit!==null||u.timeoutHandle!==-1),(g&3)===0||ln(u,g)||(i=!0,W3(u,g));u=u.next}while(i);Hk=!1}}function nse(){X3()}function X3(){fv=Bk=!1;var n=0;gi!==0&&mse()&&(n=gi);for(var l=$t(),i=null,u=Bd;u!==null;){var m=u.next,g=Q3(u,l);g===0?(u.next=null,i===null?Bd=m:i.next=m,m===null&&(Hd=i)):(i=u,(n!==0||(g&3)!==0)&&(fv=!0)),u=m}ts!==0&&ts!==5||Em(n),gi!==0&&(gi=0)}function Q3(n,l){for(var i=n.suspendedLanes,u=n.pingedLanes,m=n.expirationTimes,g=n.pendingLanes&-62914561;0V)break;var we=se.transferSize,Re=se.initiatorType;we&&a5(Re)&&(se=se.responseEnd,T+=we*(sexv){We.length=He;break}ye=new Promise(yse.bind(ye)),We.push(ye)}}}if(0"u"?null:document;function E5(n,l,i){var u=Vd;if(u&&typeof l=="string"&&l){var m=gr(l);m='link[rel="'+n+'"][href="'+m+'"]',typeof i=="string"&&(m+='[crossorigin="'+i+'"]'),T5.has(m)||(T5.add(m),n={rel:n,crossOrigin:i,href:l},u.querySelector(m)===null&&(l=u.createElement("link"),Js(l,"link",n),ys(l),u.head.appendChild(l)))}}function Bse(n){no.D(n),E5("dns-prefetch",n,null)}function Hse(n,l){no.C(n,l),E5("preconnect",n,l)}function Use(n,l,i){no.L(n,l,i);var u=Vd;if(u&&n&&l){var m='link[rel="preload"][as="'+gr(l)+'"]';l==="image"&&i&&i.imageSrcSet?(m+='[imagesrcset="'+gr(i.imageSrcSet)+'"]',typeof i.imageSizes=="string"&&(m+='[imagesizes="'+gr(i.imageSizes)+'"]')):m+='[href="'+gr(n)+'"]';var g=m;switch(l){case"style":g=Fd(n);break;case"script":g=$d(n)}if(!(Sa.has(g)||(n=I({rel:"preload",href:l==="image"&&i&&i.imageSrcSet?void 0:n,as:l},i),Sa.set(g,n),u.querySelector(m)!==null||l==="style"&&u.querySelector(Dm(g))||l==="script"&&u.querySelector(Im(g))))){var T=u.createElement("link");Js(T,"link",n),l==="style"&&(T[Ds]=!0,T.onload=T.onerror=function(){$p(T)}),ys(T),u.head.appendChild(T)}}}function Vse(n,l){no.m(n,l);var i=Vd;if(i&&n){var u=l&&typeof l.as=="string"?l.as:"script",m='link[rel="modulepreload"][as="'+gr(u)+'"][href="'+gr(n)+'"]',g=m;switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":g=$d(n)}if(!Sa.has(g)&&(n=I({rel:"modulepreload",href:n},l),Sa.set(g,n),i.querySelector(m)===null)){switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(i.querySelector(Im(g)))return}u=i.createElement("link"),Js(u,"link",n),ys(u),i.head.appendChild(u)}}}function Fse(n,l,i){no.S(n,l,i);var u=Vd;if(u&&n){var m=Qo(u).hoistableStyles,g=Fd(n);l=l||"default";var T=m.get(g);if(!T){var V={loading:0,preload:null};if(T=u.querySelector(Dm(g)))V.loading=5;else{n=I({rel:"stylesheet",href:n,"data-precedence":l},i),(i=Sa.get(g))&&oC(n,i);var se=T=u.createElement("link");ys(se),Js(se,"link",n),se._p=new Promise(function(xe,we){se.onload=xe,se.onerror=we}),se.addEventListener("load",function(){V.loading|=1}),se.addEventListener("error",function(){V.loading|=2}),V.loading|=4,hv(T,l,u)}T={type:"stylesheet",instance:T,count:1,state:V},m.set(g,T)}}}function $se(n,l){no.X(n,l);var i=Vd;if(i&&n){var u=Qo(i).hoistableScripts,m=$d(n),g=u.get(m);g||(g=i.querySelector(Im(m)),g||(n=I({src:n,async:!0},l),(l=Sa.get(m))&&iC(n,l),g=i.createElement("script"),ys(g),Js(g,"link",n),i.head.appendChild(g)),g={type:"script",instance:g,count:1,state:null},u.set(m,g))}}function qse(n,l){no.M(n,l);var i=Vd;if(i&&n){var u=Qo(i).hoistableScripts,m=$d(n),g=u.get(m);g||(g=i.querySelector(Im(m)),g||(n=I({src:n,async:!0,type:"module"},l),(l=Sa.get(m))&&iC(n,l),g=i.createElement("script"),ys(g),Js(g,"link",n),i.head.appendChild(g)),g={type:"script",instance:g,count:1,state:null},u.set(m,g))}}function A5(n,l,i,u){var m=(m=Ae.current)?Mm(m):null;if(!m)throw Error(o(446));switch(n){case"meta":case"title":return null;case"style":return typeof i.precedence=="string"&&typeof i.href=="string"?(i=Fd(i.href),l=Qo(m).hoistableStyles,u=l.get(i),u||(u={type:"style",instance:null,count:0,state:null},l.set(i,u)),u):{type:"void",instance:null,count:0,state:null};case"link":if(i.rel==="stylesheet"&&typeof i.href=="string"&&typeof i.precedence=="string"){n=Fd(i.href);var g=Qo(m).hoistableStyles,T=g.get(n);if(T||(m=m.ownerDocument||m,T={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},g.set(n,T),(g=m.querySelector(Dm(n)))?g._p||(T.instance=g,T.state.loading=5):(g=Sa.get(n),g||(g={rel:"preload",as:"style",href:i.href,crossOrigin:i.crossOrigin,integrity:i.integrity,media:i.media,hrefLang:i.hrefLang,referrerPolicy:i.referrerPolicy},Sa.set(n,g)),Gse(m,n,g,T.state))),l&&u===null)throw Error(o(528,""));return T}if(l&&u!==null)throw Error(o(529,""));return null;case"script":return l=i.async,i=i.src,typeof i=="string"&&l&&typeof l!="function"&&typeof l!="symbol"?(i=$d(i),l=Qo(m).hoistableScripts,u=l.get(i),u||(u={type:"script",instance:null,count:0,state:null},l.set(i,u)),u):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,n))}}function Fd(n){return'href="'+gr(n)+'"'}function Dm(n){return'link[rel="stylesheet"]['+n+"]"}function R5(n){return I({},n,{"data-precedence":n.precedence,precedence:null})}function Gse(n,l,i,u){if(l=n.querySelector('link[rel="preload"][as="style"]['+l+"]")){if(l[Ds]!==!0){u.loading=1;return}}else l=n.createElement("link"),l[Ds]=!0,l.onload=l.onerror=$p.bind(null,l),Js(l,"link",i),ys(l),n.head.appendChild(l);u.preload=l,l.addEventListener("load",function(){return u.loading|=1}),l.addEventListener("error",function(){return u.loading|=2})}function $d(n){return'[src="'+gr(n)+'"]'}function Im(n){return"script[async]"+n}function O5(n,l,i){if(l.count++,l.instance===null)switch(l.type){case"style":var u=n.querySelector('style[data-href~="'+gr(i.href)+'"]');if(u)return l.instance=u,ys(u),u;var m=I({},i,{"data-href":i.href,"data-precedence":i.precedence,href:null,precedence:null});return u=(n.ownerDocument||n).createElement("style"),ys(u),Js(u,"style",m),hv(u,i.precedence,n),l.instance=u;case"stylesheet":m=Fd(i.href);var g=n.querySelector(Dm(m));if(g)return l.state.loading|=4,l.instance=g,ys(g),g;u=R5(i),(m=Sa.get(m))&&oC(u,m),g=(n.ownerDocument||n).createElement("link"),ys(g);var T=g;return T._p=new Promise(function(V,se){T.onload=V,T.onerror=se}),Js(g,"link",u),l.state.loading|=4,hv(g,i.precedence,n),l.instance=g;case"script":return g=$d(i.src),(m=n.querySelector(Im(g)))?(l.instance=m,ys(m),m):(u=i,(m=Sa.get(g))&&(u=I({},i),iC(u,m)),n=n.ownerDocument||n,m=n.createElement("script"),ys(m),Js(m,"link",u),n.head.appendChild(m),l.instance=m);case"void":return null;default:throw Error(o(443,l.type))}else l.type==="stylesheet"&&(l.state.loading&4)===0&&(u=l.instance,l.state.loading|=4,hv(u,i.precedence,n));return l.instance}function hv(n,l,i){for(var u=i.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),m=u.length?u[u.length-1]:null,g=m,T=0;T title"):null)}function Kse(n,l,i){if(i===1||l.itemProp!=null)return!1;switch(n){case"meta":case"title":return!0;case"style":if(typeof l.precedence!="string"||typeof l.href!="string"||l.href==="")break;return!0;case"link":if(typeof l.rel!="string"||typeof l.href!="string"||l.href===""||l.onLoad||l.onError)break;return l.rel==="stylesheet"?(n=l.disabled,typeof l.precedence=="string"&&n==null):!0;case"script":if(l.async&&typeof l.async!="function"&&typeof l.async!="symbol"&&!l.onLoad&&!l.onError&&l.src&&typeof l.src=="string")return!0}return!1}function D5(n,l){return n==="img"&&l.src!=null&&l.src!==""&&l.onLoad==null&&l.loading!=="lazy"}function I5(n){return!(n.type==="stylesheet"&&(n.state.loading&3)===0)}function P5(n){return(n.width||100)*(n.height||100)*(typeof devicePixelRatio=="number"?devicePixelRatio:1)*.25}function _5(n,l){typeof l.decode=="function"&&(n.imgCount++,l.complete||(n.imgBytes+=P5(l),n.suspenseyImages.push(l)),n=Qse.bind(n),l.decode().then(n,n))}function Yse(n,l,i,u){if(i.type==="stylesheet"&&(typeof u.media!="string"||matchMedia(u.media).matches!==!1)&&(i.state.loading&4)===0){if(i.instance===null){var m=Fd(u.href),g=l.querySelector(Dm(m));if(g){l=g._p,l!==null&&typeof l=="object"&&typeof l.then=="function"&&(n.count++,n=Pm.bind(n),l.then(n,n)),i.state.loading|=4,i.instance=g,ys(g);return}g=l.ownerDocument||l,u=R5(u),(m=Sa.get(m))&&oC(u,m),g=g.createElement("link"),ys(g);var T=g;T._p=new Promise(function(V,se){T.onload=V,T.onerror=se}),Js(g,"link",u),i.instance=g}n.stylesheets===null&&(n.stylesheets=new Map),n.stylesheets.set(i,l),(l=i.state.preload)&&(i.state.loading&3)===0&&(n.count++,i=Pm.bind(n),l.addEventListener("load",i),l.addEventListener("error",i))}}var xv=0;function Xse(n,l){return n.stylesheets&&n.count===0&&vv(n,n.stylesheets),0xv?50:800)+l);return n.unsuspend=i,function(){n.unsuspend=null,clearTimeout(u),clearTimeout(m)}}:null}function L5(n){if(n.count===0&&(n.imgCount===0||!n.waitingForImages)){if(n.stylesheets)vv(n,n.stylesheets);else if(n.unsuspend){var l=n.unsuspend;n.unsuspend=null,l()}}}function Pm(){this.count--,L5(this)}function Qse(){this.imgCount--,L5(this)}var bv=null;function vv(n,l){n.stylesheets=null,n.unsuspend!==null&&(n.count++,bv=new Map,l.forEach(Zse,n),bv=null,Pm.call(n))}function Zse(n,l){if(!(l.state.loading&4)){var i=bv.get(n);if(i)var u=i.get(null);else{i=new Map,bv.set(n,i);for(var m=n.querySelectorAll("link[data-precedence],style[data-precedence]"),g=0;g"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Ej.exports=I8(),Ej.exports}var jn=P8();const dg=[20,50,100,200],fg=[20,50,100,200,"all"],xu=50,VR="workbuddy-desktop-table-size:";function FR(e){return e==="all"?r("全部"):String(e)}function pg(e,t=fg,a=xu){t.includes(a)||(a=t.includes(xu)?xu:t[0]);let o=null;try{o=localStorage.getItem(VR+e)}catch{return a}if(o===null||o.trim()==="")return a;if(o==="all")return t.includes("all")?"all":a;const c=Number(o);return Number.isFinite(c)&&t.includes(c)?c:a}function mg(e,t){try{localStorage.setItem(VR+e,String(t))}catch{}}function hg(e,t,a={}){const o=a.sizes??fg,c=a.defaultSize??xu,[d,f]=x.useState(()=>pg(t,o,c)),[p,h]=x.useState(1),b=Math.max(1,d==="all"?1:Math.ceil(e/d)),y=Math.min(Math.max(1,p),b);x.useEffect(()=>{y!==p&&h(y)},[y,p]);const v=x.useCallback(k=>{f(k),mg(t,k),h(1)},[t]),j=x.useCallback(k=>{h(Math.min(Math.max(1,Math.round(k)||1),b))},[b]),w=d==="all"?0:(y-1)*d,S=d==="all"?e:Math.min(e,w+d),N=x.useCallback(k=>d==="all"?k.slice():k.slice(w,S),[d,w,S]);return{size:d,page:y,pageCount:b,rangeStart:e?w+1:0,rangeEnd:e?S:0,paged:d!=="all",setSize:v,goto:j,slice:N}}function $i({total:e,page:t,pageCount:a,size:o,sizes:c=fg,onSizeChange:d,onPageChange:f,range:p=null,disabled:h=!1,leading:b,className:y}){const[v,j]=x.useState(String(t));x.useEffect(()=>j(String(t)),[t]);const w=()=>{const k=v.trim();if(!k){j(String(t));return}const A=Number(k);if(!Number.isFinite(A)){j(String(t));return}const P=Math.min(Math.max(1,Math.round(A)),a);j(String(P)),P!==t&&f(P)},S=a<=1,N=e===0?r("共 0 条"):p?r("共 {total} 条 · 当前第 {start}–{end} 条",{total:e,start:p.start,end:p.end}):r("共 {total} 条(全部显示)",{total:e});return s.jsxs("div",{className:y?`panel-foot table-foot-bar ${y}`:"panel-foot table-foot-bar",children:[b,s.jsx("div",{className:"spacer"}),s.jsxs("div",{className:"table-foot-ctl",children:[s.jsx("span",{className:"table-foot-count",children:N}),s.jsxs("span",{className:"table-foot-size",children:[r("每页"),s.jsxs(ut,{value:String(o),onValueChange:k=>d(k==="all"?"all":Number(k)),children:[s.jsx(ft,{className:"h-[26px] w-[86px]",disabled:h,"aria-label":r("每页条数"),children:s.jsx(dt,{children:FR(o)})}),s.jsx(pt,{children:c.map(k=>s.jsx($e,{value:String(k),children:FR(k)},String(k)))})]}),r("条")]}),s.jsxs("span",{className:"table-foot-jump",children:[r("跳至"),s.jsx(Fe,{className:"h-[26px] w-[52px] px-1 text-center",value:v,disabled:h||S,"aria-label":r("跳转到指定页"),title:S?r("当前只有一页"):r("跳转到第 1–{pageCount} 页",{pageCount:a}),inputMode:"numeric",onChange:k=>j(k.target.value),onKeyDown:k=>{k.key==="Enter"?(k.preventDefault(),w()):k.key==="Escape"&&j(String(t))},onBlur:w}),r("页")]}),s.jsx(K6,{page:t,pageCount:a,onPageChange:f,disabled:h})]})]})}const Oj=[{key:"pick",label:r("选择"),align:"center",legacyAlign:"left"},{key:"order",label:r("顺序"),title:r("组内先后:按住左边的把手上下拖动即可调整;整组的先后拖分组带的把手"),align:"center",legacyAlign:"left"},{key:"account",label:r("账号"),align:"center",legacyAlign:"left"},{key:"proxy",label:r("代理"),title:r("该账号出网走的代理(Clash 出口 / 自定义 / 直连);点击可修改"),align:"center"},{key:"connections",label:r("连接数"),title:r("此刻正在使用这个账号的请求数(含还在下发内容的流式请求);为 0 时不显示"),align:"center"},{key:"status",label:r("状态"),align:"center",legacyAlign:"left"},{key:"limits",label:r("限流"),title:r("该账号当前限流中的模型;点徽章看明细"),align:"center",legacyAlign:"left"},{key:"expiry",label:r("有效期"),align:"center",legacyAlign:"left"},{key:"usage",label:r("余额"),align:"center",legacyAlign:"left"},{key:"actions",label:r("操作"),align:"right"}],$R="agent2api-accounts-col-widths",If={pick:47,order:84,proxy:186,connections:56,status:80,limits:148,expiry:80,usage:148,actions:200},Mj=new Set(["account"]),_8=300,Dj=56,L8=new Set([...Object.keys(If),...Mj]),bu=(()=>{try{const e=JSON.parse(localStorage.getItem($R)||"{}"),t={};for(const[a,o]of Object.entries(e||{})){const c=Number(o);L8.has(a)&&Number.isFinite(c)&&c>=Dj&&(t[a]=Math.round(c))}return t}catch{return{}}})();function qR(){try{localStorage.setItem($R,JSON.stringify(bu))}catch{}}function z8(){return{...If,...bu}}function B8(e){let t=0;for(const a of e){const o=bu[a];o?t+=o:Mj.has(a)?t+=_8:If[a]?t+=If[a]:t+=Dj}return Math.round(t)}function GR(e,t){const a=e?.querySelector(`thead th:nth-child(${t+1})`),o=a?.getAttribute("data-col")||a?.className.match(/cell-([a-z]+)/)?.[1];if(!o)return null;const c=e?.querySelector(`colgroup col[data-col="${CSS.escape(o)}"]`)||e?.querySelectorAll("colgroup col")[t];return c?{key:o,col:c}:null}function H8(e,t,a){const o=Math.max(Dj,Math.round(a));e.style.width=o+"px",Mj.has(t)||o!==If[t]?bu[t]=o:delete bu[t]}let Ij=()=>{};function U8(e,t){if(Ij=t,!e)return;let a=null;e.addEventListener("pointerdown",o=>{if(o.button!==0)return;const c=o.target?.closest?.(".col-grip");if(!c)return;o.preventDefault();const d=c.closest("th"),f=d?.closest("table")||null,p=d?.parentElement?[...d.parentElement.children].indexOf(d):-1,h=GR(f,p);if(!h)return;const b=o.clientX,y=h.col.getBoundingClientRect().width;c.classList.add("active"),document.body.classList.add("col-resizing");try{c.setPointerCapture(o.pointerId)}catch{}a={...h,startX:b,startWidth:y,grip:c,pointerId:o.pointerId},window.addEventListener("pointermove",v),window.addEventListener("pointerup",j),window.addEventListener("pointercancel",j),window.addEventListener("blur",j);function v(w){if(a){if(w.buttons===0){j();return}H8(a.col,a.key,a.startWidth+w.clientX-a.startX)}}function j(){if(!a)return;const{grip:w,pointerId:S}=a;a=null,w.classList.remove("active"),document.body.classList.remove("col-resizing");try{w.releasePointerCapture(S)}catch{}window.removeEventListener("pointermove",v),window.removeEventListener("pointerup",j),window.removeEventListener("pointercancel",j),window.removeEventListener("blur",j),qR(),Ij()}}),e.addEventListener("dblclick",o=>{const c=o.target?.closest?.(".col-grip");if(!c)return;const d=c.closest("th"),f=d?.closest("table")||null,p=d?.parentElement?[...d.parentElement.children].indexOf(d):-1,h=GR(f,p);h&&(delete bu[h.key],qR(),Ij())})}function gt(){return window}function Ln(e,t){gt().wbApp?.toast?.(e,t)}function ko(e){return e instanceof Error&&e.message?e.message:String(e??"").trim()||r("未知错误")}function Pj(e){return(gt().wbApp?.getState?.()?.accounts?.accounts||[]).filter(a=>(a?.provider||"workbuddy")===e).length}function KR(e){const t=e?.name||"";if(t)return(gt().wbProviders?.customList?.()||[]).find(a=>(a.name||"")===t)}function V8(e){const t=e?.name||"";return t?(gt().wbPresetProviders?.list||[]).some(a=>a.name===t):!1}async function vu(e){const t=gt().__TAURI_INTERNALS__;if(!t||typeof t.invoke!="function")throw new Error(r("桌面运行时不可用(Tauri 未初始化)"));return t.invoke("api_request",{request:{method:"POST",path:"/api/accounts",body:e}})}function Pf(e){return e?.name||e?.uid||e?.userId||""}function _j(){gt().wbAddAccountModal?.close?.()}async function Co(e,t){_j(),await gt().wbApp?.refresh?.(),Ln(r("✅ {label}账号已添加{name}",{label:t,name:e?`:${e}`:""}))}const yu=new Map;function _r(e){return{defaultValue:yu.get(e)??"",onChange:t=>{const a=t.currentTarget.value;a?yu.set(e,a):yu.delete(e)}}}function To(e,t){t?yu.set(e,t):yu.delete(e);const a=document.getElementById(e);(a instanceof HTMLInputElement||a instanceof HTMLTextAreaElement)&&(a.value=t)}function dr(e){const t=document.getElementById(e);return t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement?t.value.trim():(yu.get(e)??"").trim()}function Lj(e){for(const t of e)To(t,"")}const qi={edition:"cn",loginMode:"embedded",socialRestore:!1},zj=100,F8=256,$8=e=>e.key==="name"?zj:F8,q8={provider:"raccoon",label:"小浣熊",addButton:r("添加小浣熊账号"),webLogin:{noteHtml:r("在内嵌窗口里完成官方登录,成功后自动加入账号列表。"),button:r("打开网页登录"),hint:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待"),busyText:r("等待小浣熊登录完成…")},manualTitle:r("粘贴 token / refreshToken"),manualNoteHtml:r('refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。'),fields:[{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用凭证里的账号名")},{key:"token",label:"token",rows:3,placeholder:r("粘贴 access_token(一长串 JWT)")},{key:"refreshToken",inputKey:"refresh",label:"refreshToken",rows:2,optional:!0,placeholder:r("可选")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。"),fileImport:{accept:".json,application/json",note:r("选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。")}},G8={provider:"catpaw",label:"CatPaw",webLogin:{noteHtml:r("用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。"),button:r("打开 CatPaw 网页登录"),busyText:r("等待 CatPaw 登录完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录的美团账号);完成后自动加入列表")}]},manualNote:r("token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。"),fields:[{key:"token",label:"token",rows:3,placeholder:r("CatPaw 的 X-Passport-Token(登录态 Cookie)")},{key:"uid",label:"uid",placeholder:r("必填,CatPaw 账号标识")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用登录名或 uid")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。"),desktopHint:r("读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录"),fileImport:{accept:".json,application/json",note:r("选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。")}},K8={provider:"autoclaw",label:r("AutoClaw 国内版"),manualNote:r("token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。"),smsLogin:{noteHtml:r("用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。")},fields:[{key:"token",label:"token",rows:3,placeholder:r("明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("没有则无法自动续期")},{key:"deviceId",label:"deviceId",optional:!0,placeholder:r("可选,续期时带上")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用 userId")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。"),desktopHint:r("读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows"),desktopWindowsOnly:!0},Y8={provider:"autoclaw-intl",label:r("AutoClaw 国际版"),manualNote:r("国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。"),oauthLogin:{title:r("网页登录(Zai / Google)"),noteHtml:r("点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表")}]},fields:[{key:"token",label:"token",rows:3,placeholder:r("明文 JWT(国际版账号的 access token)")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("没有则无法自动续期")},{key:"deviceId",label:"deviceId",optional:!0,placeholder:r("可选,续期时带上")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用 userId")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。"),desktopHint:r("读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows"),desktopWindowsOnly:!0};function YR(e){const{provider:t,label:a,siteNote:o}=e;return{provider:t,label:a,desktop:!1,webLogin:{noteHtml:r("打开官方授权页完成设备码授权,登录的是{label}({site})的账号。",{label:a,site:o}),button:r("打开 Qoder 网页登录"),busyText:r("等待 Qoder 授权完成…"),edition:t==="qoder"?"cn":"global",modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口用全新环境,多账号互不影响;关窗即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录账号);完成后自动加入列表")}]},manualTitle:r("使用个人访问令牌(PAT)"),manualNote:r("在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。",{label:a}),fields:[{key:"pat",label:"Qoder PAT",rows:3,placeholder:r("粘贴 Qoder 个人访问令牌(pt-…)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空使用账号昵称或邮箱")}]}}const X8=YR({provider:"qoder",label:r("中国版"),siteNote:"qoder.com.cn"}),Q8=YR({provider:"qoder-intl",label:r("国际版"),siteNote:"qoder.com"});function XR(e){const{provider:t,label:a,poolNote:o}=e;return{provider:t,label:a,desktop:!0,webLogin:{noteHtml:r("打开授权页完成确认,账号自动加入 {label}{note}",{label:a,note:o}),button:r("打开 Cline 授权页"),busyText:r("等待 Cline 授权确认…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表")}]},manualTitle:r("填写凭证"),manualNote:r("refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。",{label:a}),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("粘贴 workos:… 开头的令牌(不带前缀也会自动补上)")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("可选,没有则无法自动续期")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空使用账号姓名、邮箱或令牌指纹")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。",{label:a}),desktopHint:r("读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录"),fileImport:{accept:".json,application/json",note:r("选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。",{label:a})}}}function QR(e){const{provider:t,label:a,site:o,siteNote:c}=e;return{provider:t,label:a,webLogin:{noteHtml:r("打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。",{label:a,site:o}),button:r("打开 Accio {label}登录页",{label:a}),busyText:r("等待 Accio {label}登录完成…",{label:a}),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待")}]},manualTitle:r("填写凭证"),manualNoteHtml:r("accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)",{label:a,siteNote:c}),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("粘贴 Accio 的 accessToken")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("可选,没有则无法自动续期")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空使用账号昵称或邮箱")}]}}function ZR(e){const{provider:t,label:a,site:o,planNote:c}=e;return{provider:t,label:a,desktop:!1,webLogin:{noteHtml:r("打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。",{label:a}),button:r("打开 ZCode {label}授权页",{label:a}),busyText:r("等待 ZCode {label}授权完成…",{label:a}),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象")}]},manualTitle:r("填写凭证"),manualNoteHtml:r("本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)",{site:o,label:a,plan:c}),fields:[{key:"accessToken",label:r("编码套餐 API Key"),rows:3,optional:!0,placeholder:r("用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)")},{key:"jwt",label:"Coding Plan JWT",inputKey:"jwt",rows:3,optional:!0,placeholder:r("用于领取套餐与查询余额;不填则这个账号不能领取与查余额")},{key:"userId",label:r("用户 ID"),optional:!0,placeholder:r("可选;用于生成账号 id 与展示名")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空自动生成")}]}}const Z8={provider:"codearts",label:"CodeArts",desktop:!1,webLogin:{noteHtml:r("打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。"),button:r("打开 CodeArts 授权页"),busyText:r("等待 CodeArts 登录完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板")}]},manualTitle:r("粘贴登录凭据"),manualNoteHtml:r('整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {"codearts_provider_credential":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。'),fields:[{key:"credentialJson",label:r("凭据 JSON"),rows:8,jsonExpand:!0,placeholder:'{"codearts_provider_credential":{"access_key_id":"HSTA…","secret_access_key":"…","security_token":"…","expires_at":"2026-09-27T16:17:00.327Z","domain_id":"…","user_id":"…","user_name":"…","refresh_token":"eyJ…","oauth_context":{…}}}'},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空使用凭据里的 user_name")}]},W8={provider:"trae",label:"Trae",desktop:!1,webLogin:{noteHtml:r("打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。"),button:r("打开 Trae 授权页"),busyText:r("等待 Trae 授权完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。")}]},manualTitle:r("填写凭证"),manualNoteHtml:r("accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。"),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("Cloud-IDE-JWT(三段点分)")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("可选;填了才能到期自动续期")},{key:"uid",label:r("用户 ID"),optional:!0,placeholder:r("可选;用于去重与展示名(留空时网关会问一次上游)")},{key:"machineId",label:"machineId",optional:!0,placeholder:r("可选;UUID 形态,与凭据同生共死")},{key:"deviceId",label:"deviceId",optional:!0,placeholder:r("可选;纯数字串(上游只收 8–24 位数字)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空自动用昵称")}]},J8={provider:"loomy",label:"Loomy",smsLogin:{noteHtml:r("用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。")},manualNote:r("粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。"),fields:[{key:"session",label:"session",rows:3,placeholder:r("登录 session(一长串)")},{key:"userId",label:"userId",optional:!0,placeholder:r("可选,讯飞侧 userid")},{key:"phone",label:r("手机号"),optional:!0,placeholder:r("可选,展示用")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用脱敏手机号或 userId")}],desktop:!1},eq={provider:"kuku",label:"KukuAI",webLogin:{noteHtml:r("在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。"),button:r("打开网页登录"),busyText:r("等待 KukuAI 登录完成…")},manualTitle:r("粘贴 Cookie"),manualNote:r("BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。"),fields:[{key:"cookie",label:"Cookie",rows:3,placeholder:r("BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用账号 uk")}],desktop:!0,desktopHint:r("读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录"),desktopNote:r("读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。"),fileImport:{binary:!0,accept:"",note:r("选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。")}};function WR(e){const{provider:t,label:a,siteNote:o}=e;return{provider:t,label:a,desktop:!1,manualTitle:r("粘贴 session cookie"),manualNoteHtml:r("粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。",{siteNote:o}),fields:[{key:"session",label:"session",rows:3,placeholder:r("monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)")},{key:"imageId",label:r("任务镜像 id"),optional:!0,placeholder:r("可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用上游返回的账号名或账号 id")}]}}const tq=WR({provider:"monkeycode",label:r("MonkeyCode"),siteNote:r("这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。")}),nq=WR({provider:"monkeycode-intl",label:r("MonkeyCode 国际版"),siteNote:r("这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。")}),sq={provider:"commandcode",label:r("Command Code"),desktop:!1,manualTitle:r("粘贴 API Key"),manualNote:r("粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。"),fields:[{key:"apiKey",label:"apiKey",rows:3,placeholder:r("user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用 key 尾号")}]},rq={provider:"antigravity",label:r("Antigravity"),desktop:!1,webLogin:{noteHtml:r("在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。"),button:r("打开 Antigravity 网页登录"),busyText:r("等待 Google 授权完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表")}]},manualTitle:r("粘贴 Google refresh token"),manualNoteHtml:r("粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。"),fields:[{key:"refreshToken",label:"refreshToken",rows:2,placeholder:r("1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)")},{key:"projectId",label:"projectId",optional:!0,placeholder:r("可选(cloudaicompanionProject):留空由网关自动发现")},{key:"email",label:"email",optional:!0,placeholder:r("可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用邮箱或令牌尾号")}]},aq={provider:"officeace",label:r("OfficeAce 果办"),desktop:!1,webLogin:{noteHtml:r("打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。"),button:r("打开授权页"),busyText:r("等待 OfficeAce 登录完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表")}]},manualTitle:r("粘贴网关凭据"),manualNoteHtml:r("从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。"),fields:[{key:"baseUrl",label:r("模型网关基址"),placeholder:"https://modelgw-…huaweicloud-agentarts.com/v2"},{key:"modelAppKey",label:r("网关 Key"),placeholder:"model_app_key"},{key:"modelAppSecret",label:r("网关 Secret"),placeholder:"model_app_secret"},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空用「OfficeAce 果办」")}]},lq={provider:"orcaterm",label:"OrcaTerm",webLogin:{noteHtml:r("在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。"),button:r("打开网页登录"),hint:r("内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待"),busyText:r("等待 OrcaTerm 登录完成…")},desktop:!0,desktopHint:r("读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录"),desktopNote:r("读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。"),manualTitle:r("粘贴 accessToken"),manualNoteHtml:r("粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。"),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用账号昵称或 userId")}]},oq={provider:"chatglm",label:"智谱清言",guestLogin:{noteHtml:r("不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。"),button:r("添加访客账号"),busyText:r("正在换发访客凭证…"),namePlaceholder:r("可选,给这个访客账号起个备注名")},desktop:!0,desktopWindowsOnly:!0,desktopHint:r("读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录"),desktopNote:r("读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。"),manualTitle:r("粘贴访问令牌"),manualNoteHtml:r("粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。"),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用账号昵称")}]},JR=[q8,G8,K8,Y8,X8,Q8,XR({provider:"cline-free",label:"Cline Free",poolNote:r("(免费额度池,模型名带 cline-free/ 前缀)。")}),XR({provider:"cline-pass",label:"Cline Pass",poolNote:r("(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。")}),QR({provider:"accio",label:r("国际版"),site:"www.accio.com",siteNote:r("国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。")}),QR({provider:"accio-cn",label:r("国内版"),site:"www.accio-ai.com",siteNote:r("国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。")}),ZR({provider:"zcode",label:r("国内版"),site:"open.bigmodel.cn",planNote:r("国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。")}),ZR({provider:"zcode-intl",label:r("国际版"),site:"api.z.ai",planNote:r("国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。")}),Z8,W8,J8,eq,tq,nq,sq,rq,aq,lq,oq],Gi="workbuddy",ju="custom",Bj="WorkBuddy";function iq(e){return JR.find(t=>t.provider===e)}const eO=[{id:"guest",label:r("访客模式(免登录)")},{id:"oauth",label:r("网页登录(Zai / Google)")},{id:"sms",label:r("手机验证码登录")},{id:"web",label:r("网页登录")},{id:"manual",label:r("填写凭证")},{id:"file",label:r("导入凭证文件")},{id:"desktop",label:r("导入桌面端登录态")}],Hj=()=>gt().workbuddyDesktop?.platform||"";function tO(e){if(e.desktop===!1)return!1;const t=Hj();return!(t==="web"||e.desktopWindowsOnly&&t!=="windows")}function nO(e,t){return eO.filter(a=>a.id==="guest"?!!e.guestLogin:a.id==="oauth"?!!e.oauthLogin:a.id==="sms"?!!e.smsLogin:a.id==="web"?!!e.webLogin&&(!e.webLogin?.region||t===e.webLogin.region):a.id==="file"?!!e.fileImport:a.id==="desktop"?tO(e):!0).map(a=>a.id)}const cq=e=>e.manualTitle||r("填写凭证添加"),uq=e=>e.manualNoteHtml?{html:e.manualNoteHtml}:{text:e.manualNote||""},dq=e=>e.addButton||r("添加 {name} 账号",{name:e.label}),gg=(e,t)=>`${e.provider}-${t.inputKey||t.key}-input`;function fq(e){return e.source==="subscription"&&(e.port===null||e.port===void 0)}function tr(){return window}function qn(e,t){tr().wbApp?.toast?.(e,t)}function Ra(e){return e instanceof Error?e.message:String(e)}function sO(e){return tr().wbApp?.formatTime?.(e)||""}function Uj(e){const t=Number(e);return!Number.isFinite(t)||t<0?"":t<1e3?`${Math.round(t)}ms`:`${(t/1e3).toFixed(1)}s`}function Vj(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t]||t)}function wu(e){return String(e?.name||e?.id||"")}function rO(e){return e.source==="clash"}function _f(e){return e.source==="subscription"}function xg(e){return rO(e)||_f(e)}function pq(e){return e.localDisabled===!0||e.enabled===!1}function aO(e){return xg(e)&&e.enabled===!1&&e.localDisabled!==!0}function mq(e){return _f(e)&&pq(e)}function bg(e){return _f(e)&&e.orphan===!0}function lO(e){return!xg(e)||bg(e)}const hq=r("来自 Clash Verge 同步(名称、端口跟随 Clash),请到 Clash Verge 中修改;启用可在本页关闭"),gq=r("该节点来自订阅(名称、端口跟随订阅与内核),请在「订阅管理」里修改;启用可在本页关闭"),oO=r("该节点所属订阅已删除,不会再被同步更新,可手动删除清理");function iO(e){return bg(e)?oO:_f(e)?gq:hq}const xq=r("禁用后本端不再用它(引用它的账号回退直连);端口在 Clash Verge 侧,不受影响"),bq=r("禁用后本端不再用它(引用它的账号回退直连),并会关掉它的本地监听端口"),vq=r("已在本页禁用(打开开关即恢复)"),yq=r("这条在 Clash Verge 里是停用的,本页启用不生效 —— 到 Clash Verge 里打开它");function jq(e){if(bg(e))return oO;if(e.localDisabled===!0)return vq;if(aO(e))return yq;if(_f(e))return bq;if(rO(e))return xq}let xs={data:null,loading:!1,error:"",testing:null,pending:new Set,syncing:!1,batchBusy:!1,batchProgress:null,selected:new Set};const Fj=new Set;function cO(e){return Fj.add(e),()=>{Fj.delete(e)}}function uO(){return xs}function rs(e){xs={...xs,...e},Fj.forEach(t=>t())}function vg(){return xs.data?.items??[]}function wq(e){return xs.selected.has(e)}function Sq(e,t){const a=new Set(xs.selected);t?a.add(e):a.delete(e),rs({selected:a})}function Nq(e,t){const a=new Set(xs.selected);for(const o of e)t?a.add(o):a.delete(o);rs({selected:a})}function kq(){rs({selected:new Set})}function Eo(e){if(!e||typeof e!="object"||!Array.isArray(e.items))return;const t=new Set(e.items.map(o=>o.id)),a=new Set([...xs.selected].filter(o=>t.has(o)));rs({data:e,error:"",selected:a})}async function Lf(e=!1){const t=tr().workbuddyDesktop;if(typeof t?.getProxyPool!="function"){rs({error:r("当前环境不支持代理池(桥接方法缺失)")});return}e||rs({loading:!0});try{Eo(await t.getProxyPool())}catch(a){rs({error:Ra(a)}),e||qn(r("代理列表加载失败:{reason}",{reason:Ra(a)}),"err")}finally{rs({loading:!1})}}async function Cq(){const e=tr().workbuddyDesktop;if(typeof e?.syncClashToProxyPool!="function"){qn(r("当前环境不支持同步(桥接方法缺失)"),"err");return}if(!xs.syncing){rs({syncing:!0});try{const t=await e.syncClashToProxyPool();Eo(t),t?.syncError?qn(r("没能同步:{reason}",{reason:t.syncError}),"err"):t?.changes?qn(r("✅ 已同步 Clash Verge 出口({n} 项变更)",{n:t.changes})):qn(r("已是最新,没有需要同步的变更"))}catch(t){qn(r("同步失败:{reason}",{reason:Ra(t)}),"err")}finally{rs({syncing:!1})}}}async function Tq(e){const t=tr().workbuddyDesktop;if(typeof t?.testProxyPoolItem!="function"){qn(r("当前环境不支持代理测试(桥接方法缺失)"),"err");return}if(!xs.testing){rs({testing:e.id});try{const a=await t.testProxyPoolItem(e.id);if(a?.items&&Eo({items:a.items}),a?.success){const o=Uj(a.durationMs);qn(r("✅ 「{name}」出口可用{ip}{took}",{name:wu(e),ip:a.ip?r(" 出口 IP {ip}",{ip:a.ip}):"",took:o?` ${o}`:""}))}else qn(r("❌ 「{name}」{error}",{name:wu(e),error:a?.error||r("连接失败")}),"err");a?.saveError&&qn(r("测试结果没能记下:{reason}",{reason:a.saveError}),"err")}catch(a){qn(r("测试失败:{reason}",{reason:Ra(a)}),"err")}finally{rs({testing:null})}}}async function Eq(e,t){const a=tr().workbuddyDesktop;if(typeof a?.setProxyPoolItemEnabled!="function"){qn(r("当前环境不支持启停(桥接方法缺失)"),"err");return}const o=new Set(xs.pending);o.add(e.id),rs({pending:o});try{const c=await a.setProxyPoolItemEnabled({id:e.id,enabled:t});Eo(c);const d=wu(e),f=c?.listener??"none";qn(t?f==="opening"?r("已启用「{name}」,正在补建监听端口(内核重建中)",{name:d}):r("已启用「{name}」",{name:d}):f==="closing"?r("已禁用「{name}」,监听端口正在关闭(内核重建中)",{name:d}):r("已禁用「{name}」",{name:d})),(f==="closing"||f==="opening")&&Aq(e.id,f)}catch(c){qn(r("保存失败:{reason}",{reason:Ra(c)}),"err")}finally{const c=new Set(xs.pending);c.delete(e.id),rs({pending:c})}}async function Aq(e,t){for(let a=0;a<12;a+=1){await new Promise(d=>setTimeout(d,1500)),await Lf(!0);const o=vg().find(d=>d.id===e);if(!o)return;const c=o.port!==null&&o.port!==void 0;if(t==="closing"?!c:c)return}}async function dO(e){const t=tr().workbuddyDesktop;if(typeof t?.removeProxyPoolItem!="function")return;if(!lO(e)){qn(iO(e),"err");return}const a=e.usedBy||[],o=a.length?`

    ${r("有 {n} 个账号正在使用它({names})—— 删除后这些账号会回退直连。",{n:a.length,names:a.map(f=>Vj(String(f.name||f.id||""))).join(r("、"))})}

    `:"";if(!await tr().wbConfirm?.ask?.({title:r("删除代理"),html:r("确定删除「{name}」?{used}",{name:Vj(wu(e)),used:o}),okText:r("删除"),okClass:"danger"}))return;const d=new Set(xs.pending);d.add(e.id),rs({pending:d});try{const f=await t.removeProxyPoolItem(e.id);Eo(f),qn(r("已删除「{name}」",{name:wu(e)}))}catch(f){qn(r("删除失败:{reason}",{reason:Ra(f)}),"err")}finally{const f=new Set(xs.pending);f.delete(e.id),rs({pending:f})}}async function Rq(){const e=tr().workbuddyDesktop;if(typeof e?.testProxyPoolItem!="function"){qn(r("当前环境不支持代理测试(桥接方法缺失)"),"err");return}if(xs.batchBusy||xs.testing)return;const t=vg().filter(f=>xs.selected.has(f.id));if(!t.length)return;rs({batchBusy:!0,batchProgress:{done:0,total:t.length}});let a=0,o=0,c="";for(const[f,p]of t.entries()){rs({testing:p.id,batchProgress:{done:f,total:t.length}});try{const h=await e.testProxyPoolItem(p.id);h?.items&&Eo({items:h.items}),h?.success?a+=1:o+=1,h?.saveError&&!c&&(c=h.saveError)}catch{o+=1}}rs({testing:null,batchBusy:!1,batchProgress:null});const d=o?r("批量测试完成:{ok} 个可用、{failed} 个失败(共 {total} 个)",{ok:a,failed:o,total:t.length}):r("批量测试完成:{ok} 个可用(共 {total} 个)",{ok:a,total:t.length});qn(o?d:`✅ ${d}`,o?"err":"ok"),c&&qn(r("部分测试结果没能记下:{reason}",{reason:c}),"err")}async function Oq(){const e=tr().workbuddyDesktop;if(typeof e?.removeProxyPoolItem!="function"||xs.batchBusy||xs.testing)return;const t=vg().filter(S=>xs.selected.has(S.id)),a=t.filter(S=>lO(S)),o=t.length-a.length;if(!a.length){qn(o?r("选中的 {n} 条都是同步来的只读条目(Clash / 订阅),不能删除",{n:o}):r("没有可删除的条目"),"err");return}const c=a.slice(0,8).map(S=>Vj(wu(S))).join(r("、")),d=a.length>8?r("{names} 等 {n} 条",{names:c,n:a.length}):c,f=a.filter(S=>(S.usedBy||[]).length).length,p=f?`

    ${r("其中 {n} 条正被账号使用 —— 删除后那些账号会回退直连。",{n:f})}

    `:"",h=o?`

    ${r("另有 {n} 条是同步来的只读条目(Clash / 订阅),将跳过。",{n:o})}

    `:"";if(!await tr().wbConfirm?.ask?.({title:r("批量删除代理"),html:`${r("确定删除选中的 {n} 个代理?",{n:a.length})}

    ${d}

    ${p}${h}`,okText:r("删除"),okClass:"danger"}))return;rs({batchBusy:!0,batchProgress:{done:0,total:a.length}});let y=0,v=0,j="";for(const[S,N]of a.entries()){rs({batchProgress:{done:S,total:a.length}});try{const k=await e.removeProxyPoolItem(N.id);Eo(k),y+=1}catch(k){v+=1,j||(j=Ra(k))}}rs({batchBusy:!1,batchProgress:null});const w=[r("已删除 {n} 个代理",{n:y})];o&&w.push(r("跳过 {n} 个(同步只读条目)",{n:o})),v&&w.push(r("失败 {n} 个({reason})",{n:v,reason:j})),qn(v?w.join(r(",")):`✅ ${w.join(r(","))}`,v?"err":"ok")}async function Mq(e,t){const a=tr().workbuddyDesktop,o=e?{...t,id:e.id}:t,c=e?await a?.updateProxyPoolItem?.(o):await a?.createProxyPoolItem?.(o);return Eo(c),c}async function fO(){const e=tr().workbuddyDesktop;if(typeof e?.getProxySettings!="function")throw new Error(r("当前环境不支持代理设置(桥接方法缺失)"));const t=await e.getProxySettings();if(!t||typeof t!="object")throw new Error(r("代理设置响应异常"));return t}async function Dq(e){const t=tr().workbuddyDesktop;if(typeof t?.saveProxySettings!="function")throw new Error(r("当前环境不支持代理设置(桥接方法缺失)"));const a=await t.saveProxySettings(e);if(!a||typeof a!="object")throw new Error(r("代理设置响应异常"));return a}function nr(){return window}function an(e,t){nr().wbApp?.toast?.(e,t)}function wr(e){return e instanceof Error?e.message:String(e)}let Ft={data:null,loading:!1,error:"",pending:!1,refreshing:null};const $j=new Set;function yg(e){return $j.add(e),()=>{$j.delete(e)}}function jg(){return Ft}function wn(e){Ft={...Ft,...e},$j.forEach(t=>t())}function Iq(){return Ft.data?.items??[]}function Su(){return Ft.data?.kernel??null}function Ki(e){!e||typeof e!="object"||!Array.isArray(e.items)||wn({data:e,error:""})}function Ao(){Lf(!0)}async function Ml(e=!1){const t=nr().workbuddyDesktop;if(typeof t?.getSubscriptions!="function"){wn({error:r("当前环境不支持订阅(桥接方法缺失)")});return}e||wn({loading:!0});try{Ki(await t.getSubscriptions())}catch(a){wn({error:wr(a)})}finally{e||wn({loading:!1})}}const Pq=20;function _q(e){const t=e.kernel;if(!t||t.download.state==="downloading")return!1;if(!t.installed||t.lastError&&!t.running)return!0;const a=t.providerSync??{};return(e.items??[]).filter(o=>o.enabled!==!1).every(o=>!!a[o.id])}async function Yi(){const e=nr().workbuddyDesktop;if(typeof e?.getSubscriptions=="function")for(let t=0;tsetTimeout(o,1500)),Ao();let a;try{a=await e.getSubscriptions()}catch{return}if(Ki(a),t>=1&&a&&Array.isArray(a.items)&&_q(a))return}}async function pO(e){const a=await nr().workbuddyDesktop?.addSubscription?.({enabled:!0,kind:"url",url:"",...e});return Ki(a),an(r("已新增订阅「{name}」,内核正在同步节点…",{name:e.name.trim()})),Ao(),Yi(),a??null}async function mO(e,t){const o=await nr().workbuddyDesktop?.saveSubscription?.({id:e.id,...t});Ki(o),an(r("已保存「{name}」",{name:t.name.trim()})),Ao(),Yi()}async function Lq(e,t){const a=nr().workbuddyDesktop;if(!Ft.pending){wn({pending:!0});try{const o=await a?.saveSubscription?.({id:e.id,name:e.name,url:e.url,kind:e.kind,enabled:t});Ki(o),an(t?r("已启用「{name}」",{name:e.name}):r("已禁用「{name}」",{name:e.name})),Ao(),Yi()}catch(o){an(r("保存失败:{reason}",{reason:wr(o)}),"err")}finally{wn({pending:!1})}}}async function zq(e){const t=nr().workbuddyDesktop;if(!(Ft.refreshing||Ft.pending)){wn({refreshing:e.id});try{const a=await t?.refreshSubscription?.(e.id);Ki(a),an(r("已刷新「{name}」,正在同步节点…",{name:e.name})),Ao(),Yi()}catch(a){an(r("刷新失败:{reason}",{reason:wr(a)}),"err")}finally{wn({refreshing:null})}}}async function Bq(e){const t=nr().workbuddyDesktop;if(await window.wbConfirm?.ask?.({title:r("删除订阅"),html:r("确定删除「{name}」?它在代理池里的节点会一并移除,引用这些节点的账号会回退直连。",{name:e.name||e.id}),okText:r("删除"),okClass:"danger"})&&!Ft.pending){wn({pending:!0});try{const o=await t?.removeSubscription?.(e.id);Ki(o),an(r("已删除「{name}」",{name:e.name||e.id})),Ao(),Yi()}catch(o){an(r("删除失败:{reason}",{reason:wr(o)}),"err")}finally{wn({pending:!1})}}}async function Hq(e){const t=nr().workbuddyDesktop;if(typeof t?.downloadKernel!="function"){an(r("当前环境不支持订阅(桥接方法缺失)"),"err");return}if(!Ft.pending){wn({pending:!0});try{const a=await t.downloadKernel(e);a&&Ft.data&&wn({data:{...Ft.data,kernel:a}}),a?.saved===!1&&an(r("下载线路 / 存放目录没能写进配置(本次下载已按新设置走,重启后会恢复原值)"),"err");for(let c=0;c<300;c+=1){await new Promise(f=>setTimeout(f,1e3));const d=await t.getKernelStatus?.();if(d&&Ft.data&&wn({data:{...Ft.data,kernel:d}}),!d||d.download.state!=="downloading")break}const o=Ft.data?.kernel;o?.download.state==="error"?an(r("内核下载失败:{reason}",{reason:o.download.error||r("未知错误")}),"err"):o?.download.state==="canceled"?an(r("已停止下载内核(未下载完的临时文件已删除)")):o?.download.state==="done"&&(an(r("✅ 内核下载完成,正在启动…")),Yi())}catch(a){an(r("内核下载失败:{reason}",{reason:wr(a)}),"err")}finally{wn({pending:!1})}}}async function Uq(){const e=nr().workbuddyDesktop;if(typeof e?.cancelKernelDownload!="function")return"none";try{const t=await e.cancelKernelDownload();if(t&&Ft.data&&wn({data:{...Ft.data,kernel:t}}),t?.canceled===!1)return"none";for(let o=0;o<20;o+=1){const c=await e.getKernelStatus?.();if(c&&Ft.data&&wn({data:{...Ft.data,kernel:c}}),c&&c.download.state!=="downloading")break;await new Promise(d=>setTimeout(d,250))}const a=Ft.data?.kernel?.download.state;return a==="canceled"?"canceled":a==="done"?"done":"stalled"}catch(t){return an(r("停止下载失败:{reason}",{reason:wr(t)}),"err"),"none"}}async function Vq(){const e=nr().workbuddyDesktop;if(!Ft.pending){wn({pending:!0});try{const t=await e?.restartKernel?.();t&&Ft.data&&wn({data:{...Ft.data,kernel:t}}),an(r("内核正在启动…")),Ao(),Yi()}catch(t){an(r("内核启动失败:{reason}",{reason:wr(t)}),"err")}finally{wn({pending:!1})}}}async function Fq(){const e=nr().workbuddyDesktop;if(typeof e?.stopKernel!="function"){an(r("当前环境不支持订阅(桥接方法缺失)"),"err");return}if(!Ft.pending){wn({pending:!0});try{const t=await e.stopKernel();t&&Ft.data&&wn({data:{...Ft.data,kernel:t}});for(let o=0;o<10;o+=1){const c=await e.getKernelStatus?.();if(c&&Ft.data&&wn({data:{...Ft.data,kernel:c}}),c&&c.running===!1)break;await new Promise(d=>setTimeout(d,500))}const a=Ft.data?.kernel;if(a?.running===!1)an(r("内核已关闭(订阅与端口注册表保留,「启动内核」后原位恢复)"));else{const o=a?.lastError||r("内核没有在超时内停下来");an(r("关闭内核失败:{reason}",{reason:o}),"err")}Ml(!0)}catch(t){an(r("关闭内核失败:{reason}",{reason:wr(t)}),"err"),Ml(!0)}finally{wn({pending:!1})}}}async function $q(){const e=nr().workbuddyDesktop;if(typeof e?.removeKernel!="function"){an(r("当前环境不支持订阅(桥接方法缺失)"),"err");return}const t=Su()?.version;if(!await window.wbConfirm?.ask?.({title:r("删除内核"),html:r("确定删除已下载的内核{version}?内核文件与端口映射会被移除,订阅节点会变成「未分配端口」,引用它们的账号会暂时回退直连;订阅本身保留,重新下载内核后会重新分配端口。",{version:t?`(${t})`:""}),okText:r("删除内核"),okClass:"danger"})||Ft.pending)return;wn({pending:!0});const o=Su()?.lastError||"";try{const c=await e.removeKernel();c&&Ft.data&&wn({data:{...Ft.data,kernel:c}});for(let f=0;f<20;f+=1){const p=await e.getKernelStatus?.();if(p&&Ft.data&&wn({data:{...Ft.data,kernel:p}}),p&&p.installed===!1||p?.lastError&&p.lastError!==o)break;await new Promise(h=>setTimeout(h,500))}const d=Ft.data?.kernel;if(d?.installed===!1)an(r("已删除内核(订阅与账号引用保留,重新下载后会重新分配端口)")),Ao();else{const f=d?.lastError&&d.lastError!==o?d.lastError:r("内核目录没能删掉(可能仍被进程占用),稍后重试一次");an(r("删除内核失败:{reason}",{reason:f}),"err")}Ml(!0)}catch(c){an(r("删除内核失败:{reason}",{reason:wr(c)}),"err"),Ml(!0)}finally{wn({pending:!1})}}async function qq(e){const t=nr().workbuddyDesktop;if(typeof t?.decodeQrImage!="function")throw new Error(r("当前环境不支持订阅(桥接方法缺失)"));const a=await new Promise((d,f)=>{const p=new FileReader;p.onload=()=>d(String(p.result||"")),p.onerror=()=>f(new Error(r("图片读取失败"))),p.readAsDataURL(e)}),c=(await t.decodeQrImage({imageBase64:a}))?.url;if(!c)throw new Error(r("二维码里没有订阅链接"));return c}function hO(e){return new Promise((t,a)=>{const o=new FileReader;o.onload=()=>t(String(o.result||"")),o.onerror=()=>a(new Error(r("文件读取失败"))),o.readAsDataURL(e)})}const Nu="max-w-full flex-wrap [&_[data-slot=segmented-item]]:h-7 [&_[data-slot=segmented-item]]:px-3 [&_[data-slot=segmented-item]]:text-[12.5px]",Gq=r("登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)");let qj=!1;async function ku(e,t){if(!qj){qj=!0,e(!0);try{await t()}finally{qj=!1,e(!1)}}}function Ro({html:e,text:t}){return e?s.jsx("p",{dangerouslySetInnerHTML:{__html:e}}):s.jsx("p",{children:t||""})}function Kq(e,t,a){let o;try{o=JSON.parse(t)}catch(c){return Ln(r("{name} 不是合法 JSON:{reason}",{name:e.label,reason:ko(c)}),"err"),!1}return!o||typeof o!="object"||Array.isArray(o)?(Ln(r("{name}要粘一个 JSON 对象(形如 {sample})",{name:e.label,sample:'{"codearts_provider_credential":{…}}'}),"err"),!1):(Object.assign(a,o),!0)}function Yq({config:e,region:t,visible:a}){const o=e.provider,[c,d]=x.useState(!1),[f,p]=x.useState(""),h=uq(e),b=e.fields.map(v=>gg(e,v));async function y(){const v={provider:e.provider};e.regionOptions?.length&&(v.mode=t);for(const j of e.fields){const w=dr(gg(e,j));if(!j.optional&&!w){Ln(r("请填写 {label}",{label:j.label}),"err");return}if(w){if(j.jsonExpand){if(!Kq(j,w,v))return;continue}v[j.key]=w}}await ku(d,async()=>{try{const j=await vu(v);Lj(b),p(""),await Co(Pf(j?.account),e.label)}catch(j){Ln(r("添加失败:{reason}",{reason:ko(j)}),"err")}})}return s.jsxs(dn,{hidden:!a,onClick:v=>{v.target.closest("[data-raccoon-hint]")&&(v.preventDefault(),p(Gq))},children:[s.jsx("h3",{children:cq(e)}),s.jsx(Ro,{...h}),e.fields.map(v=>{const j=gg(e,v),w=v.optional?"":r("(必填)");return s.jsxs("div",{className:`field-row${v.rows?" stack":""}`,children:[s.jsxs("label",{htmlFor:j,children:[v.label,w]}),v.rows?s.jsx(Mi,{id:j,rows:v.rows,placeholder:v.placeholder,..._r(j)}):s.jsx(Fe,{id:j,type:"text",maxLength:$8(v),placeholder:v.placeholder,..._r(j)})]},j)}),s.jsxs("div",{className:"field-row",children:[s.jsx(ne,{id:`${o}-add-button`,onClick:()=>{y()},disabled:c,children:c?r("添加中…"):dq(e)}),s.jsx("span",{className:"detail",id:`${o}-add-hint`,children:f})]})]})}function Xq({config:e,visible:t}){const a=e.provider,[o,c]=x.useState(!1);if(!tO(e)||!e.desktopNote)return null;async function d(){await ku(c,async()=>{try{const f=await vu({provider:e.provider,importDesktop:!0});await Co(f?.account?.name||"",e.label)}catch(f){Ln(r("导入失败:{reason}",{reason:ko(f)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("从本机导入桌面端登录态")}),s.jsx("p",{children:e.desktopNote}),s.jsx("div",{className:"field-row",children:s.jsx(ne,{id:`${a}-desktop-button`,title:e.desktopHint,onClick:()=>{d()},disabled:o,children:r(o?"导入中…":"从本机导入桌面端登录态")})})]})}function Qq({config:e,visible:t}){const a=e.guestLogin,[o,c]=x.useState(!1);if(!a)return null;const d=gg(e,{key:"name"});async function f(){await ku(c,async()=>{const h=document.getElementById(d)?.value.trim()||"";try{const b=await vu({provider:e.provider,guest:!0,...h?{name:h}:{}});await Co(b?.account?.name||"",e.label)}catch(b){Ln(r("添加失败:{reason}",{reason:ko(b)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("访客模式")}),a.noteHtml?s.jsx(Ro,{html:a.noteHtml}):null,s.jsxs("div",{className:"form-field",children:[s.jsx("label",{htmlFor:d,children:r("备注名")}),s.jsx("input",{id:d,type:"text",maxLength:zj,placeholder:a.namePlaceholder||r("可选"),..._r(d)})]}),s.jsx("div",{className:"field-row",children:s.jsx(ne,{id:`${e.provider}-guest-button`,onClick:()=>{f()},disabled:o,children:o?a.busyText||r("正在添加…"):a.button})})]})}function Zq(e){const t=e.indexOf(",");return t>=0?e.slice(t+1):e}function Wq({config:e,visible:t}){const[a,o]=x.useState(!1),[c,d]=x.useState(""),f=x.useRef(null),p=e.fileImport,h=`${e.provider}-file-name`;if(!p)return null;async function b(y){const v=e.fileImport;v&&await ku(o,async()=>{try{const j=dr(h),w={provider:e.provider,authFileName:y.name};if(v.binary)w.authFileB64=Zq(await hO(y));else{const N=await y.text();let k;try{k=JSON.parse(N)}catch{Ln(r("选择的文件不是合法 JSON"),"err");return}if(!k||typeof k!="object"||Array.isArray(k)){Ln(r("不是有效的凭证文件:内容要是一个 JSON 对象"),"err");return}w.authFileContent=N}j&&(w.name=j);const S=await vu(w);d(""),await Co(Pf(S?.account),e.label)}catch(j){Ln(r("导入失败:{reason}",{reason:ko(j)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("导入凭证文件")}),s.jsx(Ro,{text:p.note}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{className:"lb-inline",htmlFor:h,children:r("备注名")}),s.jsx(Fe,{id:h,type:"text",maxLength:zj,placeholder:r("可选,留空则用文件里的昵称"),..._r(h)})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("input",{ref:f,type:"file",accept:p.accept,hidden:!0,onChange:y=>{const v=y.target.files?.[0];y.target.value="",v&&(d(v.name),b(v))}}),s.jsx(ne,{onClick:()=>f.current?.click(),disabled:a,children:r(a?"导入中…":"选择凭证文件导入")}),s.jsx("span",{className:"detail",children:c})]})]})}function Jq({config:e,mode:t,onModeChange:a,region:o,visible:c}){const d=e.webLogin,f=e.provider,p=x.useRef(t),h=x.useRef(o),b=x.useRef(null);return p.current=t,h.current=o,x.useEffect(()=>{const y=gt().wbWebLogin;if(!y||!d)return;const v=d.modes;b.current=y.create({provider:f,buttonId:`${f}-web-button`,cancelId:`${f}-web-cancel`,hintId:`${f}-web-hint`,busyText:d.busyText,texts:()=>{const j=v?.find(w=>w.value===p.current);return{button:d.button,hint:j?.hint||d.hint||""}},start:()=>gt().workbuddyDesktop?.startLogin(d.edition||h.current||"cn",p.current||"embedded",f),onSuccess:async j=>{_j(),await gt().wbApp?.refresh?.();const w=j?.payload?.warning;w?Ln(r("账号已添加,但请留意:{warning}",{warning:w}),"err"):Ln(r("✅ {label}账号已添加",{label:e.label}))}})??null},[]),x.useEffect(()=>{b.current?.syncTexts()},[t]),d?s.jsxs(dn,{hidden:!c,children:[s.jsx("h3",{children:r("网页登录")}),s.jsx(Ro,{html:d.noteHtml}),d.modes?.length?s.jsxs("div",{className:"flex flex-col gap-2.5 border-l-2 border-border pl-[11px]",children:[s.jsx("span",{className:"text-[12.5px] text-subtle",children:r("打开方式")}),s.jsx(En,{"aria-label":r("{label} 网页登录的打开方式",{label:e.label}),options:d.modes,value:t,onValueChange:a})]}):null,s.jsxs("div",{className:"field-row",children:[s.jsx(ne,{id:`${f}-web-button`,onClick:()=>b.current?.start(),children:d.button}),s.jsx(ne,{id:`${f}-web-cancel`,variant:"outline",hidden:!0,onClick:()=>b.current?.cancel(),children:r("取消等待")}),s.jsx("span",{className:"detail",id:`${f}-web-hint`,children:d.hint||d.modes?.[0]?.hint||""})]})]}):null}function eG({config:e,visible:t}){const a=e.smsLogin,o=e.provider;return x.useEffect(()=>{a&>().wbSmsLogin?.create({provider:o,onSuccess:c=>Co(Pf(c?.account),e.label)})},[]),a?s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("手机验证码登录")}),s.jsx(Ro,{html:a.noteHtml,text:r("用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。")}),s.jsxs("div",{className:"sms-form",children:[s.jsxs("div",{className:"sms-field",children:[s.jsxs("label",{className:"lb",htmlFor:`${o}-sms-phone`,children:[r("手机号"),s.jsx("i",{className:"req",children:"*"})]}),s.jsxs(Di,{children:[s.jsx(Pi,{id:`${o}-sms-phone`,type:"text",maxLength:11,placeholder:r("11 位大陆手机号"),..._r(`${o}-sms-phone`)}),s.jsx(Ii,{align:"inline-end",children:s.jsx(O4,{id:`${o}-sms-send`,className:"text-primary-fg",children:r("获取验证码")})})]})]}),s.jsxs("div",{className:"sms-field",children:[s.jsxs("label",{className:"lb",htmlFor:`${o}-sms-code`,children:[r("验证码"),s.jsx("i",{className:"req",children:"*"})]}),s.jsxs("div",{className:"sms-pair",children:[s.jsx(Fe,{id:`${o}-sms-code`,className:"sms-code",type:"text",maxLength:6,placeholder:r("6 位数字")}),s.jsx("label",{className:"lb-inline",htmlFor:`${o}-sms-name`,children:r("备注名")}),s.jsx(Fe,{id:`${o}-sms-name`,className:"sms-name",type:"text",placeholder:r("可选,留空则用脱敏手机号"),..._r(`${o}-sms-name`)})]})]}),s.jsxs("div",{className:"sms-foot",children:[s.jsx(ne,{id:`${o}-sms-submit`,children:r("登录并添加")}),s.jsx("span",{className:"detail sms-hint",id:`${o}-sms-hint`})]})]})]}):null}function tG({config:e,mode:t,onModeChange:a,visible:o}){const c=e.oauthLogin,d=e.provider,f=x.useRef(t),p=x.useRef(null);f.current=t;const h=()=>c?.modes?.find(b=>b.value===f.current)?.hint||c?.hint||"";return x.useEffect(()=>{const b=gt().wbAutoclawOauth;!b||!c||(p.current=b.create({provider:d,mode:()=>f.current||"embedded",hint:h,cancelId:`${d}-oauth-cancel`,onSuccess:()=>Co("",e.label)})??null)},[]),x.useEffect(()=>{p.current?.syncTexts()},[t]),c?s.jsxs(dn,{hidden:!o,children:[s.jsx("h3",{children:c.title||r("网页登录")}),s.jsx(Ro,{html:c.noteHtml}),c.modes?.length?s.jsxs("div",{className:"flex flex-col gap-2.5 border-l-2 border-border pl-[11px]",children:[s.jsx("span",{className:"text-[12.5px] text-subtle",children:r("打开方式")}),s.jsx(En,{"aria-label":r("{label} 网页登录的打开方式",{label:e.label}),options:c.modes,value:t,onValueChange:a})]}):null,s.jsxs("div",{className:"field-row",children:[s.jsx(ne,{id:`${d}-oauth-zai`,children:r("使用 Zai 账号登录")}),s.jsx(ne,{id:`${d}-oauth-google`,variant:"outline",children:r("使用 Google 账号登录")}),s.jsx(ne,{id:`${d}-oauth-cancel`,variant:"outline",hidden:!0,children:r("取消")})]}),s.jsx("div",{className:"field-row",children:s.jsx("span",{className:"detail",id:`${d}-oauth-hint`,children:c.modes?.[0]?.hint||c.hint||""})})]}):null}function nG({config:e,active:t}){const a=e.regionOptions?.[0]?.value??"",[o,c]=x.useState(a),[d,f]=x.useState(()=>nO(e,a)[0]),[p,h]=x.useState(e.webLogin?.modes?.[0]?.value??""),[b,y]=x.useState(e.oauthLogin?.modes?.[0]?.value??""),v=nO(e,o),j=v.includes(d)?d:v[0],w=x.useMemo(()=>eO.filter(S=>v.includes(S.id)).map(S=>({value:S.id,label:S.label})),[v.join(",")]);return s.jsxs("div",{className:"add-provider-block",hidden:!t,children:[e.regionOptions?.length?s.jsxs(dn,{children:[s.jsx("h3",{children:r("地区")}),s.jsx(En,{"aria-label":r("{label} 账号地区",{label:e.label}),className:Nu,options:e.regionOptions,value:o,onValueChange:c})]}):null,s.jsxs(dn,{children:[s.jsx("h3",{children:r("添加方式")}),s.jsx(En,{"aria-label":r("{label} 账号的添加方式",{label:e.label}),className:Nu,options:w,value:j,onValueChange:S=>f(S)})]}),s.jsx(Qq,{config:e,visible:j==="guest"}),s.jsx(tG,{config:e,mode:b,onModeChange:y,visible:j==="oauth"}),s.jsx(eG,{config:e,visible:j==="sms"}),s.jsx(Jq,{config:e,mode:p,onModeChange:h,region:o,visible:j==="web"}),s.jsx(Yq,{config:e,region:o,visible:j==="manual"}),s.jsx(Wq,{config:e,visible:j==="file"}),s.jsx(Xq,{config:e,visible:j==="desktop"})]})}const sG=r("官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth"),wg="workbuddy-file-name";function Gj(e,t,a){const o=e[a],c=[];o&&typeof o=="object"&&!Array.isArray(o)&&c.push(o),c.push(e);for(const d of c)for(const f of t){const p=d[f];if(typeof p=="string"&&p.trim())return p.trim()}return""}function rG(e){const t=Gj(e,["domain"],"auth");return/workbuddy\.ai/i.test(t)?"intl":/workbuddy\.cn|codebuddy\.cn/i.test(t)?"cn":null}function aG({edition:e,visible:t}){const[a,o]=x.useState(!1),[c,d]=x.useState(""),f=x.useRef(null);async function p(h){await ku(o,async()=>{try{let b;try{b=JSON.parse(await h.text())}catch{Ln(r("选择的文件不是合法 JSON"),"err");return}if(!b||typeof b!="object"||Array.isArray(b)){Ln(r("不是有效的凭证文件:内容要是一个 JSON 对象"),"err");return}const y=b,v=Gj(y,["accessToken","token","access_token"],"auth"),j=Gj(y,["uid"],"account");if(!v||!j){Ln(r("不是有效的凭证文件:需要包含 accessToken 与 uid"),"err");return}const w=rG(y),S=w??e;w&&w!==e&&Ln(r("文件是{edition}凭证,已按该版本导入",{edition:r(w==="intl"?"国际版":"国内版")}),"warn");const N=dr(wg),k={...y,provider:Sg(S)};N&&(k.name=N);const A=await vu(k);d(""),await Co(Pf(A?.account),S==="intl"?"WorkBuddy AI":"WorkBuddy")}catch(b){Ln(r("导入失败:{reason}",{reason:ko(b)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("导入凭证文件")}),s.jsx(Ro,{text:r("选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。")}),s.jsx("p",{className:"detail",children:s.jsx("a",{href:"#",onClick:h=>{h.preventDefault(),d(sG)},children:r("凭证文件在哪?")})}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{className:"lb-inline",htmlFor:wg,children:r("备注名")}),s.jsx(Fe,{id:wg,type:"text",maxLength:100,placeholder:r("可选,留空则用文件里的昵称"),..._r(wg)})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("input",{ref:f,type:"file",accept:".info,.json,application/json",hidden:!0,onChange:h=>{const b=h.target.files?.[0];h.target.value="",b&&p(b)}}),s.jsx(ne,{onClick:()=>f.current?.click(),disabled:a,children:r(a?"导入中…":"选择凭证文件导入")}),s.jsx("span",{className:"detail",children:c})]})]})}function lG({edition:e,visible:t}){const[a,o]=x.useState(!1);async function c(){await ku(o,async()=>{try{const d=await vu({provider:Sg(e),importDesktop:!0});await Co(Pf(d?.account),e==="intl"?"WorkBuddy AI":"WorkBuddy")}catch(d){Ln(r("导入失败:{reason}",{reason:ko(d)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("从本机导入桌面端登录态")}),s.jsx(Ro,{text:r("读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。")}),s.jsx("div",{className:"field-row",children:s.jsx(ne,{onClick:()=>{c()},disabled:a,children:r(a?"导入中…":"从本机导入桌面端登录态")})})]})}function Sg(e){return e==="intl"?"workbuddy-intl":"workbuddy"}function oG({active:e}){const[t,a]=x.useState(qi.edition),[o,c]=x.useState(qi.loginMode),[d,f]=x.useState(qi.socialRestore),[p,h]=x.useState("web"),b=x.useRef(t),y=x.useRef(o),v=x.useRef(d),j=x.useRef(null);b.current=t,y.current=o,v.current=d,x.useEffect(()=>{const C=gt().wbWebLogin;C&&(j.current=C.create({get provider(){return Sg(b.current)},buttonId:"web-login-button",cancelId:"web-login-cancel",hintId:"web-login-hint",busyText:r("等待网页登录…"),texts:()=>{const E=y.current==="external";return{button:r(E?"在浏览器中打开登录页":"打开网页登录"),hint:r(E?"系统浏览器打开(复用已登录账号);完成后自动加入列表":"内嵌窗口打开;完成后自动加入列表,关窗即取消等待")}},start:()=>gt().workbuddyDesktop?.startLogin(b.current,y.current,Sg(b.current),v.current),onSuccess:async()=>{const E=b.current==="intl"?r("国际版"):r("国内版");_j(),await gt().wbApp?.refresh?.(),Ln(r("✅ 登录成功,{edition}账号已加入列表",{edition:E}))}})??null)},[]),x.useEffect(()=>{j.current?.syncTexts()},[t,o]);function w(C){const E=C==="intl"?"external":"embedded";a(C),qi.edition=C,c(E),qi.loginMode=E}function S(C){const E=C==="external"?"external":"embedded";c(E),qi.loginMode=E}const N=t==="intl",A=N&&o==="embedded",P=r(A?"国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口":N?"只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页":"国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)"),R=p==="desktop"&&Hj()==="web"?"web":p;return s.jsxs("div",{className:"add-provider-block",hidden:!e,children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("账号版本")}),s.jsx("p",{children:r("两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。")}),s.jsx(En,{"aria-label":r("账号版本"),className:Nu,options:[{value:"cn",label:r("国内版(WorkBuddy)")},{value:"intl",label:r("国际版(WorkBuddy AI)")}],value:t,onValueChange:C=>w(C)})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("添加方式")}),s.jsx(En,{"aria-label":r("{label} 账号的添加方式",{label:"WorkBuddy"}),className:Nu,options:[{value:"web",label:r("网页登录")},{value:"file",label:r("导入凭证文件")},...Hj()!=="web"?[{value:"desktop",label:r("导入桌面端登录态")}]:[]],value:R,onValueChange:C=>h(C)})]}),s.jsxs(dn,{hidden:R!=="web",children:[s.jsx("h3",{children:r("网页登录")}),s.jsx("p",{children:r("完成登录后自动加入账号列表,昵称取自上游。")}),s.jsxs("div",{className:"field-row",children:[s.jsx("span",{className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("打开方式")}),s.jsx(En,{"aria-label":r("网页登录的打开方式"),className:Nu,options:[{value:"embedded",label:r("内嵌窗口")},{value:"external",label:r("系统默认浏览器")}],value:o,onValueChange:S}),s.jsxs("label",{className:"flex items-center gap-2",title:P,children:[s.jsx(ns,{checked:d,disabled:!A,onCheckedChange:C=>{f(C),qi.socialRestore=C}}),s.jsx("span",{className:"text-[12.5px] text-subtle",children:r("恢复 Google / GitHub 入口")})]})]}),s.jsx("p",{children:r("系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。")}),s.jsxs("div",{className:"field-row",children:[s.jsx(ne,{id:"web-login-button",onClick:()=>j.current?.start(),children:r("打开网页登录")}),s.jsx(ne,{id:"web-login-cancel",variant:"outline",hidden:!0,onClick:()=>j.current?.cancel(),children:r("取消等待")}),s.jsx("span",{className:"detail",id:"web-login-hint",children:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待")})]})]}),s.jsx(aG,{edition:t,visible:R==="file"}),s.jsx(lG,{edition:t,visible:R==="desktop"})]})}const Kj="proxy",Yj="preset",Ng="custom",iG="import",zf="preset:",Xj="__new__";function cG(e){return e===Yj||e===Ng?e:Kj}const kg={workbuddy:"assets/providers/workbuddy.png","workbuddy-intl":"assets/providers/workbuddy.png",raccoon:"assets/providers/raccoon.png",catpaw:"assets/providers/catpaw.png",autoclaw:"assets/providers/autoclaw.png","autoclaw-intl":"assets/providers/autoclaw.png",qoder:"assets/providers/qoder.png","qoder-intl":"assets/providers/qoder.png","cline-free":"assets/providers/cline.png","cline-pass":"assets/providers/cline.png",accio:"assets/providers/accio.png","accio-cn":"assets/providers/accio.png",zcode:"assets/providers/zcode.png","zcode-intl":"assets/providers/zcode.png",codearts:"assets/providers/codearts.png",trae:"assets/providers/trae.png",loomy:"assets/providers/loomy.png",kuku:"assets/providers/kuku.png",monkeycode:"assets/providers/monkeycode.png","monkeycode-intl":"assets/providers/monkeycode.png",commandcode:"assets/providers/commandcode.png",antigravity:"assets/providers/antigravity.png",officeace:"assets/providers/officeace.png",orcaterm:"assets/providers/orcaterm.png",chatglm:"assets/providers/chatglm.png"},uG=new Set(["cline-pass"]);function dG(e){const t=gt().wbProviders;if(e===Yj)return(gt().wbPresetProviders?.list||[]).map(h=>{const b=KR(h);return{id:zf+h.key,label:h.name,count:b?Pj(b.id):0,preset:!0,builtId:b?.id||""}});if(e===Ng)return(t?.customList?.()||[]).filter(h=>!V8(h)).map(h=>({id:h.id,label:h.name||h.id,count:Pj(h.id),custom:!0}));const a=(t?.all?.()||[]).filter(h=>!uG.has(String(h?.id||""))),o=(h,b)=>h===Gi?Bj:r(gt().wbProviders?.labelOf?.(h)||b),d=(a.length?a.map(h=>{const b=String(h.id||"");return{id:b,label:o(b,String(h.label||h.id||"")),count:Number(h.count)||0}}):[{id:Gi,label:Bj,count:Pj(Gi)}]).filter(h=>h.id!=="workbuddy-intl"),f=d.findIndex(h=>h.id==="autoclaw-intl"),p=d.findIndex(h=>h.id==="autoclaw");return p>=0&&f>p&&d.splice(p+1,0,d.splice(f,1)[0]),d}function fG({item:e}){const t=e.id.startsWith(zf)?gt().wbPresetProviders?.iconOf?.(e.id.slice(zf.length))||"":kg[e.id];if(t)return s.jsx("span",{className:"add-provider-logo has-icon",children:s.jsx("img",{src:t,alt:"",loading:"lazy"})});const a=String(e.label||"?").trim().slice(0,1).toUpperCase()||"?";return s.jsx("span",{className:"add-provider-logo",children:a})}function pG(e){return e.preset?e.builtId?e.count?r("已建过 · {n} 个账号,点击继续添加",{n:e.count}):r("已建过,点击继续添加账号"):r("点开即预填,填 Key 接入"):e.custom?e.count?r("{n} 个账号,点击添加",{n:e.count}):r("点击添加账号"):e.count?r("{n} 个账号",{n:e.count}):r("还没有账号")}function mG({item:e,onPick:t}){return s.jsxs("button",{type:"button",className:"add-provider-card","data-provider":e.id,role:"option",onClick:()=>t(e.id),children:[s.jsx(fG,{item:e}),s.jsxs("span",{className:"add-provider-info",children:[s.jsx("span",{className:"add-provider-name",children:e.label}),s.jsx("span",{className:"add-provider-meta",children:pG(e)})]}),s.jsx("span",{className:"add-provider-go",children:"›"})]})}function hG({onPick:e}){return s.jsxs("button",{type:"button",className:"add-provider-card is-new","data-provider":Xj,role:"option",onClick:()=>e(Xj),children:[s.jsx("span",{className:"add-provider-logo is-new",children:"+"}),s.jsxs("span",{className:"add-provider-info",children:[s.jsx("span",{className:"add-provider-name",children:r("新建自定义提供商")}),s.jsx("span",{className:"add-provider-meta",children:r("接入一个兼容上游")})]}),s.jsx("span",{className:"add-provider-go",children:"›"})]})}function gG({accountType:e,onAccountTypeChange:t,search:a,onSearchChange:o,onPick:c,version:d,importing:f,importPanel:p}){const h=x.useMemo(()=>dG(e),[e,d]),b=a.trim().toLowerCase(),y=h.filter(j=>!b||j.label.toLowerCase().includes(b)),v=e===Ng&&!b;return s.jsxs(dn,{children:[s.jsx("h3",{children:r("选择提供商")}),s.jsxs("div",{className:"add-pick-row",style:f?{display:"none"}:void 0,children:[s.jsx(En,{"aria-label":r("账号类型"),className:Nu,options:[{value:Kj,label:"Agent"},{value:Yj,label:r("预置 API")},{value:Ng,label:r("自定义")}],value:e,onValueChange:j=>t(cG(j))}),s.jsx("span",{id:"add-search-wrap",className:"add-provider-search ml-auto max-w-[340px] min-w-0 flex-[1_1_200px]",children:s.jsxs(Di,{children:[s.jsx(Ii,{children:"⌕"}),s.jsx(Pi,{id:"add-provider-search",type:"search",placeholder:r("搜索提供商…"),autoComplete:"off","aria-label":r("搜索提供商"),value:a,onChange:j=>o(j.currentTarget.value)})]})})]}),p,s.jsxs("div",{className:"add-provider-grid",id:"add-provider-grid",role:"listbox","aria-label":r("选择要添加账号的提供商"),style:f?{display:"none"}:void 0,children:[v?s.jsx(hG,{onPick:c}):null,y.map(j=>s.jsx(mG,{item:j,onPick:c},j.id)),!y.length&&b?s.jsx("div",{className:"add-provider-empty",children:r("没有匹配「{keyword}」的提供商",{keyword:a.trim()})}):null]})]})}function Cg(e,t){return Pe().wbIcons?.icon?.(e,t)||""}function xG({account:e,rank:t}){const a=r("组内第 {rank} 位",{rank:t});return s.jsxs("div",{className:"order-cell",children:[s.jsx("span",{className:"order-grip",role:"button",tabIndex:-1,"aria-label":r("拖动调整组内顺序"),title:r("按住拖动,调整这个账号在本组内的顺序"),dangerouslySetInnerHTML:{__html:Cg("gripVertical",14)}}),s.jsx("span",{className:"order-rank",title:a,children:`#${t}`})]})}function bG({group:e,ids:t,collapsed:a}){const[o,c]=x.useState(!1),d="w-full justify-start px-2 font-normal";return s.jsxs(wf,{open:o,onOpenChange:c,children:[s.jsx(Kh,{render:s.jsx("button",{type:"button",className:"grp-iconbtn",title:r("本组操作")}),children:"⋯"}),s.jsx(Sf,{align:"end",sideOffset:4,className:"w-[196px] p-1.5",children:s.jsxs("div",{className:"flex flex-col gap-0.5",children:[s.jsx(ne,{variant:"ghost",size:"sm",className:d,title:r("启用这一组里的全部账号(含被筛选隐藏的)"),onClick:()=>{c(!1),ER(t,!0)},children:r("全部启用({n})",{n:t.length})}),s.jsx(ne,{variant:"ghost",size:"sm",className:d,title:r("禁用这一组里的全部账号(含被筛选隐藏的)"),onClick:()=>{c(!1),ER(t,!1)},children:r("全部禁用({n})",{n:t.length})}),s.jsx(ne,{variant:"ghost",size:"sm",className:d,title:r("打开批量操作弹窗,并预选这一组的账号(改代理等动作在弹窗里挑参数)"),onClick:()=>{c(!1),kj(t,"proxy")},children:r("批量操作本组")}),s.jsx("div",{className:"my-1 h-px bg-hairline"}),s.jsx(ne,{variant:"ghost",size:"sm",className:d,onClick:()=>{c(!1),iR(e.provider)},children:r(a?"展开这一组":"折叠这一组")})]})})]})}function vG({group:e,collapsed:t,colSpan:a}){const o=kg[e.provider];return s.jsx("tr",{className:"grp-band","data-provider":e.provider,children:s.jsx("td",{colSpan:a,children:s.jsxs("div",{className:"grp-band-inner",children:[s.jsx("span",{className:"queue-grip",role:"button",tabIndex:-1,"aria-label":r("拖动调整整组顺序"),title:r("按住拖动,调整这一家的组顺位(整组一起动)"),dangerouslySetInnerHTML:{__html:Cg("gripVertical",14)}}),s.jsx("span",{className:"grp-rank",title:r("组顺位:越小越先用(拖动分组带调整)"),children:r("第 {rank} 顺位",{rank:e.rank})}),s.jsx("span",{className:"grp-logo",children:o?s.jsx("img",{src:o,alt:"",loading:"lazy"}):s.jsx("span",{className:"grp-logo-txt",children:String(e.label||"?").trim().slice(0,1).toUpperCase()})}),s.jsx("span",{className:"grp-name",children:r(e.label)}),s.jsx("span",{className:"grp-stat",children:r("{total} 个账号 · 启用 {enabled} · 禁用 {disabled}{limited}",{total:e.members.length,enabled:e.enabled,disabled:e.disabled,limited:e.limited>0?r(" · 限流 {n}",{n:e.limited}):""})}),s.jsx("span",{className:"grp-spacer"}),s.jsx("button",{type:"button",className:"grp-iconbtn grp-fold","aria-expanded":!t,title:r(t?"展开这一组":"折叠这一组"),onClick:()=>iR(e.provider),dangerouslySetInnerHTML:{__html:Cg("chevronDown",14)}}),s.jsx(bG,{group:e,ids:e.accounts.map(c=>c.id),collapsed:t})]})})})}function yG({account:e}){const t=ur(e),a=j$(e);!t&&d$(e,Rl(e))&&a.push({text:r("Token 限额 · 已禁用"),kind:"bad",title:r("本周期 Token 消耗达到限制器的上限,账号已被自动禁用(窗口重置也不恢复,需手动启用)")});const o=hu(e)||e.id;return s.jsxs(s.Fragment,{children:[s.jsx(ns,{checked:t,"aria-label":r("{action}{who}",{action:r(t?"禁用":"启用"),who:o}),title:r(t?"已启用,点击禁用(不参与转发)":"已禁用,点击启用"),onCheckedChange:c=>{CR(e.id,c)}}),a.length?s.jsx("div",{className:"status-tags",children:a.map(c=>s.jsx(ze,{shape:"tag",variant:c.kind==="bad"?"destructive":"secondary",title:c.title,children:c.text},c.text))}):null]})}function jG({account:e,open:t}){const a=bj(e);if(!a.length)return Qh(e,Wa(e))?s.jsx(ze,{variant:"warning",shape:"tag",title:r("余额低于限制器的阈值,转发时会跳过该账号(余额回升自动恢复)"),children:r("余额不足")}):fj(e,Rl(e))?s.jsx(ze,{variant:"warning",shape:"tag",title:r("本周期 Token 消耗达到限制器的上限,转发时会跳过该账号(窗口重置自动恢复)"),children:r("Token 限额")}):s.jsxs(ze,{variant:"success",shape:"tag",title:r("当前没有任何模型处于限流中"),children:[s.jsx(my,{}),r("正常")]});const o=jj(a[0].resetAt);return s.jsxs(s.Fragment,{children:[s.jsx(ze,{variant:"warning",shape:"tag",render:s.jsx("button",{type:"button"}),className:t?"ring-2 ring-warning-soft":void 0,title:r("点击{action}各模型的限流明细",{action:r(t?"收起":"查看")}),onClick:()=>dR(e.id,"limits",!t),children:r("{n} 个模型 ▾",{n:a.length})}),s.jsx("span",{className:"lim-sub",title:r("最早恢复"),children:r("最早 {soonest} 恢复",{soonest:o===yj?r("待定"):o})})]})}function wG({account:e}){const t=cr(An(e)),a=MA(t.edition?e.expiresAt:e[t.expiry]);if(!a)return s.jsx("span",{className:"muted",title:r("记录里没有过期时间"),children:"—"});const o=a-Date.now();if(o<=0)return s.jsx(ze,{variant:"destructive",shape:"tag",title:r("凭证已过期,转发时会先刷新"),children:r("已过期")});const c=o<36e5?r("{n} 分钟后",{n:Math.max(1,Math.round(o/6e4))}):o<48*36e5?r("{n} 小时后",{n:(o/36e5).toFixed(1)}):r("{n} 天后",{n:Math.floor(o/24/36e5)}),d=Ls(a);return s.jsx("span",{title:d?r("{text}过期({full})",{text:c,full:d}):r("{text}过期",{text:c}),children:c})}function SG({account:e}){const t=xR(e.id);return t<=0?null:s.jsx("span",{className:"conn-count",title:r("{n} 个请求正在使用该账号(含还在下发内容的流式请求)",{n:t}),children:t})}function NG(e){return!e||typeof e!="object"||Array.isArray(e)?"":gO(e.subscription)}function gO(e){if(!e||typeof e!="object")return"";const t=e,a=[];t.planName&&a.push(r("套餐 {name}",{name:String(t.planName)})),t.status&&a.push(r("状态 {status}",{status:String(t.status)})),t.state&&String(t.state)!=="active"&&a.push(qA(t.state));const o=t.expireAt;if(o!=null&&o!==""){const c=Number(o),d=Number.isFinite(c)&&c>1e11?Ls(c):String(o);d&&a.push(r("到期 {time}",{time:d}))}return Number.isFinite(Number(t.remainQuota))&&a.push(r("余量 {value}",{value:ss(t.remainQuota)})),Number.isFinite(Number(t.totalQuota))&&a.push(r("总量 {value}",{value:ss(t.totalQuota)})),a.join(" ")}function kG(e){if(!e||typeof e!="object"||Array.isArray(e))return[];const t=e.plans;return Array.isArray(t)?t.filter(a=>a&&typeof a=="object"&&String(a.state||"")==="pending"):[]}function CG(e){const t=e.map(a=>{const o=String(a.name||a.planId||r("套餐")),c=Number(a.pendingUntil??a.startsAt);return Number.isFinite(c)&&c>0?r("{name}({time} 起生效)",{name:o,time:Ls(c*1e3)}):o});return r(`已领到、还没到生效时间的套餐(生效后余额列会按它显示): +`+u.stack}}var Kn=Object.prototype.hasOwnProperty,ms=e.unstable_scheduleCallback,Yn=e.unstable_cancelCallback,vs=e.unstable_shouldYield,it=e.unstable_requestPaint,$t=e.unstable_now,Vn=e.unstable_getCurrentPriorityLevel,rn=e.unstable_ImmediatePriority,nt=e.unstable_UserBlockingPriority,Dt=e.unstable_NormalPriority,qt=e.unstable_LowPriority,ts=e.unstable_IdlePriority,Fn=e.log,$n=e.unstable_setDisableYieldValue,Dn=null,en=null;function cs(n){if(typeof Fn=="function"&&$n(n),en&&typeof en.setStrictMode=="function")try{en.setStrictMode(Dn,n)}catch{}}var Et=Math.clz32?Math.clz32:wt,xt=Math.log,jt=Math.LN2;function wt(n){return n>>>=0,n===0?32:31-(xt(n)/jt|0)|0}var Er=256,ar=262144,Fr=4194304;function Nn(n){var l=n&42;if(l!==0)return l;switch(n&-n){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return n&-n;case 262144:case 524288:case 1048576:case 2097152:return n&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return n&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return n}}function al(n,l,i){var u=n.pendingLanes;if(u===0)return 0;var m=0,g=n.suspendedLanes,A=n.pingedLanes;n=n.warmLanes;var V=u&134217727;return V!==0?(u=V&~g,u!==0?m=Nn(u):(A&=V,A!==0?m=Nn(A):i||(i=V&~n,i!==0&&(m=Nn(i))))):(V=u&~g,V!==0?m=Nn(V):A!==0?m=Nn(A):i||(i=u&~n,i!==0&&(m=Nn(i)))),m===0?0:l!==0&&l!==m&&(l&g)===0&&(g=m&-m,i=l&-l,g>=i||g===32&&(i&4194048)!==0)?l:m}function ln(n,l){return(n.pendingLanes&~(n.suspendedLanes&~n.pingedLanes)&l)===0}function gc(n,l){(l&8)!==0&&(l|=l&32);var i=n.entangledLanes;if(i!==0)for(n=n.entanglements,i&=l;0i;i++)l.push(n);return l}function Go(n,l){n.pendingLanes|=l,l!==268435456&&(n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0)}function Ko(n,l,i,u,m,g){var A=n.pendingLanes;n.pendingLanes=i,n.suspendedLanes=0,n.pingedLanes=0,n.warmLanes=0,n.expiredLanes&=i,n.entangledLanes&=i,n.errorRecoveryDisabledLanes&=i,n.shellSuspendCounter=0;var V=n.entanglements,se=n.expirationTimes,xe=n.hiddenUpdates;for(i=A&~i;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Qt=!1;if(lt)try{var In={};Object.defineProperty(In,"passive",{get:function(){Qt=!0}}),window.addEventListener("test",In,In),window.removeEventListener("test",In,In)}catch{Qt=!1}var gn=null,Pn=null,hs=null;function Ar(){if(hs)return hs;var n,l=Pn,i=l.length,u,m="value"in gn?gn.value:gn.textContent,g=m.length;for(n=0;n=nm),u_=" ",d_=!1;function f_(n,l){switch(n){case"keyup":return one.indexOf(l.keyCode)!==-1;case"keydown":return l.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function p_(n){return n=n.detail,typeof n=="object"&&"data"in n?n.data:null}var pd=!1;function cne(n,l){switch(n){case"compositionend":return p_(l);case"keypress":return l.which!==32?null:(d_=!0,u_);case"textInput":return n=l.data,n===u_&&d_?null:n;default:return null}}function une(n,l){if(pd)return n==="compositionend"||!aN&&f_(n,l)?(n=Ar(),hs=Pn=gn=null,pd=!1,n):null;switch(n){case"paste":return null;case"keypress":if(!(l.ctrlKey||l.altKey||l.metaKey)||l.ctrlKey&&l.altKey){if(l.char&&1"u")return null;try{return n.activeElement||n.body}catch{return n.body}}function j_(n){for(;n&&n.firstChild;)n=n.firstChild;return n}function w_(n,l){var i=j_(n);n=0;for(var u;i;){if(i.nodeType===3){if(u=n+i.textContent.length,n<=l&&u>=l)return{node:i,offset:l-n};n=u}e:{for(;i;){if(i.nextSibling){i=i.nextSibling;break e}i=i.parentNode}i=void 0}i=j_(i)}}function S_(n,l){return n&&l?n===l?!0:n&&n.nodeType===3?!1:l&&l.nodeType===3?S_(n,l.parentNode):"contains"in n?n.contains(l):n.compareDocumentPosition?!!(n.compareDocumentPosition(l)&16):!1:!1}function N_(n){n=n!=null&&n.ownerDocument!=null&&n.ownerDocument.defaultView!=null?n.ownerDocument.defaultView:window;for(var l=iN(n.document);l instanceof n.HTMLIFrameElement;){try{var i=typeof l.contentWindow.location.href=="string"}catch{i=!1}if(i)n=l.contentWindow;else break;l=iN(n.document)}return l}function cN(n){var l=n&&n.nodeName&&n.nodeName.toLowerCase();return l&&(l==="input"&&(n.type==="text"||n.type==="search"||n.type==="tel"||n.type==="url"||n.type==="password")||l==="textarea"||n.contentEditable==="true")}var bne=lt&&"documentMode"in document&&11>=document.documentMode,md=null,uN=null,lm=null,dN=!1;function k_(n,l,i){var u=i.window===i?i.document:i.nodeType===9?i:i.ownerDocument;dN||md==null||md!==iN(u)||(u=md,"selectionStart"in u&&cN(u)?u={start:u.selectionStart,end:u.selectionEnd}:(u=(u.ownerDocument&&u.ownerDocument.defaultView||window).getSelection(),u={anchorNode:u.anchorNode,anchorOffset:u.anchorOffset,focusNode:u.focusNode,focusOffset:u.focusOffset}),lm&&am(lm,u)||(lm=u,u=mv(uN,"onSelect"),0>=A,m-=A,ol=1<<32-Et(l)+m|i<rt?(Ns=st,st=null):Ns=st.sibling;var Zt=fe(ge,st,ye[rt],Ee);if(Zt===null){st===null&&(st=Ns);break}n&&st&&Zt.alternate===null&&l(ge,st),ie=g(Zt,ie,rt),Ht===null?Ke=Zt:Ht.sibling=Zt,Ht=Zt,st=Ns}if(rt===ye.length)return i(ge,st),At&&Xl(ge,rt),Ke;if(st===null){for(;rtrt?(Ns=st,st=null):Ns=st.sibling;var wi=fe(ge,st,Zt.value,Ee);if(wi===null){st===null&&(st=Ns);break}n&&st&&wi.alternate===null&&l(ge,st),ie=g(wi,ie,rt),Ht===null?Ke=wi:Ht.sibling=wi,Ht=wi,st=Ns}if(Zt.done)return i(ge,st),At&&Xl(ge,rt),Ke;if(st===null){for(;!Zt.done;rt++,Zt=ye.next())Zt=Re(ge,Zt.value,Ee),Zt!==null&&(ie=g(Zt,ie,rt),Ht===null?Ke=Zt:Ht.sibling=Zt,Ht=Zt);return At&&Xl(ge,rt),Ke}for(st=u(st);!Zt.done;rt++,Zt=ye.next())Zt=je(st,ge,rt,Zt.value,Ee),Zt!==null&&(n&&(Ns=Zt.alternate,Ns!==null&&st.delete(Ns.key===null?rt:Ns.key)),ie=g(Zt,ie,rt),Ht===null?Ke=Zt:Ht.sibling=Zt,Ht=Zt);return n&&st.forEach(function(cre){return l(ge,cre)}),At&&Xl(ge,rt),Ke}function vt(ge,ie,ye,Ee){if(typeof ye=="object"&&ye!==null&&ye.type===H&&ye.key===null&&ye.props.ref===void 0&&(ye=ye.props.children),typeof ye=="object"&&ye!==null){switch(ye.$$typeof){case _:e:{for(var Ke=ye.key;ie!==null;){if(ie.key===Ke){if(Ke=ye.type,Ke===H){if(ie.tag===7){i(ge,ie.sibling),Ee=m(ie,ye.props.children),si(Ee,ye),Ee.return=ge,ge=Ee;break e}}else if(ie.elementType===Ke||typeof Ke=="object"&&Ke!==null&&Ke.$$typeof===G&&Lc(Ke)===ie.type){i(ge,ie.sibling),Ee=m(ie,ye.props),si(Ee,ye),Ee.return=ge,ge=Ee;break e}i(ge,ie);break}else l(ge,ie);ie=ie.sibling}ye.type===H?(Ee=Rc(ye.props.children,ge.mode,Ee,ye.key),si(Ee,ye),Ee.return=ge,ge=Ee):(Ee=vb(ye.type,ye.key,ye.props,null,ge.mode,Ee),si(Ee,ye),Ee.return=ge,ge=Ee)}return A(ge);case z:e:{for(Ke=ye.key;ie!==null;){if(ie.key===Ke)if(ie.tag===4&&ie.stateNode.containerInfo===ye.containerInfo&&ie.stateNode.implementation===ye.implementation){i(ge,ie.sibling),Ee=m(ie,ye.children||[]),Ee.return=ge,ge=Ee;break e}else{i(ge,ie);break}else l(ge,ie);ie=ie.sibling}Ee=bN(ye,ge.mode,Ee),Ee.return=ge,ge=Ee}return A(ge);case G:return ye=Lc(ye),vt(ge,ie,ye,Ee)}if(ue(ye))return He(ge,ie,ye,Ee);if(ae(ye)){if(Ke=ae(ye),typeof Ke!="function")throw Error(o(150));return ye=Ke.call(ye),We(ge,ie,ye,Ee)}if(typeof ye.then=="function")return vt(ge,ie,Ab(ye),Ee);if(ye.$$typeof===$)return vt(ge,ie,kb(ge,ye),Ee);Rb(ge,ye)}return typeof ye=="string"&&ye!==""||typeof ye=="number"||typeof ye=="bigint"?(ye=""+ye,ie!==null&&ie.tag===6?(i(ge,ie.sibling),Ee=m(ie,ye),Ee.return=ge,ge=Ee):(i(ge,ie),Ee=xN(ye,ge.mode,Ee),Ee.return=ge,ge=Ee),A(ge)):i(ge,ie)}return function(ge,ie,ye,Ee){try{fm=0;var Ke=vt(ge,ie,ye,Ee);return Sd=null,Ke}catch(st){if(st===wd||st===Tb)throw st;var Ht=Rr(29,st,null,ge.mode);return Ht.lanes=Ee,Ht.return=ge,Ht}}}var Bc=X_(!0),Q_=X_(!1),ri=!1;function EN(n){n.updateQueue={baseState:n.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function AN(n,l){n=n.updateQueue,l.updateQueue===n&&(l.updateQueue={baseState:n.baseState,firstBaseUpdate:n.firstBaseUpdate,lastBaseUpdate:n.lastBaseUpdate,shared:n.shared,callbacks:null})}function ai(n){return{lane:n,tag:0,payload:null,callback:null,next:null}}function li(n,l,i){var u=n.updateQueue;if(u===null)return null;if(u=u.shared,(on&2)!==0){var m=u.pending;return m===null?l.next=l:(l.next=m.next,m.next=l),u.pending=l,l=bb(n),D_(n,null,i),l}return xb(n,u,l,i),bb(n)}function pm(n,l,i){if(l=l.updateQueue,l!==null&&(l=l.shared,(i&4194048)!==0)){var u=l.lanes;u&=n.pendingLanes,i|=u,l.lanes=i,xc(n,i)}}function RN(n,l){var i=n.updateQueue,u=n.alternate;if(u!==null&&(u=u.updateQueue,i===u)){var m=null,g=null;if(i=i.firstBaseUpdate,i!==null){do{var A={lane:i.lane,tag:i.tag,payload:i.payload,callback:null,next:null};g===null?m=g=A:g=g.next=A,i=i.next}while(i!==null);g===null?m=g=l:g=g.next=l}else m=g=l;i={baseState:u.baseState,firstBaseUpdate:m,lastBaseUpdate:g,shared:u.shared,callbacks:u.callbacks},n.updateQueue=i;return}n=i.lastBaseUpdate,n===null?i.firstBaseUpdate=l:n.next=l,i.lastBaseUpdate=l}var ON=!1;function mm(){if(ON){var n=jd;if(n!==null)throw n}}function hm(n,l,i,u){ON=!1;var m=n.updateQueue;ri=!1;var g=m.firstBaseUpdate,A=m.lastBaseUpdate,V=m.shared.pending;if(V!==null){m.shared.pending=null;var se=V,xe=se.next;se.next=null,A===null?g=xe:A.next=xe,A=se;var we=n.alternate;we!==null&&(we=we.updateQueue,V=we.lastBaseUpdate,V!==A&&(V===null?we.firstBaseUpdate=xe:V.next=xe,we.lastBaseUpdate=se))}if(g!==null){var Re=m.baseState;A=0,we=xe=se=null,V=g;do{var fe=V.lane&-536870913,je=fe!==V.lane;if(je?(Bt&fe)===fe:(u&fe)===fe){fe!==0&&fe===Pc&&(ON=!0),we!==null&&(we=we.next={lane:0,tag:V.tag,payload:V.payload,callback:null,next:null});e:{var He=n,We=V;fe=l;var vt=i;switch(We.tag){case 1:if(He=We.payload,typeof He=="function"){Re=He.call(vt,Re,fe);break e}Re=He;break e;case 3:He.flags=He.flags&-65537|128;case 0:if(He=We.payload,fe=typeof He=="function"?He.call(vt,Re,fe):He,fe==null)break e;Re=I({},Re,fe);break e;case 2:ri=!0}}fe=V.callback,fe!==null&&(n.flags|=64,je&&(n.flags|=8192),je=m.callbacks,je===null?m.callbacks=[fe]:je.push(fe))}else je={lane:fe,tag:V.tag,payload:V.payload,callback:V.callback,next:null},we===null?(xe=we=je,se=Re):we=we.next=je,A|=fe;if(V=V.next,V===null){if(V=m.shared.pending,V===null)break;je=V,V=je.next,je.next=null,m.lastBaseUpdate=je,m.shared.pending=null}}while(!0);we===null&&(se=Re),m.baseState=se,m.firstBaseUpdate=xe,m.lastBaseUpdate=we,g===null&&(m.shared.lanes=0),pi|=A,n.lanes=A,n.memoizedState=Re}}function Z_(n,l){if(typeof n!="function")throw Error(o(191,n));n.call(l)}function W_(n,l){var i=n.callbacks;if(i!==null)for(n.callbacks=null,n=0;ng?g:8;var A=ve.T,V={};V.types=A!==null?A.types:null,ve.T=V,ZN(n,!1,l,i);try{var se=m(),xe=ve.S;if(xe!==null&&xe(V,se),se!==null&&typeof se=="object"&&typeof se.then=="function"){var we=Ane(se,u);vm(n,l,we,Jr(n))}else vm(n,l,u,Jr(n))}catch(Re){vm(n,l,{then:function(){},status:"rejected",reason:Re},Jr())}finally{ee.p=g,A!==null&&V.types!==null&&(A.types=V.types),ve.T=A}}function Pne(){}function XN(n,l,i,u){if(n.tag!==5)throw Error(o(476));var m=RL(n).queue;AL(n,m,l,he,i===null?Pne:function(){return OL(n),i(u)})}function RL(n){var l=n.memoizedState;if(l!==null)return l;l={memoizedState:he,baseState:he,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Jl,lastRenderedState:he},next:null};var i={};return l.next={memoizedState:i,baseState:i,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Jl,lastRenderedState:i},next:null},n.memoizedState=l,n=n.alternate,n!==null&&(n.memoizedState=l),l}function OL(n){var l=RL(n);l.next===null&&(l=n.alternate.memoizedState),vm(n,l.next.queue,{},Jr())}function QN(){return Xs(qd)}function ML(){return gs().memoizedState}function DL(){return gs().memoizedState}function _ne(n){for(var l=n.return;l!==null;){switch(l.tag){case 24:case 3:var i=Jr();n=ai(i);var u=li(l,n,i);u!==null&&(Ir(u,l,i),pm(u,l,i)),l={cache:NN()},n.payload=l;return}l=l.return}}function Lne(n,l,i){var u=Jr();i={lane:u,revertLane:0,gesture:null,action:i,hasEagerState:!1,eagerState:null,next:null},Hb(n)?PL(l,i):(i=hN(n,l,i,u),i!==null&&(Ir(i,n,u),_L(i,l,u)))}function IL(n,l,i){var u=Jr();vm(n,l,i,u)}function vm(n,l,i,u){var m={lane:u,revertLane:0,gesture:null,action:i,hasEagerState:!1,eagerState:null,next:null};if(Hb(n))PL(l,m);else{var g=n.alternate;if(n.lanes===0&&(g===null||g.lanes===0)&&(g=l.lastRenderedReducer,g!==null))try{var A=l.lastRenderedState,V=g(A,i);if(m.hasEagerState=!0,m.eagerState=V,Yr(V,A))return xb(n,l,m,0),_n===null&&gb(),!1}catch{}if(i=hN(n,l,m,u),i!==null)return Ir(i,n,u),_L(i,l,u),!0}return!1}function ZN(n,l,i,u){if(u={lane:2,revertLane:Uk(),gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null},Hb(n)){if(l)throw Error(o(479))}else l=hN(n,i,u,2),l!==null&&Ir(l,n,2)}function Hb(n){var l=n.alternate;return n===bt||l!==null&&l===bt}function PL(n,l){Nd=Db=!0;var i=n.pending;i===null?l.next=l:(l.next=i.next,i.next=l),n.pending=l}function _L(n,l,i){if((i&4194048)!==0){var u=l.lanes;u&=n.pendingLanes,i|=u,l.lanes=i,xc(n,i)}}var Ub={readContext:Xs,use:_b,useCallback:us,useContext:us,useEffect:us,useImperativeHandle:us,useLayoutEffect:us,useInsertionEffect:us,useMemo:us,useReducer:us,useRef:us,useState:us,useDebugValue:us,useDeferredValue:us,useTransition:us,useSyncExternalStore:us,useId:us,useHostTransitionStatus:us,useFormState:us,useActionState:us,useOptimistic:us,useMemoCache:us,useCacheRefresh:us,useEffectEvent:us},LL={readContext:Xs,use:_b,useCallback:function(n,l){return br().memoizedState=[n,l===void 0?null:l],n},useContext:Xs,useEffect:yL,useImperativeHandle:function(n,l,i){i=i!=null?i.concat([n]):null,zb(4194308,4,NL.bind(null,l,n),i)},useLayoutEffect:function(n,l){return zb(4194308,4,n,l)},useInsertionEffect:function(n,l){zb(4,2,n,l)},useMemo:function(n,l){var i=br();l=l===void 0?null:l;var u=n();if(Hc){cs(!0);try{n()}finally{cs(!1)}}return i.memoizedState=[u,l],u},useReducer:function(n,l,i){var u=br();if(i!==void 0){var m=i(l);if(Hc){cs(!0);try{i(l)}finally{cs(!1)}}}else m=l;return u.memoizedState=u.baseState=m,n={pending:null,lanes:0,dispatch:null,lastRenderedReducer:n,lastRenderedState:m},u.queue=n,n=n.dispatch=Lne.bind(null,bt,n),[u.memoizedState,n]},useRef:function(n){var l=br();return n={current:n},l.memoizedState=n},useState:function(n){n=$N(n);var l=n.queue,i=IL.bind(null,bt,l);return l.dispatch=i,[n.memoizedState,i]},useDebugValue:KN,useDeferredValue:function(n,l){var i=br();return YN(i,n,l)},useTransition:function(){var n=$N(!1);return n=AL.bind(null,bt,n.queue,!0,!1),br().memoizedState=n,[!1,n]},useSyncExternalStore:function(n,l,i){var u=bt,m=br();if(At){if(i===void 0)throw Error(o(407));i=i()}else{if(i=l(),_n===null)throw Error(o(349));(Bt&127)!==0||rL(u,l,i)}m.memoizedState=i;var g={value:i,getSnapshot:l};return m.queue=g,yL(lL.bind(null,u,g,n),[n]),u.flags|=2048,Cd(9,{destroy:void 0},aL.bind(null,u,g,i,l),null),i},useId:function(){var n=br(),l=_n.identifierPrefix;if(At){var i=il,u=ol;i=(u&~(1<<32-Et(u)-1)).toString(32)+i,l="_"+l+"R_"+i,i=Ib++,0<\/script>",g=g.removeChild(g.firstChild);break;case"select":g=typeof u.is=="string"?A.createElement("select",{is:u.is}):A.createElement("select"),u.multiple?g.multiple=!0:u.size&&(g.size=u.size);break;default:g=typeof u.is=="string"?A.createElement(m,{is:u.is}):A.createElement(m)}}g[Ms]=l,g[Ys]=u;e:for(A=l.child;A!==null;){if(A.tag===5||A.tag===6)g.appendChild(A.stateNode);else if(A.tag!==4&&A.tag!==27&&A.child!==null){A.child.return=A,A=A.child;continue}if(A===l)break e;for(;A.sibling===null;){if(A.return===null||A.return===l)break e;A=A.return}A.sibling.return=A.return,A=A.sibling}l.stateNode=g;e:switch(Js(g,m,u),m){case"button":case"input":case"select":case"textarea":u=!!u.autoFocus;break e;case"img":u=!0;break e;default:u=!1}u&&to(l)}}return Hn(l),l.subtreeFlags&=-33554433,uk(l,l.type,n===null?null:n.memoizedProps,l.pendingProps,i),null;case 6:if(n&&l.stateNode!=null)n.memoizedProps!==u&&to(l);else{if(typeof u!="string"&&l.stateNode===null)throw Error(o(166));if(n=Ae.current,yd(l)){if(n=l.stateNode,i=l.memoizedProps,u=null,m=Hs,m!==null)switch(m.tag){case 27:case 5:u=m.memoizedProps}n[Ms]=l,n=!!(n.nodeValue===i||u!==null&&u.suppressHydrationWarning===!0||l5(n.nodeValue,i)),n||ti(l,!0)}else n=Mm(n).createTextNode(u),n[Ms]=l,l.stateNode=n}return Hn(l),null;case 31:if(i=l.memoizedState,n===null||n.memoizedState!==null){if(u=yd(l),i!==null){if(n===null){if(!u)throw Error(o(318));if(n=l.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(o(557));n[Ms]=l}else Oc(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Hn(l),n=!1}else i=jN(),n!==null&&n.memoizedState!==null&&(n.memoizedState.hydrationErrors=i),n=!0;if(!n)return l.flags&256?(Xr(l),l):(Xr(l),null);if((l.flags&128)!==0)throw Error(o(558))}return Hn(l),null;case 13:if(u=l.memoizedState,n===null||n.memoizedState!==null&&n.memoizedState.dehydrated!==null){if(m=yd(l),u!==null&&u.dehydrated!==null){if(n===null){if(!m)throw Error(o(318));if(m=l.memoizedState,m=m!==null?m.dehydrated:null,!m)throw Error(o(317));m[Ms]=l}else Oc(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Hn(l),m=!1}else m=jN(),n!==null&&n.memoizedState!==null&&(n.memoizedState.hydrationErrors=m),m=!0;if(!m)return l.flags&256?(Xr(l),l):(Xr(l),null)}return Xr(l),(l.flags&128)!==0?(l.lanes=i,l):(i=u!==null,n=n!==null&&n.memoizedState!==null,i&&(u=l.child,m=null,u.alternate!==null&&u.alternate.memoizedState!==null&&u.alternate.memoizedState.cachePool!==null&&(m=u.alternate.memoizedState.cachePool.pool),g=null,u.memoizedState!==null&&u.memoizedState.cachePool!==null&&(g=u.memoizedState.cachePool.pool),g!==m&&(u.flags|=2048)),i!==n&&i&&(l.child.flags|=8192),Kb(l,l.updateQueue),Hn(l),null);case 4:return pe(),n===null&&qk(l.stateNode.containerInfo),l.flags|=67108864,Hn(l),null;case 10:return Zl(l.type),Hn(l),null;case 19:if(PN(l),u=l.memoizedState,u===null)return Hn(l),null;if(m=(l.flags&128)!==0,g=u.rendering,g===null)if(m)jm(u,!1);else{if(ds!==0||n!==null&&(n.flags&128)!==0)for(n=l.child;n!==null;){if(g=Mb(n),g!==null){for(l.flags|=128,jm(u,!1),n=g.updateQueue,l.updateQueue=n,Kb(l,n),l.subtreeFlags=0,n=i,i=l.child;i!==null;)I_(i,n),i=i.sibling;return gm(l,Zs.current&1|2),At&&Xl(l,u.treeForkCount),l.child}n=n.sibling}u.tail!==null&&$t()>av&&(l.flags|=128,m=!0,jm(u,!1),l.lanes=4194304)}else{if(!m)if(n=Mb(g),n!==null){if(l.flags|=128,m=!0,n=n.updateQueue,l.updateQueue=n,Kb(l,n),jm(u,!0),u.tail===null&&u.tailMode!=="collapsed"&&u.tailMode!=="visible"&&!g.alternate&&!At)return Hn(l),null}else 2*$t()-u.renderingStartTime>av&&i!==536870912&&(l.flags|=128,m=!0,jm(u,!1),l.lanes=4194304);u.isBackwards?(g.sibling=l.child,l.child=g):(n=u.last,n!==null?n.sibling=g:l.child=g,u.last=g)}if(u.tail!==null){n=u.tail;e:{for(i=n;i!==null;){if(i.alternate!==null){i=!1;break e}i=i.sibling}i=!0}return u.rendering=n,u.tail=n.sibling,u.renderingStartTime=$t(),n.sibling=null,g=Zs.current,g=m?g&1|2:g&1,u.tailMode==="visible"||u.tailMode==="collapsed"||!i||At?gm(l,g):(i=g,Se(Qs,l),Se(Zs,i),or===null&&(or=l)),At&&Xl(l,u.treeForkCount),n}return Hn(l),null;case 22:case 23:return Xr(l),DN(),u=l.memoizedState!==null,n!==null?n.memoizedState!==null!==u&&(l.flags|=8192):u&&(l.flags|=8192),u?(i&536870912)!==0&&(l.flags&128)===0&&(Hn(l),l.subtreeFlags&6&&(l.flags|=8192)):Hn(l),i=l.updateQueue,i!==null&&Kb(l,i.retryQueue),i=null,n!==null&&n.memoizedState!==null&&n.memoizedState.cachePool!==null&&(i=n.memoizedState.cachePool.pool),u=null,l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(u=l.memoizedState.cachePool.pool),u!==i&&(l.flags|=2048),n!==null&&de(_c),null;case 24:return i=null,n!==null&&(i=n.memoizedState.cache),l.memoizedState.cache!==i&&(l.flags|=2048),Zl(js),Hn(l),null;case 25:return null;case 30:return l.flags|=33554432,Hn(l),null}throw Error(o(156,l.tag))}function $ne(n,l){switch(vN(l),l.tag){case 1:return n=l.flags,n&65536?(l.flags=n&-65537|128,l):null;case 3:return Zl(js),pe(),n=l.flags,(n&65536)!==0&&(n&128)===0?(l.flags=n&-65537|128,l):null;case 26:case 27:case 5:return Ne(l),null;case 31:if(l.memoizedState!==null){if(Xr(l),l.alternate===null)throw Error(o(340));Oc()}return n=l.flags,n&65536?(l.flags=n&-65537|128,l):null;case 13:if(Xr(l),n=l.memoizedState,n!==null&&n.dehydrated!==null){if(l.alternate===null)throw Error(o(340));Oc()}return n=l.flags,n&65536?(l.flags=n&-65537|128,l):null;case 19:return PN(l),n=l.flags,n&65536?(l.flags=n&-65537|128,n=l.memoizedState,n!==null&&(n.rendering=null,n.tail=null),l.flags|=4,l):null;case 4:return pe(),null;case 10:return Zl(l.type),null;case 22:case 23:return Xr(l),DN(),n!==null&&de(_c),n=l.flags,n&65536?(l.flags=n&-65537|128,l):null;case 24:return Zl(js),null;case 25:return null;default:return null}}function i3(n,l){switch(vN(l),l.tag){case 3:Zl(js),pe();break;case 26:case 27:case 5:Ne(l);break;case 4:pe();break;case 31:l.memoizedState!==null&&Xr(l);break;case 13:Xr(l);break;case 19:PN(l);break;case 10:Zl(l.type);break;case 22:case 23:Xr(l),DN(),n!==null&&de(_c);break;case 24:Zl(js)}}function wm(n,l){try{var i=l.updateQueue,u=i!==null?i.lastEffect:null;if(u!==null){var m=u.next;i=m;do{if((i.tag&n)===n){u=void 0;var g=i.create,A=i.inst;u=g(),A.destroy=u}i=i.next}while(i!==m)}}catch(V){bn(l,l.return,V)}}function ui(n,l,i){try{var u=l.updateQueue,m=u!==null?u.lastEffect:null;if(m!==null){var g=m.next;u=g;do{if((u.tag&n)===n){var A=u.inst,V=A.destroy;if(V!==void 0){A.destroy=void 0,m=l;var se=i,xe=V;try{xe()}catch(we){bn(m,se,we)}}}u=u.next}while(u!==g)}}catch(we){bn(l,l.return,we)}}function c3(n){var l=n.updateQueue;if(l!==null){var i=n.stateNode;try{W_(l,i)}catch(u){bn(n,n.return,u)}}}function u3(n,l,i){i.props=Uc(n.type,n.memoizedProps),i.state=n.memoizedState;try{i.componentWillUnmount()}catch(u){bn(n,l,u)}}function cl(n,l){try{var i=n.ref;if(i!==null){switch(n.tag){case 26:case 27:case 5:var u=n.stateNode;break;case 30:var m=n.stateNode,g=Gl(n.memoizedProps,m);(m.ref===null||m.ref.name!==g)&&(m.ref=x5(g)),u=m.ref;break;case 7:if(n.stateNode===null){var A=new ea(n);v(n.child,!1,Ise,A,void 0,void 0),n.stateNode=A}u=n.stateNode;break;default:u=n.stateNode}typeof i=="function"?n.refCleanup=i(u):i.current=u}}catch(V){bn(n,l,V)}}function Ws(n,l){var i=n.ref,u=n.refCleanup;if(i!==null)if(typeof u=="function")try{u()}catch(m){bn(n,l,m)}finally{n.refCleanup=null,n=n.alternate,n!=null&&(n.refCleanup=null)}else if(typeof i=="function")try{i(null)}catch(m){bn(n,l,m)}else i.current=null}function Yb(n,l){if((n.tag===5||n.tag===27||n.tag===6)&&n.alternate===null&&l!==null)for(var i=0;i title"))),Js(u,l,i),u[Ms]=n,ys(u),l=u;break e;case"link":if(g=I5("link","href",m).get(l+(i.href||""))){for(A=0;Avt&&(A=vt,vt=We,We=A);var ge=w_(V,We),ie=w_(V,vt);if(ge&&ie&&(je.rangeCount!==1||je.anchorNode!==ge.node||je.anchorOffset!==ge.offset||je.focusNode!==ie.node||je.focusOffset!==ie.offset)){var ye=Re.createRange();ye.setStart(ge.node,ge.offset),je.removeAllRanges(),We>vt?(je.addRange(ye),je.extend(ie.node,ie.offset)):(ye.setEnd(ie.node,ie.offset),je.addRange(ye))}}}}for(Re=[],je=V;je=je.parentNode;)je.nodeType===1&&Re.push({element:je,left:je.scrollLeft,top:je.scrollTop});for(typeof V.focus=="function"&&V.focus(),V=0;Vi?32:i,ve.T=null,i=Ok,Ok=null;var g=Fa,A=hl;if(ns=0,qc=Fa=null,hl=0,(on&6)!==0)throw Error(o(331));var V=on;if(on|=4,D3(g.current),R3(g,g.current,A,i),on=V,Am(0,!1),en&&typeof en.onPostCommitFiberRoot=="function")try{en.onPostCommitFiberRoot(Dn,g)}catch{}return!0}finally{ee.p=m,ve.T=u,Y3(n,l)}}function X3(n,l,i){l=xa(i,l),l=ek(n.stateNode,l,2),n=li(n,l,2),n!==null&&(Go(n,2),gl(n))}function bn(n,l,i){if(n.tag===3)X3(n,n,i);else for(;l!==null;){if(l.tag===3){X3(l,n,i);break}else if(l.tag===1){var u=l.stateNode;if(typeof l.type.getDerivedStateFromError=="function"||typeof u.componentDidCatch=="function"&&(mi===null||!mi.has(u))){n=xa(i,n),i=qL(2),u=li(l,i,2),u!==null&&(GL(i,u,l,n),Go(u,2),gl(u));break}}l=l.return}}function zk(n,l,i){var u=n.pingCache;if(u===null){u=n.pingCache=new Yne;var m=new Set;u.set(l,m)}else m=u.get(l),m===void 0&&(m=new Set,u.set(l,m));m.has(i)||(Ek=!0,m.add(i),n=nse.bind(null,n,l,i),l.then(n,n))}function nse(n,l,i){var u=n.pingCache;u!==null&&u.delete(l),n.pingedLanes|=n.suspendedLanes&i,n.warmLanes&=~i,_n===n&&(Bt&i)===i&&((ds===4||ds===3&&(Bt&62914560)===Bt&&300>$t()-rv)&&(on&2)===0?Ld(n,0):sv|=i,Md===Bt&&(Md=0)),gl(n)}function Q3(n,l){l===0&&(l=hr()),n=Ac(n,l),n!==null&&(Go(n,l),gl(n))}function sse(n){var l=n.memoizedState,i=0;l!==null&&(i=l.retryLane),Q3(n,i)}function rse(n,l){var i=0;switch(n.tag){case 31:case 13:var u=n.stateNode,m=n.memoizedState;m!==null&&(i=m.retryLane);break;case 19:u=n.stateNode;break;case 22:u=n.stateNode._retryCache;break;default:throw Error(o(314))}u!==null&&u.delete(l),Q3(n,i)}function ase(n,l){return ms(n,l)}var Bd=null,Hd=null,Bk=!1,fv=!1,Hk=!1,gi=0;function gl(n){n!==Hd&&n.next===null&&(Hd===null?Bd=Hd=n:Hd=Hd.next=n),fv=!0,Bk||(Bk=!0,ose())}function Am(n,l){if(!Hk&&fv){Hk=!0;do for(var i=!1,u=Bd;u!==null;){if(n!==0){var m=u.pendingLanes;if(m===0)var g=0;else{var A=u.suspendedLanes,V=u.pingedLanes;g=(1<<31-Et(42|n)+1)-1,g&=m&~(A&~V),g=g&201326741?g&201326741|1:g?g|2:0}g!==0&&(i=!0,e5(u,g))}else g=Bt,g=al(u,u===_n?g:0,u.cancelPendingCommit!==null||u.timeoutHandle!==-1),(g&3)===0||ln(u,g)||(i=!0,e5(u,g));u=u.next}while(i);Hk=!1}}function lse(){Z3()}function Z3(){fv=Bk=!1;var n=0;gi!==0&&bse()&&(n=gi);for(var l=$t(),i=null,u=Bd;u!==null;){var m=u.next,g=W3(u,l);g===0?(u.next=null,i===null?Bd=m:i.next=m,m===null&&(Hd=i)):(i=u,(n!==0||(g&3)!==0)&&(fv=!0)),u=m}ns!==0&&ns!==5||Am(n),gi!==0&&(gi=0)}function W3(n,l){for(var i=n.suspendedLanes,u=n.pingedLanes,m=n.expirationTimes,g=n.pendingLanes&-62914561;0V)break;var we=se.transferSize,Re=se.initiatorType;we&&o5(Re)&&(se=se.responseEnd,A+=we*(sexv){We.length=He;break}ye=new Promise(Nse.bind(ye)),We.push(ye)}}}if(0"u"?null:document;function R5(n,l,i){var u=Vd;if(u&&typeof l=="string"&&l){var m=xr(l);m='link[rel="'+n+'"][href="'+m+'"]',typeof i=="string"&&(m+='[crossorigin="'+i+'"]'),A5.has(m)||(A5.add(m),n={rel:n,crossOrigin:i,href:l},u.querySelector(m)===null&&(l=u.createElement("link"),Js(l,"link",n),ys(l),u.head.appendChild(l)))}}function Fse(n){so.D(n),R5("dns-prefetch",n,null)}function $se(n,l){so.C(n,l),R5("preconnect",n,l)}function qse(n,l,i){so.L(n,l,i);var u=Vd;if(u&&n&&l){var m='link[rel="preload"][as="'+xr(l)+'"]';l==="image"&&i&&i.imageSrcSet?(m+='[imagesrcset="'+xr(i.imageSrcSet)+'"]',typeof i.imageSizes=="string"&&(m+='[imagesizes="'+xr(i.imageSizes)+'"]')):m+='[href="'+xr(n)+'"]';var g=m;switch(l){case"style":g=Fd(n);break;case"script":g=$d(n)}if(!(Sa.has(g)||(n=I({rel:"preload",href:l==="image"&&i&&i.imageSrcSet?void 0:n,as:l},i),Sa.set(g,n),u.querySelector(m)!==null||l==="style"&&u.querySelector(Im(g))||l==="script"&&u.querySelector(Pm(g))))){var A=u.createElement("link");Js(A,"link",n),l==="style"&&(A[Ds]=!0,A.onload=A.onerror=function(){qp(A)}),ys(A),u.head.appendChild(A)}}}function Gse(n,l){so.m(n,l);var i=Vd;if(i&&n){var u=l&&typeof l.as=="string"?l.as:"script",m='link[rel="modulepreload"][as="'+xr(u)+'"][href="'+xr(n)+'"]',g=m;switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":g=$d(n)}if(!Sa.has(g)&&(n=I({rel:"modulepreload",href:n},l),Sa.set(g,n),i.querySelector(m)===null)){switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(i.querySelector(Pm(g)))return}u=i.createElement("link"),Js(u,"link",n),ys(u),i.head.appendChild(u)}}}function Kse(n,l,i){so.S(n,l,i);var u=Vd;if(u&&n){var m=Qo(u).hoistableStyles,g=Fd(n);l=l||"default";var A=m.get(g);if(!A){var V={loading:0,preload:null};if(A=u.querySelector(Im(g)))V.loading=5;else{n=I({rel:"stylesheet",href:n,"data-precedence":l},i),(i=Sa.get(g))&&oC(n,i);var se=A=u.createElement("link");ys(se),Js(se,"link",n),se._p=new Promise(function(xe,we){se.onload=xe,se.onerror=we}),se.addEventListener("load",function(){V.loading|=1}),se.addEventListener("error",function(){V.loading|=2}),V.loading|=4,hv(A,l,u)}A={type:"stylesheet",instance:A,count:1,state:V},m.set(g,A)}}}function Yse(n,l){so.X(n,l);var i=Vd;if(i&&n){var u=Qo(i).hoistableScripts,m=$d(n),g=u.get(m);g||(g=i.querySelector(Pm(m)),g||(n=I({src:n,async:!0},l),(l=Sa.get(m))&&iC(n,l),g=i.createElement("script"),ys(g),Js(g,"link",n),i.head.appendChild(g)),g={type:"script",instance:g,count:1,state:null},u.set(m,g))}}function Xse(n,l){so.M(n,l);var i=Vd;if(i&&n){var u=Qo(i).hoistableScripts,m=$d(n),g=u.get(m);g||(g=i.querySelector(Pm(m)),g||(n=I({src:n,async:!0,type:"module"},l),(l=Sa.get(m))&&iC(n,l),g=i.createElement("script"),ys(g),Js(g,"link",n),i.head.appendChild(g)),g={type:"script",instance:g,count:1,state:null},u.set(m,g))}}function O5(n,l,i,u){var m=(m=Ae.current)?Dm(m):null;if(!m)throw Error(o(446));switch(n){case"meta":case"title":return null;case"style":return typeof i.precedence=="string"&&typeof i.href=="string"?(i=Fd(i.href),l=Qo(m).hoistableStyles,u=l.get(i),u||(u={type:"style",instance:null,count:0,state:null},l.set(i,u)),u):{type:"void",instance:null,count:0,state:null};case"link":if(i.rel==="stylesheet"&&typeof i.href=="string"&&typeof i.precedence=="string"){n=Fd(i.href);var g=Qo(m).hoistableStyles,A=g.get(n);if(A||(m=m.ownerDocument||m,A={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},g.set(n,A),(g=m.querySelector(Im(n)))?g._p||(A.instance=g,A.state.loading=5):(g=Sa.get(n),g||(g={rel:"preload",as:"style",href:i.href,crossOrigin:i.crossOrigin,integrity:i.integrity,media:i.media,hrefLang:i.hrefLang,referrerPolicy:i.referrerPolicy},Sa.set(n,g)),Qse(m,n,g,A.state))),l&&u===null)throw Error(o(528,""));return A}if(l&&u!==null)throw Error(o(529,""));return null;case"script":return l=i.async,i=i.src,typeof i=="string"&&l&&typeof l!="function"&&typeof l!="symbol"?(i=$d(i),l=Qo(m).hoistableScripts,u=l.get(i),u||(u={type:"script",instance:null,count:0,state:null},l.set(i,u)),u):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,n))}}function Fd(n){return'href="'+xr(n)+'"'}function Im(n){return'link[rel="stylesheet"]['+n+"]"}function M5(n){return I({},n,{"data-precedence":n.precedence,precedence:null})}function Qse(n,l,i,u){if(l=n.querySelector('link[rel="preload"][as="style"]['+l+"]")){if(l[Ds]!==!0){u.loading=1;return}}else l=n.createElement("link"),l[Ds]=!0,l.onload=l.onerror=qp.bind(null,l),Js(l,"link",i),ys(l),n.head.appendChild(l);u.preload=l,l.addEventListener("load",function(){return u.loading|=1}),l.addEventListener("error",function(){return u.loading|=2})}function $d(n){return'[src="'+xr(n)+'"]'}function Pm(n){return"script[async]"+n}function D5(n,l,i){if(l.count++,l.instance===null)switch(l.type){case"style":var u=n.querySelector('style[data-href~="'+xr(i.href)+'"]');if(u)return l.instance=u,ys(u),u;var m=I({},i,{"data-href":i.href,"data-precedence":i.precedence,href:null,precedence:null});return u=(n.ownerDocument||n).createElement("style"),ys(u),Js(u,"style",m),hv(u,i.precedence,n),l.instance=u;case"stylesheet":m=Fd(i.href);var g=n.querySelector(Im(m));if(g)return l.state.loading|=4,l.instance=g,ys(g),g;u=M5(i),(m=Sa.get(m))&&oC(u,m),g=(n.ownerDocument||n).createElement("link"),ys(g);var A=g;return A._p=new Promise(function(V,se){A.onload=V,A.onerror=se}),Js(g,"link",u),l.state.loading|=4,hv(g,i.precedence,n),l.instance=g;case"script":return g=$d(i.src),(m=n.querySelector(Pm(g)))?(l.instance=m,ys(m),m):(u=i,(m=Sa.get(g))&&(u=I({},i),iC(u,m)),n=n.ownerDocument||n,m=n.createElement("script"),ys(m),Js(m,"link",u),n.head.appendChild(m),l.instance=m);case"void":return null;default:throw Error(o(443,l.type))}else l.type==="stylesheet"&&(l.state.loading&4)===0&&(u=l.instance,l.state.loading|=4,hv(u,i.precedence,n));return l.instance}function hv(n,l,i){for(var u=i.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),m=u.length?u[u.length-1]:null,g=m,A=0;A title"):null)}function Zse(n,l,i){if(i===1||l.itemProp!=null)return!1;switch(n){case"meta":case"title":return!0;case"style":if(typeof l.precedence!="string"||typeof l.href!="string"||l.href==="")break;return!0;case"link":if(typeof l.rel!="string"||typeof l.href!="string"||l.href===""||l.onLoad||l.onError)break;return l.rel==="stylesheet"?(n=l.disabled,typeof l.precedence=="string"&&n==null):!0;case"script":if(l.async&&typeof l.async!="function"&&typeof l.async!="symbol"&&!l.onLoad&&!l.onError&&l.src&&typeof l.src=="string")return!0}return!1}function P5(n,l){return n==="img"&&l.src!=null&&l.src!==""&&l.onLoad==null&&l.loading!=="lazy"}function _5(n){return!(n.type==="stylesheet"&&(n.state.loading&3)===0)}function L5(n){return(n.width||100)*(n.height||100)*(typeof devicePixelRatio=="number"?devicePixelRatio:1)*.25}function z5(n,l){typeof l.decode=="function"&&(n.imgCount++,l.complete||(n.imgBytes+=L5(l),n.suspenseyImages.push(l)),n=ere.bind(n),l.decode().then(n,n))}function Wse(n,l,i,u){if(i.type==="stylesheet"&&(typeof u.media!="string"||matchMedia(u.media).matches!==!1)&&(i.state.loading&4)===0){if(i.instance===null){var m=Fd(u.href),g=l.querySelector(Im(m));if(g){l=g._p,l!==null&&typeof l=="object"&&typeof l.then=="function"&&(n.count++,n=_m.bind(n),l.then(n,n)),i.state.loading|=4,i.instance=g,ys(g);return}g=l.ownerDocument||l,u=M5(u),(m=Sa.get(m))&&oC(u,m),g=g.createElement("link"),ys(g);var A=g;A._p=new Promise(function(V,se){A.onload=V,A.onerror=se}),Js(g,"link",u),i.instance=g}n.stylesheets===null&&(n.stylesheets=new Map),n.stylesheets.set(i,l),(l=i.state.preload)&&(i.state.loading&3)===0&&(n.count++,i=_m.bind(n),l.addEventListener("load",i),l.addEventListener("error",i))}}var xv=0;function Jse(n,l){return n.stylesheets&&n.count===0&&vv(n,n.stylesheets),0xv?50:800)+l);return n.unsuspend=i,function(){n.unsuspend=null,clearTimeout(u),clearTimeout(m)}}:null}function B5(n){if(n.count===0&&(n.imgCount===0||!n.waitingForImages)){if(n.stylesheets)vv(n,n.stylesheets);else if(n.unsuspend){var l=n.unsuspend;n.unsuspend=null,l()}}}function _m(){this.count--,B5(this)}function ere(){this.imgCount--,B5(this)}var bv=null;function vv(n,l){n.stylesheets=null,n.unsuspend!==null&&(n.count++,bv=new Map,l.forEach(tre,n),bv=null,_m.call(n))}function tre(n,l){if(!(l.state.loading&4)){var i=bv.get(n);if(i)var u=i.get(null);else{i=new Map,bv.set(n,i);for(var m=n.querySelectorAll("link[data-precedence],style[data-precedence]"),g=0;g"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Ej.exports=_8(),Ej.exports}var jn=L8();const fg=[20,50,100,200],pg=[20,50,100,200,"all"],bu=50,VR="workbuddy-desktop-table-size:";function FR(e){return e==="all"?r("全部"):String(e)}function mg(e,t=pg,a=bu){t.includes(a)||(a=t.includes(bu)?bu:t[0]);let o=null;try{o=localStorage.getItem(VR+e)}catch{return a}if(o===null||o.trim()==="")return a;if(o==="all")return t.includes("all")?"all":a;const c=Number(o);return Number.isFinite(c)&&t.includes(c)?c:a}function hg(e,t){try{localStorage.setItem(VR+e,String(t))}catch{}}function gg(e,t,a={}){const o=a.sizes??pg,c=a.defaultSize??bu,[d,f]=x.useState(()=>mg(t,o,c)),[p,h]=x.useState(1),b=Math.max(1,d==="all"?1:Math.ceil(e/d)),y=Math.min(Math.max(1,p),b);x.useEffect(()=>{y!==p&&h(y)},[y,p]);const v=x.useCallback(N=>{f(N),hg(t,N),h(1)},[t]),j=x.useCallback(N=>{h(Math.min(Math.max(1,Math.round(N)||1),b))},[b]),w=d==="all"?0:(y-1)*d,k=d==="all"?e:Math.min(e,w+d),S=x.useCallback(N=>d==="all"?N.slice():N.slice(w,k),[d,w,k]);return{size:d,page:y,pageCount:b,rangeStart:e?w+1:0,rangeEnd:e?k:0,paged:d!=="all",setSize:v,goto:j,slice:S}}function $i({total:e,page:t,pageCount:a,size:o,sizes:c=pg,onSizeChange:d,onPageChange:f,range:p=null,disabled:h=!1,leading:b,className:y}){const[v,j]=x.useState(String(t));x.useEffect(()=>j(String(t)),[t]);const w=()=>{const N=v.trim();if(!N){j(String(t));return}const R=Number(N);if(!Number.isFinite(R)){j(String(t));return}const P=Math.min(Math.max(1,Math.round(R)),a);j(String(P)),P!==t&&f(P)},k=a<=1,S=e===0?r("共 0 条"):p?r("共 {total} 条 · 当前第 {start}–{end} 条",{total:e,start:p.start,end:p.end}):r("共 {total} 条(全部显示)",{total:e});return s.jsxs("div",{className:y?`panel-foot table-foot-bar ${y}`:"panel-foot table-foot-bar",children:[b,s.jsx("div",{className:"spacer"}),s.jsxs("div",{className:"table-foot-ctl",children:[s.jsx("span",{className:"table-foot-count",children:S}),s.jsxs("span",{className:"table-foot-size",children:[r("每页"),s.jsxs(dt,{value:String(o),onValueChange:N=>d(N==="all"?"all":Number(N)),children:[s.jsx(pt,{className:"h-[26px] w-[86px]",disabled:h,"aria-label":r("每页条数"),children:s.jsx(ft,{children:FR(o)})}),s.jsx(mt,{children:c.map(N=>s.jsx($e,{value:String(N),children:FR(N)},String(N)))})]}),r("条")]}),s.jsxs("span",{className:"table-foot-jump",children:[r("跳至"),s.jsx(Fe,{className:"h-[26px] w-[52px] px-1 text-center",value:v,disabled:h||k,"aria-label":r("跳转到指定页"),title:k?r("当前只有一页"):r("跳转到第 1–{pageCount} 页",{pageCount:a}),inputMode:"numeric",onChange:N=>j(N.target.value),onKeyDown:N=>{N.key==="Enter"?(N.preventDefault(),w()):N.key==="Escape"&&j(String(t))},onBlur:w}),r("页")]}),s.jsx(X6,{page:t,pageCount:a,onPageChange:f,disabled:h})]})]})}const Oj=[{key:"pick",label:r("选择"),align:"center",legacyAlign:"left"},{key:"order",label:r("顺序"),title:r("组内先后:按住左边的把手上下拖动即可调整;整组的先后拖分组带的把手"),align:"center",legacyAlign:"left"},{key:"account",label:r("账号"),align:"center",legacyAlign:"left"},{key:"proxy",label:r("代理"),title:r("该账号出网走的代理(Clash 出口 / 自定义 / 直连);点击可修改"),align:"center"},{key:"connections",label:r("连接数"),title:r("此刻正在使用这个账号的请求数(含还在下发内容的流式请求);为 0 时不显示"),align:"center"},{key:"status",label:r("状态"),align:"center",legacyAlign:"left"},{key:"limits",label:r("限流"),title:r("该账号当前限流中的模型;点徽章看明细"),align:"center",legacyAlign:"left"},{key:"expiry",label:r("有效期"),align:"center",legacyAlign:"left"},{key:"usage",label:r("余额"),align:"center",legacyAlign:"left"},{key:"actions",label:r("操作"),align:"right"}],$R="agent2api-accounts-col-widths",If={pick:47,order:84,proxy:186,connections:56,status:80,limits:148,expiry:80,usage:148,actions:200},Mj=new Set(["account"]),z8=300,Dj=56,B8=new Set([...Object.keys(If),...Mj]),vu=(()=>{try{const e=JSON.parse(localStorage.getItem($R)||"{}"),t={};for(const[a,o]of Object.entries(e||{})){const c=Number(o);B8.has(a)&&Number.isFinite(c)&&c>=Dj&&(t[a]=Math.round(c))}return t}catch{return{}}})();function qR(){try{localStorage.setItem($R,JSON.stringify(vu))}catch{}}function H8(){return{...If,...vu}}function U8(e){let t=0;for(const a of e){const o=vu[a];o?t+=o:Mj.has(a)?t+=z8:If[a]?t+=If[a]:t+=Dj}return Math.round(t)}function GR(e,t){const a=e?.querySelector(`thead th:nth-child(${t+1})`),o=a?.getAttribute("data-col")||a?.className.match(/cell-([a-z]+)/)?.[1];if(!o)return null;const c=e?.querySelector(`colgroup col[data-col="${CSS.escape(o)}"]`)||e?.querySelectorAll("colgroup col")[t];return c?{key:o,col:c}:null}function V8(e,t,a){const o=Math.max(Dj,Math.round(a));e.style.width=o+"px",Mj.has(t)||o!==If[t]?vu[t]=o:delete vu[t]}let Ij=()=>{};function F8(e,t){if(Ij=t,!e)return;let a=null;e.addEventListener("pointerdown",o=>{if(o.button!==0)return;const c=o.target?.closest?.(".col-grip");if(!c)return;o.preventDefault();const d=c.closest("th"),f=d?.closest("table")||null,p=d?.parentElement?[...d.parentElement.children].indexOf(d):-1,h=GR(f,p);if(!h)return;const b=o.clientX,y=h.col.getBoundingClientRect().width;c.classList.add("active"),document.body.classList.add("col-resizing");try{c.setPointerCapture(o.pointerId)}catch{}a={...h,startX:b,startWidth:y,grip:c,pointerId:o.pointerId},window.addEventListener("pointermove",v),window.addEventListener("pointerup",j),window.addEventListener("pointercancel",j),window.addEventListener("blur",j);function v(w){if(a){if(w.buttons===0){j();return}V8(a.col,a.key,a.startWidth+w.clientX-a.startX)}}function j(){if(!a)return;const{grip:w,pointerId:k}=a;a=null,w.classList.remove("active"),document.body.classList.remove("col-resizing");try{w.releasePointerCapture(k)}catch{}window.removeEventListener("pointermove",v),window.removeEventListener("pointerup",j),window.removeEventListener("pointercancel",j),window.removeEventListener("blur",j),qR(),Ij()}}),e.addEventListener("dblclick",o=>{const c=o.target?.closest?.(".col-grip");if(!c)return;const d=c.closest("th"),f=d?.closest("table")||null,p=d?.parentElement?[...d.parentElement.children].indexOf(d):-1,h=GR(f,p);h&&(delete vu[h.key],qR(),Ij())})}function gt(){return window}function Ln(e,t){gt().wbApp?.toast?.(e,t)}function Co(e){return e instanceof Error&&e.message?e.message:String(e??"").trim()||r("未知错误")}function Pj(e){return(gt().wbApp?.getState?.()?.accounts?.accounts||[]).filter(a=>(a?.provider||"workbuddy")===e).length}function KR(e){const t=e?.name||"";if(t)return(gt().wbProviders?.customList?.()||[]).find(a=>(a.name||"")===t)}function $8(e){const t=e?.name||"";return t?(gt().wbPresetProviders?.list||[]).some(a=>a.name===t):!1}async function yu(e){const t=gt().__TAURI_INTERNALS__;if(!t||typeof t.invoke!="function")throw new Error(r("桌面运行时不可用(Tauri 未初始化)"));return t.invoke("api_request",{request:{method:"POST",path:"/api/accounts",body:e}})}function Pf(e){return e?.name||e?.uid||e?.userId||""}function _j(){gt().wbAddAccountModal?.close?.()}async function To(e,t){_j(),await gt().wbApp?.refresh?.(),Ln(r("✅ {label}账号已添加{name}",{label:t,name:e?`:${e}`:""}))}const ju=new Map;function Lr(e){return{defaultValue:ju.get(e)??"",onChange:t=>{const a=t.currentTarget.value;a?ju.set(e,a):ju.delete(e)}}}function Eo(e,t){t?ju.set(e,t):ju.delete(e);const a=document.getElementById(e);(a instanceof HTMLInputElement||a instanceof HTMLTextAreaElement)&&(a.value=t)}function dr(e){const t=document.getElementById(e);return t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement?t.value.trim():(ju.get(e)??"").trim()}function Lj(e){for(const t of e)Eo(t,"")}const qi={edition:"cn",loginMode:"embedded",socialRestore:!1},zj=100,q8=256,G8=e=>e.key==="name"?zj:q8,K8={provider:"raccoon",label:"小浣熊",addButton:r("添加小浣熊账号"),webLogin:{noteHtml:r("在内嵌窗口里完成官方登录,成功后自动加入账号列表。"),button:r("打开网页登录"),hint:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待"),busyText:r("等待小浣熊登录完成…")},manualTitle:r("粘贴 token / refreshToken"),manualNoteHtml:r('refreshToken 可选,填了到期可自动续期;两者都能从小浣熊客户端登录态文件里取到。'),fields:[{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用凭证里的账号名")},{key:"token",label:"token",rows:3,placeholder:r("粘贴 access_token(一长串 JWT)")},{key:"refreshToken",inputKey:"refresh",label:"refreshToken",rows:2,optional:!0,placeholder:r("可选")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后点「刷新 Token」同步。"),fileImport:{accept:".json,application/json",note:r("选择小浣熊客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json;macOS / Linux:~/.box-agent/config/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。")}},Y8={provider:"catpaw",label:"CatPaw",webLogin:{noteHtml:r("用 CatPaw 账号完成登录(美团 passport),成功后自动加入账号列表。"),button:r("打开 CatPaw 网页登录"),busyText:r("等待 CatPaw 登录完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录的美团账号);完成后自动加入列表")}]},manualNote:r("token 是登录态 Cookie;CatPaw 没有刷新机制,过期后需在客户端重新登录。"),fields:[{key:"token",label:"token",rows:3,placeholder:r("CatPaw 的 X-Passport-Token(登录态 Cookie)")},{key:"uid",label:"uid",placeholder:r("必填,CatPaw 账号标识")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用登录名或 uid")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。客户端重新登录后重新导入即可。"),desktopHint:r("读取 ~/.meituan-catpaw/auth.json,需已在 CatPaw 客户端登录"),fileImport:{accept:".json,application/json",note:r("选择 CatPaw 客户端的登录态文件 auth.json(Windows:C:\\Users\\<你的用户名>\\.meituan-catpaw\\auth.json;macOS / Linux:~/.meituan-catpaw/auth.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端。")}},X8={provider:"autoclaw",label:r("AutoClaw 国内版"),manualNote:r("token 支持 enc: 前缀(Windows 上自动解密)。未填 refreshToken 无法自动续期。"),smsLogin:{noteHtml:r("用绑定的手机号登录:点「获取验证码」后填入即可。这是国内版官方唯一的登录方式。")},fields:[{key:"token",label:"token",rows:3,placeholder:r("明文 JWT 或 auth.json 里的 enc: 加密值(自动解密)")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("没有则无法自动续期")},{key:"deviceId",label:"deviceId",optional:!0,placeholder:r("可选,续期时带上")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用 userId")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。"),desktopHint:r("读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows"),desktopWindowsOnly:!0},Q8={provider:"autoclaw-intl",label:r("AutoClaw 国际版"),manualNote:r("国际版与国内版账号体系独立,请填国际版的凭证。未填 refreshToken 无法自动续期。"),oauthLogin:{title:r("网页登录(Zai / Google)"),noteHtml:r("点按钮后先过一次滑块验证(官方风控),随后打开登录页,登录完成即自动添加账号。
    这是国际版官方唯一的登录方式;已在客户端登录过的,用「导入桌面端登录态」更快。"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口打开;关窗即取消等待(Google 账号被拒时改用系统浏览器)")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录的 Zai / Google 账号);完成后自动加入列表")}]},fields:[{key:"token",label:"token",rows:3,placeholder:r("明文 JWT(国际版账号的 access token)")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("没有则无法自动续期")},{key:"deviceId",label:"deviceId",optional:!0,placeholder:r("可选,续期时带上")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用 userId")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。用 Zai / Google 登录客户端的用户走这一条。"),desktopHint:r("读取 %APPDATA%/AutoClaw/auth.json 并解密,仅 Windows"),desktopWindowsOnly:!0};function YR(e){const{provider:t,label:a,siteNote:o}=e;return{provider:t,label:a,desktop:!1,webLogin:{noteHtml:r("打开官方授权页完成设备码授权,登录的是{label}({site})的账号。",{label:a,site:o}),button:r("打开 Qoder 网页登录"),busyText:r("等待 Qoder 授权完成…"),edition:t==="qoder"?"cn":"global",modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口用全新环境,多账号互不影响;关窗即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录账号);完成后自动加入列表")}]},manualTitle:r("使用个人访问令牌(PAT)"),manualNote:r("在{label}的 Qoder 账号设置 → Integrations 生成 PAT(别填 Google / GitHub 的令牌)。两个地区的账号与凭证不通用。",{label:a}),fields:[{key:"pat",label:"Qoder PAT",rows:3,placeholder:r("粘贴 Qoder 个人访问令牌(pt-…)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空使用账号昵称或邮箱")}]}}const Z8=YR({provider:"qoder",label:r("中国版"),siteNote:"qoder.com.cn"}),W8=YR({provider:"qoder-intl",label:r("国际版"),siteNote:"qoder.com"});function XR(e){const{provider:t,label:a,poolNote:o}=e;return{provider:t,label:a,desktop:!0,webLogin:{noteHtml:r("打开授权页完成确认,账号自动加入 {label}{note}",{label:a,note:o}),button:r("打开 Cline 授权页"),busyText:r("等待 Cline 授权确认…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录的 Cline 账号);完成后自动加入列表")}]},manualTitle:r("填写凭证"),manualNote:r("refreshToken 可选,填了可自动续期;两者都能从客户端登录态文件取到。同一个 Cline 账号两个池都能用,这里归入 {label}。",{label:a}),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("粘贴 workos:… 开头的令牌(不带前缀也会自动补上)")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("可选,没有则无法自动续期")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空使用账号姓名、邮箱或令牌指纹")}],desktopNote:r("读本机客户端当前登录态,每次实时读取(删掉这条记录不影响客户端登录态)。这一条归入 {label}。",{label:a}),desktopHint:r("读取 ~/.cline/data/settings/providers.json,需已在 Cline 客户端登录"),fileImport:{accept:".json,application/json",note:r("选择 Cline 客户端的登录态文件 providers.json(Windows:C:\\Users\\<你的用户名>\\.cline\\data\\settings\\providers.json;macOS / Linux:~/.cline/data/settings/providers.json)。导入后凭证直接落在网关、可独立转发,不再依赖本机客户端;这一条归入 {label}。",{label:a})}}}function QR(e){const{provider:t,label:a,site:o,siteNote:c}=e;return{provider:t,label:a,webLogin:{noteHtml:r("打开 Accio {label}的官方登录页({site})并用你的 Accio 账号登录:登录成功后官方页面会跳回本机;同机自动完成,Docker / 远程面板按提示粘贴回调地址即可(授权码只在本机传给网关,界面不显示明文 token)。",{label:a,site:o}),button:r("打开 Accio {label}登录页",{label:a}),busyText:r("等待 Accio {label}登录完成…",{label:a}),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开登录页(会复用浏览器里已登录的 Accio 账号);完成登录后自动加入账号列表,关掉弹窗即取消等待")}]},manualTitle:r("填写凭证"),manualNoteHtml:r("accessToken 是 Accio 的登录凭证(一长串不透明 token,不是 JWT);refreshToken 可选,填了之后到期能自动续期。请填写 {label}账号的凭证 —— {siteNote}(最容易拿到的办法:直接用上方的「网页登录」,不需要手工找 token。)",{label:a,siteNote:c}),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("粘贴 Accio 的 accessToken")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("可选,没有则无法自动续期")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空使用账号昵称或邮箱")}]}}function ZR(e){const{provider:t,label:a,site:o,planNote:c}=e;return{provider:t,label:a,desktop:!1,webLogin:{noteHtml:r("打开 ZCode {label}的官方授权页并用你的账号登录。授权结果由 ZCode 服务端记录,网关在后台自动取回凭证并加入账号列表。",{label:a}),button:r("打开 ZCode {label}授权页",{label:a}),busyText:r("等待 ZCode {label}授权完成…",{label:a}),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;授权完成后自动加入账号列表。关掉窗口即取消等待。授权页最后可能提示无法打开 zcode:// 链接,这是正常的 —— 结果已由服务端记下")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开授权页(会复用浏览器里已登录的 ZCode 账号);授权完成后自动加入账号列表。页面最后可能提示无法打开 zcode:// 链接,属正常现象")}]},manualTitle:r("填写凭证"),manualNoteHtml:r("本家有两个**互不替代**的凭证,按你要用的功能填,至少填一个:编码套餐 API Key 用于转发推理(打 {site})与查询窗口限额(每 N 小时 / 每周的剩余比例);jwt 用于领取套餐与查询余额(打 zcode.z.ai 的 billing 网关,官方叫 Coding Plan JWT,是一串三段点分的字符串)。余额两把都能查、但读到的东西不同:jwt 读到余额桶与套餐到期,API Key 读到窗口限额;而领取只认 jwt、转发只认 API Key。请填写 {label}账号的凭证 —— {plan}(最容易拿到的办法:直接用上方的「网页登录」—— 它会替你把这个 API Key 换好,两个凭证一起拿到。)",{site:o,label:a,plan:c}),fields:[{key:"accessToken",label:r("编码套餐 API Key"),rows:3,optional:!0,placeholder:r("用于转发;形如 apiKey.secret 两段点分(不填则这个账号不能转发)")},{key:"jwt",label:"Coding Plan JWT",inputKey:"jwt",rows:3,optional:!0,placeholder:r("用于领取套餐与查询余额;不填则这个账号不能领取与查余额")},{key:"userId",label:r("用户 ID"),optional:!0,placeholder:r("可选;用于生成账号 id 与展示名")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空自动生成")}]}}const J8={provider:"codearts",label:"CodeArts",desktop:!1,webLogin:{noteHtml:r("打开华为云 CodeArts 的官方授权页登录:登录完成后官方页面会把浏览器带回网关自己的 /oauth/callback,网关用一次性授权码换取临时凭据并加入账号列表。
    网关跑在另一台机器上时,网页端会提示把地址栏中的最终回调地址直接粘贴回面板。"),button:r("打开 CodeArts 授权页"),busyText:r("等待 CodeArts 登录完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);浏览器与网关不在同一台机器时,按上方说明把最终回调地址粘贴回面板")}]},manualTitle:r("粘贴登录凭据"),manualNoteHtml:r('整份粘贴官方插件 / CLIProxyAPI 落盘的凭据 JSON(形如 {"codearts_provider_credential":{…}},铺平的也行)。
    必填:access_key_id、secret_access_key、security_token。要能自动续期,必须连 refresh_token 与 oauth_context 一起粘 —— 临时凭据约一小时到期,缺这半块就续不回来,只能重新登录。'),fields:[{key:"credentialJson",label:r("凭据 JSON"),rows:8,jsonExpand:!0,placeholder:'{"codearts_provider_credential":{"access_key_id":"HSTA…","secret_access_key":"…","security_token":"…","expires_at":"2026-09-27T16:17:00.327Z","domain_id":"…","user_id":"…","user_name":"…","refresh_token":"eyJ…","oauth_context":{…}}}'},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空使用凭据里的 user_name")}]},eq={provider:"trae",label:"Trae",desktop:!1,webLogin:{noteHtml:r("打开 Trae SOLO 的官方授权页(trae.cn)并用你的 Trae 账号登录:授权完成后官方页面会跳回本机的一个临时端口;同机部署自动接收,Docker / 远程面板请按提示复制地址栏回调地址。"),button:r("打开 Trae 授权页"),busyText:r("等待 Trae 授权完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;授权完成后自动加入账号列表。远程面板可粘贴回调地址。关掉窗口即取消等待。链接 5 分钟内有效,超时或未点就会作废(可重新发起)")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开授权页(会复用浏览器里已登录的 Trae 账号);同机完成后自动加入,Docker / 远程面板按提示粘贴地址栏回调地址。")}]},manualTitle:r("填写凭证"),manualNoteHtml:r("accessToken 是 Trae 的 Cloud-IDE-JWT(三段点分),refreshToken 用于到期自动续期(本家 refreshToken 一次一换:换发一次旧的即作废,所以两份程序别同时刷同一个账号)。
    手工粘贴时请连 machineId / deviceId 一起填:上游把它们与登录时上传的设备公钥绑在一起判设备,凭空换一对会撞 2xxxx 那族设备绑定拒绝。
    没有这三样时的正路是用上方的「网页登录」;容器 / 远程部署形态按提示粘贴地址栏回调地址即可。"),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("Cloud-IDE-JWT(三段点分)")},{key:"refreshToken",label:"refreshToken",rows:2,optional:!0,placeholder:r("可选;填了才能到期自动续期")},{key:"uid",label:r("用户 ID"),optional:!0,placeholder:r("可选;用于去重与展示名(留空时网关会问一次上游)")},{key:"machineId",label:"machineId",optional:!0,placeholder:r("可选;UUID 形态,与凭据同生共死")},{key:"deviceId",label:"deviceId",optional:!0,placeholder:r("可选;纯数字串(上游只收 8–24 位数字)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空自动用昵称")}]},tq={provider:"loomy",label:"Loomy",smsLogin:{noteHtml:r("用 Loomy 账号绑定的手机号登录:点「获取验证码」后填入即可。这是本家最省事的入口。")},manualNote:r("粘贴的是登录 session(同时是模型网关的 token)。Loomy 没有续期接口,session 有效期约 14 天,过期后重新登录即可。"),fields:[{key:"session",label:"session",rows:3,placeholder:r("登录 session(一长串)")},{key:"userId",label:"userId",optional:!0,placeholder:r("可选,讯飞侧 userid")},{key:"phone",label:r("手机号"),optional:!0,placeholder:r("可选,展示用")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用脱敏手机号或 userId")}],desktop:!1},nq={provider:"kuku",label:"KukuAI",webLogin:{noteHtml:r("在打开的窗口里用百度账号登录 KukuAI 主站(手机验证码 / 扫码均可),登录成功后自动加入账号列表。网关会向百度换发 KukuAI 业务会话令牌(依赖本机已安装库库AI 客户端)。"),button:r("打开网页登录"),busyText:r("等待 KukuAI 登录完成…")},manualTitle:r("粘贴 Cookie"),manualNote:r("BDUSS 必填;请粘贴**完整 Cookie**(Cookie 编辑器一键导出即可)—— 其中 **PTOKEN 必须保留**,网关要用它向百度换发 KukuAI 业务会话令牌,缺了它模型刷新会报「未登录」。支持整段 Cookie 头、Cookie 编辑器导出的 JSON 数组,或 {BDUSS, STOKEN} 对象。KukuAI 没有刷新机制,登录态过期后重新粘贴即可。"),fields:[{key:"cookie",label:"Cookie",rows:3,placeholder:r("BDUSS=…; STOKEN=…(或 Cookie 编辑器导出的 JSON)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用账号 uk")}],desktop:!0,desktopHint:r("读取本机 KukuAI 客户端登录态(%APPDATA%\\baidugenflowpro\\Network\\Cookies),需已在 KukuAI 客户端登录"),desktopNote:r("读本机客户端当前登录态(明文 Cookie,无需解密)。客户端运行时 Cookies 文件被独占占用,导入前请先关闭 KukuAI 客户端。"),fileImport:{binary:!0,accept:"",note:r("选择 KukuAI 客户端的 Cookies 文件(%APPDATA%\\baidugenflowpro\\Network\\Cookies):它是**二进制** SQLite 数据库(无扩展名,不是 JSON)。导入时读的是你选中文件的副本、不和运行中的客户端抢占用,因此**无需先关闭客户端**。导入后凭证直接落在网关、可独立转发。")}};function WR(e){const{provider:t,label:a,siteNote:o}=e;return{provider:t,label:a,desktop:!1,manualTitle:r("粘贴 session cookie"),manualNoteHtml:r("粘贴网页登录态 cookie monkeycode_ai_session 的值(在浏览器里复制整段 Cookie 直接粘贴也行,网关会自己剥出值)。
    {siteNote}
    MonkeyCode 没有续期接口:session 有效期约 30 天(硬限制),过期后重新登录网页、再粘贴一次即可。",{siteNote:o}),fields:[{key:"session",label:"session",rows:3,placeholder:r("monkeycode_ai_session 的值(也可直接粘贴整段 Cookie)")},{key:"imageId",label:r("任务镜像 id"),optional:!0,placeholder:r("可选:发起对话必需,留空则由网关从该账号已有任务里自动发现,发现不到时之后手动补")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用上游返回的账号名或账号 id")}]}}const sq=WR({provider:"monkeycode",label:r("MonkeyCode"),siteNote:r("这里填国内站(monkeycode-ai.com)的账号:请粘贴国内站的 session。国际站(monkeycode-ai.net)是另一家 provider、另一套账号,两边的凭证不通用。")}),rq=WR({provider:"monkeycode-intl",label:r("MonkeyCode 国际版"),siteNote:r("这里填国际站(monkeycode-ai.net)的账号:请粘贴国际站的 session。国内站(monkeycode-ai.com)是另一家 provider、另一套账号,两边的凭证不通用。")}),aq={provider:"commandcode",label:r("Command Code"),desktop:!1,manualTitle:r("粘贴 API Key"),manualNote:r("粘贴 Command Code 的 API Key(user_ 开头;从官方 CLI 的 ~/.commandcode/auth.json 或网页 studio 获取)。整行 / 带引号 / 带 Bearer 前缀地粘都行,网关会自己剥成裸 key。key 不过期、也没有续期接口,失效后重新获取即可;添加时网关会做一次轻量探活,失败不影响添加。"),fields:[{key:"apiKey",label:"apiKey",rows:3,placeholder:r("user_ 开头的 API Key(也可直接粘贴 Authorization: Bearer … 整行)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用 key 尾号")}]},lq={provider:"antigravity",label:r("Antigravity"),desktop:!1,webLogin:{noteHtml:r("在打开的窗口里登录 Google 账号(Antigravity 的授权页),授权完成后自动加入账号列表。"),button:r("打开 Antigravity 网页登录"),busyText:r("等待 Google 授权完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("系统浏览器打开(复用已登录的 Google 账号);完成后自动加入列表")}]},manualTitle:r("粘贴 Google refresh token"),manualNoteHtml:r("粘贴 Antigravity 的 Google refresh token(以 1// 开头;直接粘贴含 refresh_token= 的整行也行)。
    这是网页登录之外的手工入口(例如从已登录的官方 IDE 里导出)。refresh token 不会过期,access token 到期由网关自动续期;令牌丢了只能重新走 Google 授权,请妥善保存。"),fields:[{key:"refreshToken",label:"refreshToken",rows:2,placeholder:r("1// 开头的 Google refresh token(也可直接粘贴 refresh_token=… 整行)")},{key:"projectId",label:"projectId",optional:!0,placeholder:r("可选(cloudaicompanionProject):留空由网关自动发现")},{key:"email",label:"email",optional:!0,placeholder:r("可选:账号邮箱,用于展示与身份识别(换新令牌也能认回同一账号)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用邮箱或令牌尾号")}]},oq={provider:"officeace",label:r("OfficeAce 果办"),desktop:!1,webLogin:{noteHtml:r("打开华为云授权页登录:登录完成后网关会自动轮询云端取回授权码并加入账号列表(不需要装 OfficeAce 桌面端,也无需手工回填回调地址)。"),button:r("打开授权页"),busyText:r("等待 OfficeAce 登录完成…"),modes:[{value:"embedded",label:r("内嵌窗口(推荐)"),hint:r("将打开内嵌窗口;登录完成后自动加入账号列表。关掉窗口即取消等待")},{value:"external",label:r("系统浏览器"),hint:r("将用系统默认浏览器打开授权页(会复用浏览器里已登录的华为云账号);授权码由网关轮询云端取回,与浏览器跑在哪台机器无关,完成后自动加入账号列表")}]},manualTitle:r("粘贴网关凭据"),manualNoteHtml:r("从别的机器(或 OfficeAce 桌面端 models.json)取三项贴进来:模型网关基址(baseUrl,形如 https://modelgw-…/v2)与 modelAppKey / modelAppSecret。这三项就能转发(网关凭据不过期);控制面临时凭据(accessKeyId 等)可选,留空则额度/自动续期不可用,但不影响转发。"),fields:[{key:"baseUrl",label:r("模型网关基址"),placeholder:"https://modelgw-…huaweicloud-agentarts.com/v2"},{key:"modelAppKey",label:r("网关 Key"),placeholder:"model_app_key"},{key:"modelAppSecret",label:r("网关 Secret"),placeholder:"model_app_secret"},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空用「OfficeAce 果办」")}]},iq={provider:"orcaterm",label:"OrcaTerm",webLogin:{noteHtml:r("在打开的官方授权页里用微信扫码登录(页面会直接显示二维码)。扫码成功后自动加入账号列表。"),button:r("打开网页登录"),hint:r("内嵌窗口打开;扫码完成后自动加入列表,关窗即取消等待"),busyText:r("等待 OrcaTerm 登录完成…")},desktop:!0,desktopHint:r("读取本机 OrcaTerm 客户端登录态(%APPDATA%\\com.orcaterm-desktop.app\\data.bin),需已在 OrcaTerm 客户端登录"),desktopNote:r("读本机客户端当前登录的 OAuth 令牌(明文 JSON,无需解密)。导入后由网关自动续期,无需跟随客户端的 2 小时时效手动换令牌。"),manualTitle:r("粘贴 accessToken"),manualNoteHtml:r("粘贴 OrcaTerm 的 OAuth accessToken(JWT,三段点分;从桌面客户端 data.bin 或 Web 版 Cookie ot_session 获取)。直接粘贴含 Bearer / ot_session= 的整行也行,网关会自己剥成裸 token。添加后由网关自动续期(上游有续期接口),无需跟随 2 小时时效手动更换。"),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("JWT(三段点分;也可直接粘贴 Bearer 整行或 data.bin 内容)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用账号昵称或 userId")}]};function JR(e){const{provider:t,label:a,site:o,siteNote:c}=e;return{provider:t,label:a,desktop:!1,manualTitle:r("粘贴 API 令牌"),manualNoteHtml:r("粘贴 ModelScope 的 API 令牌(ms- 开头,在 {site} 的「访问令牌」页获取)。
    {siteNote}
    这枚令牌两用:网关既用它调推理,也用它读账号身份、魔粒余额与每日签到。令牌长期有效、没有续期接口,失效后重新获取再粘一次即可。",{site:o,siteNote:c}),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("ms- 开头的 API 令牌")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用上游账号昵称")}]}}const cq=JR({provider:"modelscope",label:r("ModelScope 国内版"),site:"modelscope.cn",siteNote:r("这里填国内站(modelscope.cn)的账号:请粘贴国内站的令牌。国际站(modelscope.ai)是另一家 provider、另一套账号,两边的令牌不通用。")}),uq=JR({provider:"modelscope-intl",label:r("ModelScope 国际版"),site:"modelscope.ai",siteNote:r("这里填国际站(modelscope.ai)的账号:请粘贴国际站的令牌。国内站(modelscope.cn)是另一家 provider、另一套账号,两边的令牌不通用。")}),dq={provider:"chatglm",label:"智谱清言",guestLogin:{noteHtml:r("不需要登录:点下面的按钮,网关会直接在智谱清言换发一份访客凭证并加入账号列表(也可以先填个备注名)。访客凭证可以直接用来对话,免费额度由上游按设备发放。

    注意:访客账号没有积分体系 —— 它与「会员积分」「每日登录积分」「活动领取」相关的接口一律需要登录,因此那些能力对访客会如实跳过(账号页的积分、签到中心都不显示读数)。想要积分就用「填写凭证」粘一个已登录账号的令牌,或「导入桌面端登录态」。"),button:r("添加访客账号"),busyText:r("正在换发访客凭证…"),namePlaceholder:r("可选,给这个访客账号起个备注名")},desktop:!0,desktopWindowsOnly:!0,desktopHint:r("读取本机智谱清言客户端登录态(%APPDATA%\\chatglm\\Network\\Cookies),需已在客户端登录"),desktopNote:r("读本机客户端当前的登录态。客户端的 Cookies 是 DPAPI 加密的(Chromium os_crypt),因此仅 Windows 可用;客户端正在运行时可能读不到该文件,先退出客户端再试即可(也可改用「填写凭证」粘贴令牌)。"),manualTitle:r("粘贴访问令牌"),manualNoteHtml:r("粘贴智谱清言的访问令牌(JWT,三段点分)。获取方式:浏览器打开 chatglm.cn 并登录后,在开发者工具的 Application → Cookies 里复制 chatglm_token 的值(也可以直接粘 chatglm_token=…; 整行)。粘贴后会先向上游校验一次,校验通过才落账号;登录账号的积分、签到能力都能用,之后由网关自动续期(上游有续期接口)。"),fields:[{key:"accessToken",label:"accessToken",rows:3,placeholder:r("JWT(三段点分;也可直接粘贴 chatglm_token=… 整行)")},{key:"name",label:r("备注名"),optional:!0,placeholder:r("可选,留空则用账号昵称")}]},eO=[K8,Y8,X8,Q8,Z8,W8,XR({provider:"cline-free",label:"Cline Free",poolNote:r("(免费额度池,模型名带 cline-free/ 前缀)。")}),XR({provider:"cline-pass",label:"Cline Pass",poolNote:r("(订阅池,模型名带 cline-pass/ 前缀,需要账号有对应订阅)。")}),QR({provider:"accio",label:r("国际版"),site:"www.accio.com",siteNote:r("国际版与国内版是**两套独立的账号**(同一账号体系的两个站点),凭证不通用。")}),QR({provider:"accio-cn",label:r("国内版"),site:"www.accio-ai.com",siteNote:r("国内版的登录站点是 www.accio-ai.com,与国际版不是同一站。")}),ZR({provider:"zcode",label:r("国内版"),site:"open.bigmodel.cn",planNote:r("国内版与**国际版是两套独立的账号与套餐**,凭证与领取的套餐都不通用。")}),ZR({provider:"zcode-intl",label:r("国际版"),site:"api.z.ai",planNote:r("国际版的推理站点是 api.z.ai,与国内版不是同一站;套餐也各自独立。")}),J8,eq,tq,nq,sq,rq,aq,lq,oq,iq,dq,cq,uq],Gi="workbuddy",wu="custom",Bj="WorkBuddy";function fq(e){return eO.find(t=>t.provider===e)}const tO=[{id:"guest",label:r("访客模式(免登录)")},{id:"oauth",label:r("网页登录(Zai / Google)")},{id:"sms",label:r("手机验证码登录")},{id:"web",label:r("网页登录")},{id:"manual",label:r("填写凭证")},{id:"file",label:r("导入凭证文件")},{id:"desktop",label:r("导入桌面端登录态")}],Hj=()=>gt().workbuddyDesktop?.platform||"";function nO(e){if(e.desktop===!1)return!1;const t=Hj();return!(t==="web"||e.desktopWindowsOnly&&t!=="windows")}function sO(e,t){return tO.filter(a=>a.id==="guest"?!!e.guestLogin:a.id==="oauth"?!!e.oauthLogin:a.id==="sms"?!!e.smsLogin:a.id==="web"?!!e.webLogin&&(!e.webLogin?.region||t===e.webLogin.region):a.id==="file"?!!e.fileImport:a.id==="desktop"?nO(e):!0).map(a=>a.id)}const pq=e=>e.manualTitle||r("填写凭证添加"),mq=e=>e.manualNoteHtml?{html:e.manualNoteHtml}:{text:e.manualNote||""},hq=e=>e.addButton||r("添加 {name} 账号",{name:e.label}),xg=(e,t)=>`${e.provider}-${t.inputKey||t.key}-input`;function gq(e){return e.source==="subscription"&&(e.port===null||e.port===void 0)}function tr(){return window}function qn(e,t){tr().wbApp?.toast?.(e,t)}function Ra(e){return e instanceof Error?e.message:String(e)}function rO(e){return tr().wbApp?.formatTime?.(e)||""}function Uj(e){const t=Number(e);return!Number.isFinite(t)||t<0?"":t<1e3?`${Math.round(t)}ms`:`${(t/1e3).toFixed(1)}s`}function Vj(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t]||t)}function Su(e){return String(e?.name||e?.id||"")}function aO(e){return e.source==="clash"}function _f(e){return e.source==="subscription"}function bg(e){return aO(e)||_f(e)}function xq(e){return e.localDisabled===!0||e.enabled===!1}function lO(e){return bg(e)&&e.enabled===!1&&e.localDisabled!==!0}function bq(e){return _f(e)&&xq(e)}function vg(e){return _f(e)&&e.orphan===!0}function oO(e){return!bg(e)||vg(e)}const vq=r("来自 Clash Verge 同步(名称、端口跟随 Clash),请到 Clash Verge 中修改;启用可在本页关闭"),yq=r("该节点来自订阅(名称、端口跟随订阅与内核),请在「订阅管理」里修改;启用可在本页关闭"),iO=r("该节点所属订阅已删除,不会再被同步更新,可手动删除清理");function cO(e){return vg(e)?iO:_f(e)?yq:vq}const jq=r("禁用后本端不再用它(引用它的账号回退直连);端口在 Clash Verge 侧,不受影响"),wq=r("禁用后本端不再用它(引用它的账号回退直连),并会关掉它的本地监听端口"),Sq=r("已在本页禁用(打开开关即恢复)"),Nq=r("这条在 Clash Verge 里是停用的,本页启用不生效 —— 到 Clash Verge 里打开它");function kq(e){if(vg(e))return iO;if(e.localDisabled===!0)return Sq;if(lO(e))return Nq;if(_f(e))return wq;if(aO(e))return jq}let xs={data:null,loading:!1,error:"",testing:null,pending:new Set,syncing:!1,batchBusy:!1,batchProgress:null,selected:new Set};const Fj=new Set;function uO(e){return Fj.add(e),()=>{Fj.delete(e)}}function dO(){return xs}function rs(e){xs={...xs,...e},Fj.forEach(t=>t())}function yg(){return xs.data?.items??[]}function Cq(e){return xs.selected.has(e)}function Tq(e,t){const a=new Set(xs.selected);t?a.add(e):a.delete(e),rs({selected:a})}function Eq(e,t){const a=new Set(xs.selected);for(const o of e)t?a.add(o):a.delete(o);rs({selected:a})}function Aq(){rs({selected:new Set})}function Ao(e){if(!e||typeof e!="object"||!Array.isArray(e.items))return;const t=new Set(e.items.map(o=>o.id)),a=new Set([...xs.selected].filter(o=>t.has(o)));rs({data:e,error:"",selected:a})}async function Lf(e=!1){const t=tr().workbuddyDesktop;if(typeof t?.getProxyPool!="function"){rs({error:r("当前环境不支持代理池(桥接方法缺失)")});return}e||rs({loading:!0});try{Ao(await t.getProxyPool())}catch(a){rs({error:Ra(a)}),e||qn(r("代理列表加载失败:{reason}",{reason:Ra(a)}),"err")}finally{rs({loading:!1})}}async function Rq(){const e=tr().workbuddyDesktop;if(typeof e?.syncClashToProxyPool!="function"){qn(r("当前环境不支持同步(桥接方法缺失)"),"err");return}if(!xs.syncing){rs({syncing:!0});try{const t=await e.syncClashToProxyPool();Ao(t),t?.syncError?qn(r("没能同步:{reason}",{reason:t.syncError}),"err"):t?.changes?qn(r("✅ 已同步 Clash Verge 出口({n} 项变更)",{n:t.changes})):qn(r("已是最新,没有需要同步的变更"))}catch(t){qn(r("同步失败:{reason}",{reason:Ra(t)}),"err")}finally{rs({syncing:!1})}}}async function Oq(e){const t=tr().workbuddyDesktop;if(typeof t?.testProxyPoolItem!="function"){qn(r("当前环境不支持代理测试(桥接方法缺失)"),"err");return}if(!xs.testing){rs({testing:e.id});try{const a=await t.testProxyPoolItem(e.id);if(a?.items&&Ao({items:a.items}),a?.success){const o=Uj(a.durationMs);qn(r("✅ 「{name}」出口可用{ip}{took}",{name:Su(e),ip:a.ip?r(" 出口 IP {ip}",{ip:a.ip}):"",took:o?` ${o}`:""}))}else qn(r("❌ 「{name}」{error}",{name:Su(e),error:a?.error||r("连接失败")}),"err");a?.saveError&&qn(r("测试结果没能记下:{reason}",{reason:a.saveError}),"err")}catch(a){qn(r("测试失败:{reason}",{reason:Ra(a)}),"err")}finally{rs({testing:null})}}}async function Mq(e,t){const a=tr().workbuddyDesktop;if(typeof a?.setProxyPoolItemEnabled!="function"){qn(r("当前环境不支持启停(桥接方法缺失)"),"err");return}const o=new Set(xs.pending);o.add(e.id),rs({pending:o});try{const c=await a.setProxyPoolItemEnabled({id:e.id,enabled:t});Ao(c);const d=Su(e),f=c?.listener??"none";qn(t?f==="opening"?r("已启用「{name}」,正在补建监听端口(内核重建中)",{name:d}):r("已启用「{name}」",{name:d}):f==="closing"?r("已禁用「{name}」,监听端口正在关闭(内核重建中)",{name:d}):r("已禁用「{name}」",{name:d})),(f==="closing"||f==="opening")&&Dq(e.id,f)}catch(c){qn(r("保存失败:{reason}",{reason:Ra(c)}),"err")}finally{const c=new Set(xs.pending);c.delete(e.id),rs({pending:c})}}async function Dq(e,t){for(let a=0;a<12;a+=1){await new Promise(d=>setTimeout(d,1500)),await Lf(!0);const o=yg().find(d=>d.id===e);if(!o)return;const c=o.port!==null&&o.port!==void 0;if(t==="closing"?!c:c)return}}async function fO(e){const t=tr().workbuddyDesktop;if(typeof t?.removeProxyPoolItem!="function")return;if(!oO(e)){qn(cO(e),"err");return}const a=e.usedBy||[],o=a.length?`

    ${r("有 {n} 个账号正在使用它({names})—— 删除后这些账号会回退直连。",{n:a.length,names:a.map(f=>Vj(String(f.name||f.id||""))).join(r("、"))})}

    `:"";if(!await tr().wbConfirm?.ask?.({title:r("删除代理"),html:r("确定删除「{name}」?{used}",{name:Vj(Su(e)),used:o}),okText:r("删除"),okClass:"danger"}))return;const d=new Set(xs.pending);d.add(e.id),rs({pending:d});try{const f=await t.removeProxyPoolItem(e.id);Ao(f),qn(r("已删除「{name}」",{name:Su(e)}))}catch(f){qn(r("删除失败:{reason}",{reason:Ra(f)}),"err")}finally{const f=new Set(xs.pending);f.delete(e.id),rs({pending:f})}}async function Iq(){const e=tr().workbuddyDesktop;if(typeof e?.testProxyPoolItem!="function"){qn(r("当前环境不支持代理测试(桥接方法缺失)"),"err");return}if(xs.batchBusy||xs.testing)return;const t=yg().filter(f=>xs.selected.has(f.id));if(!t.length)return;rs({batchBusy:!0,batchProgress:{done:0,total:t.length}});let a=0,o=0,c="";for(const[f,p]of t.entries()){rs({testing:p.id,batchProgress:{done:f,total:t.length}});try{const h=await e.testProxyPoolItem(p.id);h?.items&&Ao({items:h.items}),h?.success?a+=1:o+=1,h?.saveError&&!c&&(c=h.saveError)}catch{o+=1}}rs({testing:null,batchBusy:!1,batchProgress:null});const d=o?r("批量测试完成:{ok} 个可用、{failed} 个失败(共 {total} 个)",{ok:a,failed:o,total:t.length}):r("批量测试完成:{ok} 个可用(共 {total} 个)",{ok:a,total:t.length});qn(o?d:`✅ ${d}`,o?"err":"ok"),c&&qn(r("部分测试结果没能记下:{reason}",{reason:c}),"err")}async function Pq(){const e=tr().workbuddyDesktop;if(typeof e?.removeProxyPoolItem!="function"||xs.batchBusy||xs.testing)return;const t=yg().filter(k=>xs.selected.has(k.id)),a=t.filter(k=>oO(k)),o=t.length-a.length;if(!a.length){qn(o?r("选中的 {n} 条都是同步来的只读条目(Clash / 订阅),不能删除",{n:o}):r("没有可删除的条目"),"err");return}const c=a.slice(0,8).map(k=>Vj(Su(k))).join(r("、")),d=a.length>8?r("{names} 等 {n} 条",{names:c,n:a.length}):c,f=a.filter(k=>(k.usedBy||[]).length).length,p=f?`

    ${r("其中 {n} 条正被账号使用 —— 删除后那些账号会回退直连。",{n:f})}

    `:"",h=o?`

    ${r("另有 {n} 条是同步来的只读条目(Clash / 订阅),将跳过。",{n:o})}

    `:"";if(!await tr().wbConfirm?.ask?.({title:r("批量删除代理"),html:`${r("确定删除选中的 {n} 个代理?",{n:a.length})}

    ${d}

    ${p}${h}`,okText:r("删除"),okClass:"danger"}))return;rs({batchBusy:!0,batchProgress:{done:0,total:a.length}});let y=0,v=0,j="";for(const[k,S]of a.entries()){rs({batchProgress:{done:k,total:a.length}});try{const N=await e.removeProxyPoolItem(S.id);Ao(N),y+=1}catch(N){v+=1,j||(j=Ra(N))}}rs({batchBusy:!1,batchProgress:null});const w=[r("已删除 {n} 个代理",{n:y})];o&&w.push(r("跳过 {n} 个(同步只读条目)",{n:o})),v&&w.push(r("失败 {n} 个({reason})",{n:v,reason:j})),qn(v?w.join(r(",")):`✅ ${w.join(r(","))}`,v?"err":"ok")}async function _q(e,t){const a=tr().workbuddyDesktop,o=e?{...t,id:e.id}:t,c=e?await a?.updateProxyPoolItem?.(o):await a?.createProxyPoolItem?.(o);return Ao(c),c}async function pO(){const e=tr().workbuddyDesktop;if(typeof e?.getProxySettings!="function")throw new Error(r("当前环境不支持代理设置(桥接方法缺失)"));const t=await e.getProxySettings();if(!t||typeof t!="object")throw new Error(r("代理设置响应异常"));return t}async function Lq(e){const t=tr().workbuddyDesktop;if(typeof t?.saveProxySettings!="function")throw new Error(r("当前环境不支持代理设置(桥接方法缺失)"));const a=await t.saveProxySettings(e);if(!a||typeof a!="object")throw new Error(r("代理设置响应异常"));return a}function nr(){return window}function an(e,t){nr().wbApp?.toast?.(e,t)}function Sr(e){return e instanceof Error?e.message:String(e)}let Ft={data:null,loading:!1,error:"",pending:!1,refreshing:null};const $j=new Set;function jg(e){return $j.add(e),()=>{$j.delete(e)}}function wg(){return Ft}function wn(e){Ft={...Ft,...e},$j.forEach(t=>t())}function zq(){return Ft.data?.items??[]}function Nu(){return Ft.data?.kernel??null}function Ki(e){!e||typeof e!="object"||!Array.isArray(e.items)||wn({data:e,error:""})}function Ro(){Lf(!0)}async function Ml(e=!1){const t=nr().workbuddyDesktop;if(typeof t?.getSubscriptions!="function"){wn({error:r("当前环境不支持订阅(桥接方法缺失)")});return}e||wn({loading:!0});try{Ki(await t.getSubscriptions())}catch(a){wn({error:Sr(a)})}finally{e||wn({loading:!1})}}const Bq=20;function Hq(e){const t=e.kernel;if(!t||t.download.state==="downloading")return!1;if(!t.installed||t.lastError&&!t.running)return!0;const a=t.providerSync??{};return(e.items??[]).filter(o=>o.enabled!==!1).every(o=>!!a[o.id])}async function Yi(){const e=nr().workbuddyDesktop;if(typeof e?.getSubscriptions=="function")for(let t=0;tsetTimeout(o,1500)),Ro();let a;try{a=await e.getSubscriptions()}catch{return}if(Ki(a),t>=1&&a&&Array.isArray(a.items)&&Hq(a))return}}async function mO(e){const a=await nr().workbuddyDesktop?.addSubscription?.({enabled:!0,kind:"url",url:"",...e});return Ki(a),an(r("已新增订阅「{name}」,内核正在同步节点…",{name:e.name.trim()})),Ro(),Yi(),a??null}async function hO(e,t){const o=await nr().workbuddyDesktop?.saveSubscription?.({id:e.id,...t});Ki(o),an(r("已保存「{name}」",{name:t.name.trim()})),Ro(),Yi()}async function Uq(e,t){const a=nr().workbuddyDesktop;if(!Ft.pending){wn({pending:!0});try{const o=await a?.saveSubscription?.({id:e.id,name:e.name,url:e.url,kind:e.kind,enabled:t});Ki(o),an(t?r("已启用「{name}」",{name:e.name}):r("已禁用「{name}」",{name:e.name})),Ro(),Yi()}catch(o){an(r("保存失败:{reason}",{reason:Sr(o)}),"err")}finally{wn({pending:!1})}}}async function Vq(e){const t=nr().workbuddyDesktop;if(!(Ft.refreshing||Ft.pending)){wn({refreshing:e.id});try{const a=await t?.refreshSubscription?.(e.id);Ki(a),an(r("已刷新「{name}」,正在同步节点…",{name:e.name})),Ro(),Yi()}catch(a){an(r("刷新失败:{reason}",{reason:Sr(a)}),"err")}finally{wn({refreshing:null})}}}async function Fq(e){const t=nr().workbuddyDesktop;if(await window.wbConfirm?.ask?.({title:r("删除订阅"),html:r("确定删除「{name}」?它在代理池里的节点会一并移除,引用这些节点的账号会回退直连。",{name:e.name||e.id}),okText:r("删除"),okClass:"danger"})&&!Ft.pending){wn({pending:!0});try{const o=await t?.removeSubscription?.(e.id);Ki(o),an(r("已删除「{name}」",{name:e.name||e.id})),Ro(),Yi()}catch(o){an(r("删除失败:{reason}",{reason:Sr(o)}),"err")}finally{wn({pending:!1})}}}async function $q(e){const t=nr().workbuddyDesktop;if(typeof t?.downloadKernel!="function"){an(r("当前环境不支持订阅(桥接方法缺失)"),"err");return}if(!Ft.pending){wn({pending:!0});try{const a=await t.downloadKernel(e);a&&Ft.data&&wn({data:{...Ft.data,kernel:a}}),a?.saved===!1&&an(r("下载线路 / 存放目录没能写进配置(本次下载已按新设置走,重启后会恢复原值)"),"err");for(let c=0;c<300;c+=1){await new Promise(f=>setTimeout(f,1e3));const d=await t.getKernelStatus?.();if(d&&Ft.data&&wn({data:{...Ft.data,kernel:d}}),!d||d.download.state!=="downloading")break}const o=Ft.data?.kernel;o?.download.state==="error"?an(r("内核下载失败:{reason}",{reason:o.download.error||r("未知错误")}),"err"):o?.download.state==="canceled"?an(r("已停止下载内核(未下载完的临时文件已删除)")):o?.download.state==="done"&&(an(r("✅ 内核下载完成,正在启动…")),Yi())}catch(a){an(r("内核下载失败:{reason}",{reason:Sr(a)}),"err")}finally{wn({pending:!1})}}}async function qq(){const e=nr().workbuddyDesktop;if(typeof e?.cancelKernelDownload!="function")return"none";try{const t=await e.cancelKernelDownload();if(t&&Ft.data&&wn({data:{...Ft.data,kernel:t}}),t?.canceled===!1)return"none";for(let o=0;o<20;o+=1){const c=await e.getKernelStatus?.();if(c&&Ft.data&&wn({data:{...Ft.data,kernel:c}}),c&&c.download.state!=="downloading")break;await new Promise(d=>setTimeout(d,250))}const a=Ft.data?.kernel?.download.state;return a==="canceled"?"canceled":a==="done"?"done":"stalled"}catch(t){return an(r("停止下载失败:{reason}",{reason:Sr(t)}),"err"),"none"}}async function Gq(){const e=nr().workbuddyDesktop;if(!Ft.pending){wn({pending:!0});try{const t=await e?.restartKernel?.();t&&Ft.data&&wn({data:{...Ft.data,kernel:t}}),an(r("内核正在启动…")),Ro(),Yi()}catch(t){an(r("内核启动失败:{reason}",{reason:Sr(t)}),"err")}finally{wn({pending:!1})}}}async function Kq(){const e=nr().workbuddyDesktop;if(typeof e?.stopKernel!="function"){an(r("当前环境不支持订阅(桥接方法缺失)"),"err");return}if(!Ft.pending){wn({pending:!0});try{const t=await e.stopKernel();t&&Ft.data&&wn({data:{...Ft.data,kernel:t}});for(let o=0;o<10;o+=1){const c=await e.getKernelStatus?.();if(c&&Ft.data&&wn({data:{...Ft.data,kernel:c}}),c&&c.running===!1)break;await new Promise(d=>setTimeout(d,500))}const a=Ft.data?.kernel;if(a?.running===!1)an(r("内核已关闭(订阅与端口注册表保留,「启动内核」后原位恢复)"));else{const o=a?.lastError||r("内核没有在超时内停下来");an(r("关闭内核失败:{reason}",{reason:o}),"err")}Ml(!0)}catch(t){an(r("关闭内核失败:{reason}",{reason:Sr(t)}),"err"),Ml(!0)}finally{wn({pending:!1})}}}async function Yq(){const e=nr().workbuddyDesktop;if(typeof e?.removeKernel!="function"){an(r("当前环境不支持订阅(桥接方法缺失)"),"err");return}const t=Nu()?.version;if(!await window.wbConfirm?.ask?.({title:r("删除内核"),html:r("确定删除已下载的内核{version}?内核文件与端口映射会被移除,订阅节点会变成「未分配端口」,引用它们的账号会暂时回退直连;订阅本身保留,重新下载内核后会重新分配端口。",{version:t?`(${t})`:""}),okText:r("删除内核"),okClass:"danger"})||Ft.pending)return;wn({pending:!0});const o=Nu()?.lastError||"";try{const c=await e.removeKernel();c&&Ft.data&&wn({data:{...Ft.data,kernel:c}});for(let f=0;f<20;f+=1){const p=await e.getKernelStatus?.();if(p&&Ft.data&&wn({data:{...Ft.data,kernel:p}}),p&&p.installed===!1||p?.lastError&&p.lastError!==o)break;await new Promise(h=>setTimeout(h,500))}const d=Ft.data?.kernel;if(d?.installed===!1)an(r("已删除内核(订阅与账号引用保留,重新下载后会重新分配端口)")),Ro();else{const f=d?.lastError&&d.lastError!==o?d.lastError:r("内核目录没能删掉(可能仍被进程占用),稍后重试一次");an(r("删除内核失败:{reason}",{reason:f}),"err")}Ml(!0)}catch(c){an(r("删除内核失败:{reason}",{reason:Sr(c)}),"err"),Ml(!0)}finally{wn({pending:!1})}}async function Xq(e){const t=nr().workbuddyDesktop;if(typeof t?.decodeQrImage!="function")throw new Error(r("当前环境不支持订阅(桥接方法缺失)"));const a=await new Promise((d,f)=>{const p=new FileReader;p.onload=()=>d(String(p.result||"")),p.onerror=()=>f(new Error(r("图片读取失败"))),p.readAsDataURL(e)}),c=(await t.decodeQrImage({imageBase64:a}))?.url;if(!c)throw new Error(r("二维码里没有订阅链接"));return c}function gO(e){return new Promise((t,a)=>{const o=new FileReader;o.onload=()=>t(String(o.result||"")),o.onerror=()=>a(new Error(r("文件读取失败"))),o.readAsDataURL(e)})}const ku="max-w-full flex-wrap [&_[data-slot=segmented-item]]:h-7 [&_[data-slot=segmented-item]]:px-3 [&_[data-slot=segmented-item]]:text-[12.5px]",Qq=r("登录态文件路径:~/.box-agent/config/auth.json(Windows:C:\\Users\\<你的用户名>\\.box-agent\\config\\auth.json)");let qj=!1;async function Cu(e,t){if(!qj){qj=!0,e(!0);try{await t()}finally{qj=!1,e(!1)}}}function Oo({html:e,text:t}){return e?s.jsx("p",{dangerouslySetInnerHTML:{__html:e}}):s.jsx("p",{children:t||""})}function Zq(e,t,a){let o;try{o=JSON.parse(t)}catch(c){return Ln(r("{name} 不是合法 JSON:{reason}",{name:e.label,reason:Co(c)}),"err"),!1}return!o||typeof o!="object"||Array.isArray(o)?(Ln(r("{name}要粘一个 JSON 对象(形如 {sample})",{name:e.label,sample:'{"codearts_provider_credential":{…}}'}),"err"),!1):(Object.assign(a,o),!0)}function Wq({config:e,region:t,visible:a}){const o=e.provider,[c,d]=x.useState(!1),[f,p]=x.useState(""),h=mq(e),b=e.fields.map(v=>xg(e,v));async function y(){const v={provider:e.provider};e.regionOptions?.length&&(v.mode=t);for(const j of e.fields){const w=dr(xg(e,j));if(!j.optional&&!w){Ln(r("请填写 {label}",{label:j.label}),"err");return}if(w){if(j.jsonExpand){if(!Zq(j,w,v))return;continue}v[j.key]=w}}await Cu(d,async()=>{try{const j=await yu(v);Lj(b),p(""),await To(Pf(j?.account),e.label)}catch(j){Ln(r("添加失败:{reason}",{reason:Co(j)}),"err")}})}return s.jsxs(dn,{hidden:!a,onClick:v=>{v.target.closest("[data-raccoon-hint]")&&(v.preventDefault(),p(Qq))},children:[s.jsx("h3",{children:pq(e)}),s.jsx(Oo,{...h}),e.fields.map(v=>{const j=xg(e,v),w=v.optional?"":r("(必填)");return s.jsxs("div",{className:`field-row${v.rows?" stack":""}`,children:[s.jsxs("label",{htmlFor:j,children:[v.label,w]}),v.rows?s.jsx(Mi,{id:j,rows:v.rows,placeholder:v.placeholder,...Lr(j)}):s.jsx(Fe,{id:j,type:"text",maxLength:G8(v),placeholder:v.placeholder,...Lr(j)})]},j)}),s.jsxs("div",{className:"field-row",children:[s.jsx(ne,{id:`${o}-add-button`,onClick:()=>{y()},disabled:c,children:c?r("添加中…"):hq(e)}),s.jsx("span",{className:"detail",id:`${o}-add-hint`,children:f})]})]})}function Jq({config:e,visible:t}){const a=e.provider,[o,c]=x.useState(!1);if(!nO(e)||!e.desktopNote)return null;async function d(){await Cu(c,async()=>{try{const f=await yu({provider:e.provider,importDesktop:!0});await To(f?.account?.name||"",e.label)}catch(f){Ln(r("导入失败:{reason}",{reason:Co(f)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("从本机导入桌面端登录态")}),s.jsx("p",{children:e.desktopNote}),s.jsx("div",{className:"field-row",children:s.jsx(ne,{id:`${a}-desktop-button`,title:e.desktopHint,onClick:()=>{d()},disabled:o,children:r(o?"导入中…":"从本机导入桌面端登录态")})})]})}function eG({config:e,visible:t}){const a=e.guestLogin,[o,c]=x.useState(!1);if(!a)return null;const d=xg(e,{key:"name"});async function f(){await Cu(c,async()=>{const h=document.getElementById(d)?.value.trim()||"";try{const b=await yu({provider:e.provider,guest:!0,...h?{name:h}:{}});await To(b?.account?.name||"",e.label)}catch(b){Ln(r("添加失败:{reason}",{reason:Co(b)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("访客模式")}),a.noteHtml?s.jsx(Oo,{html:a.noteHtml}):null,s.jsxs("div",{className:"form-field",children:[s.jsx("label",{htmlFor:d,children:r("备注名")}),s.jsx("input",{id:d,type:"text",maxLength:zj,placeholder:a.namePlaceholder||r("可选"),...Lr(d)})]}),s.jsx("div",{className:"field-row",children:s.jsx(ne,{id:`${e.provider}-guest-button`,onClick:()=>{f()},disabled:o,children:o?a.busyText||r("正在添加…"):a.button})})]})}function tG(e){const t=e.indexOf(",");return t>=0?e.slice(t+1):e}function nG({config:e,visible:t}){const[a,o]=x.useState(!1),[c,d]=x.useState(""),f=x.useRef(null),p=e.fileImport,h=`${e.provider}-file-name`;if(!p)return null;async function b(y){const v=e.fileImport;v&&await Cu(o,async()=>{try{const j=dr(h),w={provider:e.provider,authFileName:y.name};if(v.binary)w.authFileB64=tG(await gO(y));else{const S=await y.text();let N;try{N=JSON.parse(S)}catch{Ln(r("选择的文件不是合法 JSON"),"err");return}if(!N||typeof N!="object"||Array.isArray(N)){Ln(r("不是有效的凭证文件:内容要是一个 JSON 对象"),"err");return}w.authFileContent=S}j&&(w.name=j);const k=await yu(w);d(""),await To(Pf(k?.account),e.label)}catch(j){Ln(r("导入失败:{reason}",{reason:Co(j)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("导入凭证文件")}),s.jsx(Oo,{text:p.note}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{className:"lb-inline",htmlFor:h,children:r("备注名")}),s.jsx(Fe,{id:h,type:"text",maxLength:zj,placeholder:r("可选,留空则用文件里的昵称"),...Lr(h)})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("input",{ref:f,type:"file",accept:p.accept,hidden:!0,onChange:y=>{const v=y.target.files?.[0];y.target.value="",v&&(d(v.name),b(v))}}),s.jsx(ne,{onClick:()=>f.current?.click(),disabled:a,children:r(a?"导入中…":"选择凭证文件导入")}),s.jsx("span",{className:"detail",children:c})]})]})}function sG({config:e,mode:t,onModeChange:a,region:o,visible:c}){const d=e.webLogin,f=e.provider,p=x.useRef(t),h=x.useRef(o),b=x.useRef(null);return p.current=t,h.current=o,x.useEffect(()=>{const y=gt().wbWebLogin;if(!y||!d)return;const v=d.modes;b.current=y.create({provider:f,buttonId:`${f}-web-button`,cancelId:`${f}-web-cancel`,hintId:`${f}-web-hint`,busyText:d.busyText,texts:()=>{const j=v?.find(w=>w.value===p.current);return{button:d.button,hint:j?.hint||d.hint||""}},start:()=>gt().workbuddyDesktop?.startLogin(d.edition||h.current||"cn",p.current||"embedded",f),onSuccess:async j=>{_j(),await gt().wbApp?.refresh?.();const w=j?.payload?.warning;w?Ln(r("账号已添加,但请留意:{warning}",{warning:w}),"err"):Ln(r("✅ {label}账号已添加",{label:e.label}))}})??null},[]),x.useEffect(()=>{b.current?.syncTexts()},[t]),d?s.jsxs(dn,{hidden:!c,children:[s.jsx("h3",{children:r("网页登录")}),s.jsx(Oo,{html:d.noteHtml}),d.modes?.length?s.jsxs("div",{className:"flex flex-col gap-2.5 border-l-2 border-border pl-[11px]",children:[s.jsx("span",{className:"text-[12.5px] text-subtle",children:r("打开方式")}),s.jsx(En,{"aria-label":r("{label} 网页登录的打开方式",{label:e.label}),options:d.modes,value:t,onValueChange:a})]}):null,s.jsxs("div",{className:"field-row",children:[s.jsx(ne,{id:`${f}-web-button`,onClick:()=>b.current?.start(),children:d.button}),s.jsx(ne,{id:`${f}-web-cancel`,variant:"outline",hidden:!0,onClick:()=>b.current?.cancel(),children:r("取消等待")}),s.jsx("span",{className:"detail",id:`${f}-web-hint`,children:d.hint||d.modes?.[0]?.hint||""})]})]}):null}function rG({config:e,visible:t}){const a=e.smsLogin,o=e.provider;return x.useEffect(()=>{a&>().wbSmsLogin?.create({provider:o,onSuccess:c=>To(Pf(c?.account),e.label)})},[]),a?s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("手机验证码登录")}),s.jsx(Oo,{html:a.noteHtml,text:r("用 AutoClaw 账号绑定的手机号登录:点击「获取验证码」,收到短信后填入下方并登录。验证码由本机直接提交给官方接口,界面不显示 token。")}),s.jsxs("div",{className:"sms-form",children:[s.jsxs("div",{className:"sms-field",children:[s.jsxs("label",{className:"lb",htmlFor:`${o}-sms-phone`,children:[r("手机号"),s.jsx("i",{className:"req",children:"*"})]}),s.jsxs(Di,{children:[s.jsx(Pi,{id:`${o}-sms-phone`,type:"text",maxLength:11,placeholder:r("11 位大陆手机号"),...Lr(`${o}-sms-phone`)}),s.jsx(Ii,{align:"inline-end",children:s.jsx(D4,{id:`${o}-sms-send`,className:"text-primary-fg",children:r("获取验证码")})})]})]}),s.jsxs("div",{className:"sms-field",children:[s.jsxs("label",{className:"lb",htmlFor:`${o}-sms-code`,children:[r("验证码"),s.jsx("i",{className:"req",children:"*"})]}),s.jsxs("div",{className:"sms-pair",children:[s.jsx(Fe,{id:`${o}-sms-code`,className:"sms-code",type:"text",maxLength:6,placeholder:r("6 位数字")}),s.jsx("label",{className:"lb-inline",htmlFor:`${o}-sms-name`,children:r("备注名")}),s.jsx(Fe,{id:`${o}-sms-name`,className:"sms-name",type:"text",placeholder:r("可选,留空则用脱敏手机号"),...Lr(`${o}-sms-name`)})]})]}),s.jsxs("div",{className:"sms-foot",children:[s.jsx(ne,{id:`${o}-sms-submit`,children:r("登录并添加")}),s.jsx("span",{className:"detail sms-hint",id:`${o}-sms-hint`})]})]})]}):null}function aG({config:e,mode:t,onModeChange:a,visible:o}){const c=e.oauthLogin,d=e.provider,f=x.useRef(t),p=x.useRef(null);f.current=t;const h=()=>c?.modes?.find(b=>b.value===f.current)?.hint||c?.hint||"";return x.useEffect(()=>{const b=gt().wbAutoclawOauth;!b||!c||(p.current=b.create({provider:d,mode:()=>f.current||"embedded",hint:h,cancelId:`${d}-oauth-cancel`,onSuccess:()=>To("",e.label)})??null)},[]),x.useEffect(()=>{p.current?.syncTexts()},[t]),c?s.jsxs(dn,{hidden:!o,children:[s.jsx("h3",{children:c.title||r("网页登录")}),s.jsx(Oo,{html:c.noteHtml}),c.modes?.length?s.jsxs("div",{className:"flex flex-col gap-2.5 border-l-2 border-border pl-[11px]",children:[s.jsx("span",{className:"text-[12.5px] text-subtle",children:r("打开方式")}),s.jsx(En,{"aria-label":r("{label} 网页登录的打开方式",{label:e.label}),options:c.modes,value:t,onValueChange:a})]}):null,s.jsxs("div",{className:"field-row",children:[s.jsx(ne,{id:`${d}-oauth-zai`,children:r("使用 Zai 账号登录")}),s.jsx(ne,{id:`${d}-oauth-google`,variant:"outline",children:r("使用 Google 账号登录")}),s.jsx(ne,{id:`${d}-oauth-cancel`,variant:"outline",hidden:!0,children:r("取消")})]}),s.jsx("div",{className:"field-row",children:s.jsx("span",{className:"detail",id:`${d}-oauth-hint`,children:c.modes?.[0]?.hint||c.hint||""})})]}):null}function lG({config:e,active:t}){const a=e.regionOptions?.[0]?.value??"",[o,c]=x.useState(a),[d,f]=x.useState(()=>sO(e,a)[0]),[p,h]=x.useState(e.webLogin?.modes?.[0]?.value??""),[b,y]=x.useState(e.oauthLogin?.modes?.[0]?.value??""),v=sO(e,o),j=v.includes(d)?d:v[0],w=x.useMemo(()=>tO.filter(k=>v.includes(k.id)).map(k=>({value:k.id,label:k.label})),[v.join(",")]);return s.jsxs("div",{className:"add-provider-block",hidden:!t,children:[e.regionOptions?.length?s.jsxs(dn,{children:[s.jsx("h3",{children:r("地区")}),s.jsx(En,{"aria-label":r("{label} 账号地区",{label:e.label}),className:ku,options:e.regionOptions,value:o,onValueChange:c})]}):null,s.jsxs(dn,{children:[s.jsx("h3",{children:r("添加方式")}),s.jsx(En,{"aria-label":r("{label} 账号的添加方式",{label:e.label}),className:ku,options:w,value:j,onValueChange:k=>f(k)})]}),s.jsx(eG,{config:e,visible:j==="guest"}),s.jsx(aG,{config:e,mode:b,onModeChange:y,visible:j==="oauth"}),s.jsx(rG,{config:e,visible:j==="sms"}),s.jsx(sG,{config:e,mode:p,onModeChange:h,region:o,visible:j==="web"}),s.jsx(Wq,{config:e,region:o,visible:j==="manual"}),s.jsx(nG,{config:e,visible:j==="file"}),s.jsx(Jq,{config:e,visible:j==="desktop"})]})}const oG=r("官方客户端凭证目录:Windows 是 C:\\Users\\<你的用户名>\\AppData\\Local\\CodeBuddyExtension\\Data\\Public\\auth,macOS 是 ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth"),Sg="workbuddy-file-name";function Gj(e,t,a){const o=e[a],c=[];o&&typeof o=="object"&&!Array.isArray(o)&&c.push(o),c.push(e);for(const d of c)for(const f of t){const p=d[f];if(typeof p=="string"&&p.trim())return p.trim()}return""}function iG(e){const t=Gj(e,["domain"],"auth");return/workbuddy\.ai/i.test(t)?"intl":/workbuddy\.cn|codebuddy\.cn/i.test(t)?"cn":null}function cG({edition:e,visible:t}){const[a,o]=x.useState(!1),[c,d]=x.useState(""),f=x.useRef(null);async function p(h){await Cu(o,async()=>{try{let b;try{b=JSON.parse(await h.text())}catch{Ln(r("选择的文件不是合法 JSON"),"err");return}if(!b||typeof b!="object"||Array.isArray(b)){Ln(r("不是有效的凭证文件:内容要是一个 JSON 对象"),"err");return}const y=b,v=Gj(y,["accessToken","token","access_token"],"auth"),j=Gj(y,["uid"],"account");if(!v||!j){Ln(r("不是有效的凭证文件:需要包含 accessToken 与 uid"),"err");return}const w=iG(y),k=w??e;w&&w!==e&&Ln(r("文件是{edition}凭证,已按该版本导入",{edition:r(w==="intl"?"国际版":"国内版")}),"warn");const S=dr(Sg),N={...y,provider:Ng(k)};S&&(N.name=S);const R=await yu(N);d(""),await To(Pf(R?.account),k==="intl"?"WorkBuddy AI":"WorkBuddy")}catch(b){Ln(r("导入失败:{reason}",{reason:Co(b)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("导入凭证文件")}),s.jsx(Oo,{text:r("选择官方客户端的登录态凭证文件(workbuddy-desktop.info / workbuddy-desktop-ai.info)或 wb2api 导出的账号 JSON(嵌套 / 扁平形均可)。")}),s.jsx("p",{className:"detail",children:s.jsx("a",{href:"#",onClick:h=>{h.preventDefault(),d(oG)},children:r("凭证文件在哪?")})}),s.jsxs("div",{className:"field-row",children:[s.jsx("label",{className:"lb-inline",htmlFor:Sg,children:r("备注名")}),s.jsx(Fe,{id:Sg,type:"text",maxLength:100,placeholder:r("可选,留空则用文件里的昵称"),...Lr(Sg)})]}),s.jsxs("div",{className:"field-row",children:[s.jsx("input",{ref:f,type:"file",accept:".info,.json,application/json",hidden:!0,onChange:h=>{const b=h.target.files?.[0];h.target.value="",b&&p(b)}}),s.jsx(ne,{onClick:()=>f.current?.click(),disabled:a,children:r(a?"导入中…":"选择凭证文件导入")}),s.jsx("span",{className:"detail",children:c})]})]})}function uG({edition:e,visible:t}){const[a,o]=x.useState(!1);async function c(){await Cu(o,async()=>{try{const d=await yu({provider:Ng(e),importDesktop:!0});await To(Pf(d?.account),e==="intl"?"WorkBuddy AI":"WorkBuddy")}catch(d){Ln(r("导入失败:{reason}",{reason:Co(d)}),"err")}})}return s.jsxs(dn,{hidden:!t,children:[s.jsx("h3",{children:r("从本机导入桌面端登录态")}),s.jsx(Oo,{text:r("读本机官方客户端(Tencent WorkBuddy / WorkBuddy AI)当前登录的账号:自动定位其凭证目录里最新的登录态文件(需已在本机官方客户端登录)。导入后由网关自动续期,无需跟随 2 小时时效手动换令牌。")}),s.jsx("div",{className:"field-row",children:s.jsx(ne,{onClick:()=>{c()},disabled:a,children:r(a?"导入中…":"从本机导入桌面端登录态")})})]})}function Ng(e){return e==="intl"?"workbuddy-intl":"workbuddy"}function dG({active:e}){const[t,a]=x.useState(qi.edition),[o,c]=x.useState(qi.loginMode),[d,f]=x.useState(qi.socialRestore),[p,h]=x.useState("web"),b=x.useRef(t),y=x.useRef(o),v=x.useRef(d),j=x.useRef(null);b.current=t,y.current=o,v.current=d,x.useEffect(()=>{const C=gt().wbWebLogin;C&&(j.current=C.create({get provider(){return Ng(b.current)},buttonId:"web-login-button",cancelId:"web-login-cancel",hintId:"web-login-hint",busyText:r("等待网页登录…"),texts:()=>{const E=y.current==="external";return{button:r(E?"在浏览器中打开登录页":"打开网页登录"),hint:r(E?"系统浏览器打开(复用已登录账号);完成后自动加入列表":"内嵌窗口打开;完成后自动加入列表,关窗即取消等待")}},start:()=>gt().workbuddyDesktop?.startLogin(b.current,y.current,Ng(b.current),v.current),onSuccess:async()=>{const E=b.current==="intl"?r("国际版"):r("国内版");_j(),await gt().wbApp?.refresh?.(),Ln(r("✅ 登录成功,{edition}账号已加入列表",{edition:E}))}})??null)},[]),x.useEffect(()=>{j.current?.syncTexts()},[t,o]);function w(C){const E=C==="intl"?"external":"embedded";a(C),qi.edition=C,c(E),qi.loginMode=E}function k(C){const E=C==="external"?"external":"embedded";c(E),qi.loginMode=E}const S=t==="intl",R=S&&o==="embedded",P=r(R?"国际版登录页默认只显示邮箱登录,勾选后恢复 Google / GitHub / X 入口":S?"只有「内嵌窗口」能恢复第三方入口:系统浏览器里我们无法改动登录页":"国内版登录页没有 Google / GitHub 入口(它用微信 / 手机号 / 邮箱登录)"),T=p==="desktop"&&Hj()==="web"?"web":p;return s.jsxs("div",{className:"add-provider-block",hidden:!e,children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("账号版本")}),s.jsx("p",{children:r("两版账号可同时保存,各自一份模型清单(国内版与国际版是两家提供商,可分别启用与映射)。")}),s.jsx(En,{"aria-label":r("账号版本"),className:ku,options:[{value:"cn",label:r("国内版(WorkBuddy)")},{value:"intl",label:r("国际版(WorkBuddy AI)")}],value:t,onValueChange:C=>w(C)})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("添加方式")}),s.jsx(En,{"aria-label":r("{label} 账号的添加方式",{label:"WorkBuddy"}),className:ku,options:[{value:"web",label:r("网页登录")},{value:"file",label:r("导入凭证文件")},...Hj()!=="web"?[{value:"desktop",label:r("导入桌面端登录态")}]:[]],value:T,onValueChange:C=>h(C)})]}),s.jsxs(dn,{hidden:T!=="web",children:[s.jsx("h3",{children:r("网页登录")}),s.jsx("p",{children:r("完成登录后自动加入账号列表,昵称取自上游。")}),s.jsxs("div",{className:"field-row",children:[s.jsx("span",{className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("打开方式")}),s.jsx(En,{"aria-label":r("网页登录的打开方式"),className:ku,options:[{value:"embedded",label:r("内嵌窗口")},{value:"external",label:r("系统默认浏览器")}],value:o,onValueChange:k}),s.jsxs("label",{className:"flex items-center gap-2",title:P,children:[s.jsx(Zn,{checked:d,disabled:!R,onCheckedChange:C=>{f(C),qi.socialRestore=C}}),s.jsx("span",{className:"text-[12.5px] text-subtle",children:r("恢复 Google / GitHub 入口")})]})]}),s.jsx("p",{children:r("系统浏览器可复用已有登录态(国际版推荐);内嵌窗口更干净。")}),s.jsxs("div",{className:"field-row",children:[s.jsx(ne,{id:"web-login-button",onClick:()=>j.current?.start(),children:r("打开网页登录")}),s.jsx(ne,{id:"web-login-cancel",variant:"outline",hidden:!0,onClick:()=>j.current?.cancel(),children:r("取消等待")}),s.jsx("span",{className:"detail",id:"web-login-hint",children:r("内嵌窗口打开;完成后自动加入列表,关窗即取消等待")})]})]}),s.jsx(cG,{edition:t,visible:T==="file"}),s.jsx(uG,{edition:t,visible:T==="desktop"})]})}const Kj="proxy",Yj="preset",kg="custom",fG="import",zf="preset:",Xj="__new__";function pG(e){return e===Yj||e===kg?e:Kj}const Cg={workbuddy:"assets/providers/workbuddy.png","workbuddy-intl":"assets/providers/workbuddy.png",raccoon:"assets/providers/raccoon.png",catpaw:"assets/providers/catpaw.png",autoclaw:"assets/providers/autoclaw.png","autoclaw-intl":"assets/providers/autoclaw.png",qoder:"assets/providers/qoder.png","qoder-intl":"assets/providers/qoder.png","cline-free":"assets/providers/cline.png","cline-pass":"assets/providers/cline.png",accio:"assets/providers/accio.png","accio-cn":"assets/providers/accio.png",zcode:"assets/providers/zcode.png","zcode-intl":"assets/providers/zcode.png",codearts:"assets/providers/codearts.png",trae:"assets/providers/trae.png",loomy:"assets/providers/loomy.png",kuku:"assets/providers/kuku.png",monkeycode:"assets/providers/monkeycode.png","monkeycode-intl":"assets/providers/monkeycode.png",commandcode:"assets/providers/commandcode.png",antigravity:"assets/providers/antigravity.png",officeace:"assets/providers/officeace.png",orcaterm:"assets/providers/orcaterm.png",modelscope:"assets/providers/modelscope.png","modelscope-intl":"assets/providers/modelscope.png",chatglm:"assets/providers/chatglm.png"},mG=new Set(["cline-pass"]);function hG(e){const t=gt().wbProviders;if(e===Yj)return(gt().wbPresetProviders?.list||[]).map(h=>{const b=KR(h);return{id:zf+h.key,label:h.name,count:b?Pj(b.id):0,preset:!0,builtId:b?.id||""}});if(e===kg)return(t?.customList?.()||[]).filter(h=>!$8(h)).map(h=>({id:h.id,label:h.name||h.id,count:Pj(h.id),custom:!0}));const a=(t?.all?.()||[]).filter(h=>!mG.has(String(h?.id||""))),o=(h,b)=>h===Gi?Bj:r(gt().wbProviders?.labelOf?.(h)||b),d=(a.length?a.map(h=>{const b=String(h.id||"");return{id:b,label:o(b,String(h.label||h.id||"")),count:Number(h.count)||0}}):[{id:Gi,label:Bj,count:Pj(Gi)}]).filter(h=>h.id!=="workbuddy-intl"),f=d.findIndex(h=>h.id==="autoclaw-intl"),p=d.findIndex(h=>h.id==="autoclaw");return p>=0&&f>p&&d.splice(p+1,0,d.splice(f,1)[0]),d}function gG({item:e}){const t=e.id.startsWith(zf)?gt().wbPresetProviders?.iconOf?.(e.id.slice(zf.length))||"":Cg[e.id];if(t)return s.jsx("span",{className:"add-provider-logo has-icon",children:s.jsx("img",{src:t,alt:"",loading:"lazy"})});const a=String(e.label||"?").trim().slice(0,1).toUpperCase()||"?";return s.jsx("span",{className:"add-provider-logo",children:a})}function xG(e){return e.preset?e.builtId?e.count?r("已建过 · {n} 个账号,点击继续添加",{n:e.count}):r("已建过,点击继续添加账号"):r("点开即预填,填 Key 接入"):e.custom?e.count?r("{n} 个账号,点击添加",{n:e.count}):r("点击添加账号"):e.count?r("{n} 个账号",{n:e.count}):r("还没有账号")}function bG({item:e,onPick:t}){return s.jsxs("button",{type:"button",className:"add-provider-card","data-provider":e.id,role:"option",onClick:()=>t(e.id),children:[s.jsx(gG,{item:e}),s.jsxs("span",{className:"add-provider-info",children:[s.jsx("span",{className:"add-provider-name",children:e.label}),s.jsx("span",{className:"add-provider-meta",children:xG(e)})]}),s.jsx("span",{className:"add-provider-go",children:"›"})]})}function vG({onPick:e}){return s.jsxs("button",{type:"button",className:"add-provider-card is-new","data-provider":Xj,role:"option",onClick:()=>e(Xj),children:[s.jsx("span",{className:"add-provider-logo is-new",children:"+"}),s.jsxs("span",{className:"add-provider-info",children:[s.jsx("span",{className:"add-provider-name",children:r("新建自定义提供商")}),s.jsx("span",{className:"add-provider-meta",children:r("接入一个兼容上游")})]}),s.jsx("span",{className:"add-provider-go",children:"›"})]})}function yG({accountType:e,onAccountTypeChange:t,search:a,onSearchChange:o,onPick:c,version:d,importing:f,importPanel:p}){const h=x.useMemo(()=>hG(e),[e,d]),b=a.trim().toLowerCase(),y=h.filter(j=>!b||j.label.toLowerCase().includes(b)),v=e===kg&&!b;return s.jsxs(dn,{children:[s.jsx("h3",{children:r("选择提供商")}),s.jsxs("div",{className:"add-pick-row",style:f?{display:"none"}:void 0,children:[s.jsx(En,{"aria-label":r("账号类型"),className:ku,options:[{value:Kj,label:"Agent"},{value:Yj,label:r("预置 API")},{value:kg,label:r("自定义")}],value:e,onValueChange:j=>t(pG(j))}),s.jsx("span",{id:"add-search-wrap",className:"add-provider-search ml-auto max-w-[340px] min-w-0 flex-[1_1_200px]",children:s.jsxs(Di,{children:[s.jsx(Ii,{children:"⌕"}),s.jsx(Pi,{id:"add-provider-search",type:"search",placeholder:r("搜索提供商…"),autoComplete:"off","aria-label":r("搜索提供商"),value:a,onChange:j=>o(j.currentTarget.value)})]})})]}),p,s.jsxs("div",{className:"add-provider-grid",id:"add-provider-grid",role:"listbox","aria-label":r("选择要添加账号的提供商"),style:f?{display:"none"}:void 0,children:[v?s.jsx(vG,{onPick:c}):null,y.map(j=>s.jsx(bG,{item:j,onPick:c},j.id)),!y.length&&b?s.jsx("div",{className:"add-provider-empty",children:r("没有匹配「{keyword}」的提供商",{keyword:a.trim()})}):null]})]})}function Tg(e,t){return Pe().wbIcons?.icon?.(e,t)||""}function jG({account:e,rank:t}){const a=r("组内第 {rank} 位",{rank:t});return s.jsxs("div",{className:"order-cell",children:[s.jsx("span",{className:"order-grip",role:"button",tabIndex:-1,"aria-label":r("拖动调整组内顺序"),title:r("按住拖动,调整这个账号在本组内的顺序"),dangerouslySetInnerHTML:{__html:Tg("gripVertical",14)}}),s.jsx("span",{className:"order-rank",title:a,children:`#${t}`})]})}function wG({group:e,ids:t,collapsed:a}){const[o,c]=x.useState(!1),d="w-full justify-start px-2 font-normal";return s.jsxs(wf,{open:o,onOpenChange:c,children:[s.jsx(Yh,{render:s.jsx("button",{type:"button",className:"grp-iconbtn",title:r("本组操作")}),children:"⋯"}),s.jsx(Sf,{align:"end",sideOffset:4,className:"w-[196px] p-1.5",children:s.jsxs("div",{className:"flex flex-col gap-0.5",children:[s.jsx(ne,{variant:"ghost",size:"sm",className:d,title:r("启用这一组里的全部账号(含被筛选隐藏的)"),onClick:()=>{c(!1),ER(t,!0)},children:r("全部启用({n})",{n:t.length})}),s.jsx(ne,{variant:"ghost",size:"sm",className:d,title:r("禁用这一组里的全部账号(含被筛选隐藏的)"),onClick:()=>{c(!1),ER(t,!1)},children:r("全部禁用({n})",{n:t.length})}),s.jsx(ne,{variant:"ghost",size:"sm",className:d,title:r("打开批量操作弹窗,并预选这一组的账号(改代理等动作在弹窗里挑参数)"),onClick:()=>{c(!1),kj(t,"proxy")},children:r("批量操作本组")}),s.jsx("div",{className:"my-1 h-px bg-hairline"}),s.jsx(ne,{variant:"ghost",size:"sm",className:d,onClick:()=>{c(!1),iR(e.provider)},children:r(a?"展开这一组":"折叠这一组")})]})})]})}function SG({group:e,collapsed:t,colSpan:a}){const o=Cg[e.provider];return s.jsx("tr",{className:"grp-band","data-provider":e.provider,children:s.jsx("td",{colSpan:a,children:s.jsxs("div",{className:"grp-band-inner",children:[s.jsx("span",{className:"queue-grip",role:"button",tabIndex:-1,"aria-label":r("拖动调整整组顺序"),title:r("按住拖动,调整这一家的组顺位(整组一起动)"),dangerouslySetInnerHTML:{__html:Tg("gripVertical",14)}}),s.jsx("span",{className:"grp-rank",title:r("组顺位:越小越先用(拖动分组带调整)"),children:r("第 {rank} 顺位",{rank:e.rank})}),s.jsx("span",{className:"grp-logo",children:o?s.jsx("img",{src:o,alt:"",loading:"lazy"}):s.jsx("span",{className:"grp-logo-txt",children:String(e.label||"?").trim().slice(0,1).toUpperCase()})}),s.jsx("span",{className:"grp-name",children:r(e.label)}),s.jsx("span",{className:"grp-stat",children:r("{total} 个账号 · 启用 {enabled} · 禁用 {disabled}{limited}",{total:e.members.length,enabled:e.enabled,disabled:e.disabled,limited:e.limited>0?r(" · 限流 {n}",{n:e.limited}):""})}),s.jsx("span",{className:"grp-spacer"}),s.jsx("button",{type:"button",className:"grp-iconbtn grp-fold","aria-expanded":!t,title:r(t?"展开这一组":"折叠这一组"),onClick:()=>iR(e.provider),dangerouslySetInnerHTML:{__html:Tg("chevronDown",14)}}),s.jsx(wG,{group:e,ids:e.accounts.map(c=>c.id),collapsed:t})]})})})}function NG({account:e}){const t=ur(e),a=S$(e);!t&&p$(e,Rl(e))&&a.push({text:r("Token 限额 · 已禁用"),kind:"bad",title:r("本周期 Token 消耗达到限制器的上限,账号已被自动禁用(窗口重置也不恢复,需手动启用)")});const o=gu(e)||e.id;return s.jsxs(s.Fragment,{children:[s.jsx(Zn,{checked:t,"aria-label":r("{action}{who}",{action:r(t?"禁用":"启用"),who:o}),title:r(t?"已启用,点击禁用(不参与转发)":"已禁用,点击启用"),onCheckedChange:c=>{CR(e.id,c)}}),a.length?s.jsx("div",{className:"status-tags",children:a.map(c=>s.jsx(ze,{shape:"tag",variant:c.kind==="bad"?"destructive":"secondary",title:c.title,children:c.text},c.text))}):null]})}function kG({account:e,open:t}){const a=bj(e);if(!a.length)return Zh(e,Wa(e))?s.jsx(ze,{variant:"warning",shape:"tag",title:r("余额低于限制器的阈值,转发时会跳过该账号(余额回升自动恢复)"),children:r("余额不足")}):fj(e,Rl(e))?s.jsx(ze,{variant:"warning",shape:"tag",title:r("本周期 Token 消耗达到限制器的上限,转发时会跳过该账号(窗口重置自动恢复)"),children:r("Token 限额")}):s.jsxs(ze,{variant:"success",shape:"tag",title:r("当前没有任何模型处于限流中"),children:[s.jsx(my,{}),r("正常")]});const o=jj(a[0].resetAt);return s.jsxs(s.Fragment,{children:[s.jsx(ze,{variant:"warning",shape:"tag",render:s.jsx("button",{type:"button"}),className:t?"ring-2 ring-warning-soft":void 0,title:r("点击{action}各模型的限流明细",{action:r(t?"收起":"查看")}),onClick:()=>dR(e.id,"limits",!t),children:r("{n} 个模型 ▾",{n:a.length})}),s.jsx("span",{className:"lim-sub",title:r("最早恢复"),children:r("最早 {soonest} 恢复",{soonest:o===yj?r("待定"):o})})]})}function CG({account:e}){const t=cr(An(e)),a=MA(t.edition?e.expiresAt:e[t.expiry]);if(!a)return s.jsx("span",{className:"muted",title:r("记录里没有过期时间"),children:"—"});const o=a-Date.now();if(o<=0)return s.jsx(ze,{variant:"destructive",shape:"tag",title:r("凭证已过期,转发时会先刷新"),children:r("已过期")});const c=o<36e5?r("{n} 分钟后",{n:Math.max(1,Math.round(o/6e4))}):o<48*36e5?r("{n} 小时后",{n:(o/36e5).toFixed(1)}):r("{n} 天后",{n:Math.floor(o/24/36e5)}),d=Ls(a);return s.jsx("span",{title:d?r("{text}过期({full})",{text:c,full:d}):r("{text}过期",{text:c}),children:c})}function TG({account:e}){const t=xR(e.id);return t<=0?null:s.jsx("span",{className:"conn-count",title:r("{n} 个请求正在使用该账号(含还在下发内容的流式请求)",{n:t}),children:t})}function EG(e){return!e||typeof e!="object"||Array.isArray(e)?"":xO(e.subscription)}function xO(e){if(!e||typeof e!="object")return"";const t=e,a=[];t.planName&&a.push(r("套餐 {name}",{name:String(t.planName)})),t.status&&a.push(r("状态 {status}",{status:String(t.status)})),t.state&&String(t.state)!=="active"&&a.push(qA(t.state));const o=t.expireAt;if(o!=null&&o!==""){const c=Number(o),d=Number.isFinite(c)&&c>1e11?Ls(c):String(o);d&&a.push(r("到期 {time}",{time:d}))}return Number.isFinite(Number(t.remainQuota))&&a.push(r("余量 {value}",{value:ss(t.remainQuota)})),Number.isFinite(Number(t.totalQuota))&&a.push(r("总量 {value}",{value:ss(t.totalQuota)})),a.join(" ")}function AG(e){if(!e||typeof e!="object"||Array.isArray(e))return[];const t=e.plans;return Array.isArray(t)?t.filter(a=>a&&typeof a=="object"&&String(a.state||"")==="pending"):[]}function RG(e){const t=e.map(a=>{const o=String(a.name||a.planId||r("套餐")),c=Number(a.pendingUntil??a.startsAt);return Number.isFinite(c)&&c>0?r("{name}({time} 起生效)",{name:o,time:Ls(c*1e3)}):o});return r(`已领到、还没到生效时间的套餐(生效后余额列会按它显示): {lines}`,{lines:t.join(` -`)})}function TG(e){if(e===void 0)return{text:r("未查询"),kind:"muted",title:r("尚未查询该账号的余额")};if(e===null)return{text:r("查询中…"),kind:"muted",title:r("正在查询")};const t=gu(e);if(t)return t.notConfigured?{text:r("未配置"),kind:"muted",title:r("{message}(去该账号的「设置」里填上查询凭证即可)",{message:t.message})}:{text:r("查询失败"),kind:"bad",title:t.message};if(typeof e!="object"||e===null)return{text:r("无数据"),kind:"muted",title:String(e)};const a=e;if(Object.prototype.hasOwnProperty.call(a,"totalLeft")){const o=a.unlimited?"∞":ss(a.totalLeft);return{text:r("可用 {total}",{total:o}),kind:"ok",title:r("总剩余 {total} · 套餐 {plan} · 奖励 {bonus}",{total:o,plan:ss(a.planLeft),bonus:ss(a.bonusLeft)})}}if(Object.prototype.hasOwnProperty.call(a,"available")||Array.isArray(a.wallets)){const o=String(a.unit||r("积分")),c=Array.isArray(a.wallets)?a.wallets:[],d=c.map(j=>`${j?.displayName||j?.type||r("明细")} ${j?.balanceView?String(j.balanceView):ss(j?.balance)}`).join(" · "),f=gO(a.subscription),p=[];if(c.length===0&&Array.isArray(a.plans)&&a.plans.length>0){const j=xO(a);p.push(j&&bO(j)?r("读数里没有额度桶,这里按套餐权益里的已用 / 总量显示(上游给的数)"):r("上游的余额读数里没有这个套餐的额度桶,剩余量读不到;余额列显示的是套餐发放的权益额度,不是剩余量"))}String(a.walletsFrom||"")==="monitor"&&p.push(r("额度窗口读数来自开放平台监控通道(套餐 JWT 那条通道没有额度桶):读的是每 N 小时 / 每周窗口的剩余比例"));const h=a.available==null?c.find(j=>j?.balance!=null):void 0,b=a.availableView?String(a.availableView):h?r("可用 {value} {unit}",{value:ss(h.balance),unit:String(h.unit||o)}):r("可用 {value} {unit}",{value:ss(a.available),unit:o}),y=[a.statisticsError?r("订阅统计未读到:{error}",{error:String(a.statisticsError)}):"",a.benefitError?r("福利网关未读到:{error}",{error:String(a.benefitError)}):""].filter(Boolean),v=a.benefitAbsent?[r("该账号没有福利模型额度(福利按活动下发,不是每个账号都有)")]:[];return{text:b+(y.length?" ⚠":""),kind:y.length?"warn":"ok",title:[b,d,f,...p,...v,...y].filter(Boolean).join(" · ")}}return{text:r("无数据"),kind:"muted",title:r("未返回可识别的余额数据")}}function xO(e){const t=Array.isArray(e.plans)?e.plans:[],a=o=>String(o?.state||"");return t.find(o=>a(o)==="active")||t.find(o=>a(o)==="pending")||t[0]||null}function EG(e){const t=Array.isArray(e.entitlements)?e.entitlements:[];let a=null;for(const o of t){const c=Number(o?.grantUnits);if(!Number.isFinite(c)||c<=0)continue;const d=String(o?.unitType||"").trim();(!a||c>a.units)&&(a={units:c,unit:d})}return a}function bO(e){const t=Array.isArray(e.entitlements)?e.entitlements:[];for(const a of t){const o=Sr(a?.totalUnits);if(o===null||o<=0)continue;const c=Sr(a?.usedUnits),d=Sr(a?.remainingUnits),f=c===null?d===null?null:Math.max(0,o-d):c;if(f!==null)return{used:f,total:o,unit:String(a?.unitType||"").trim()}}return null}function AG(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const t=e,a=Array.isArray(t.wallets)?t.wallets:[];let o=null;for(const p of a){const h=Number(p?.total);!Number.isFinite(h)||h<=0||(!o||h>Number(o.total))&&(o=p)}const c=t.subscription&&typeof t.subscription=="object"?t.subscription:{};if(!o){let p=null;for(const j of a){const w=Sr(j?.remainingPercent);w!==null&&(!p||w0?r("重置 {date}",{date:Ls(w)}):"";o.push({name:b,view:j,tone:v===null?"muted":v<20?"warn":"ok",percent:v,over:!1,title:[d||[b,h].filter(Boolean).join(" "),j,S].filter(Boolean).join(" · "),variant:"compact",percentText:v===null?"":`${Math.round(v)}%`,windowShort:h,id:String(c.key||"").trim()||b})}return o}function MG(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const t=e.subscription&&typeof e.subscription=="object"?e.subscription:{},a=String(t.planName||"").trim();return a?{text:KA(a),free:hj(a)}:null}function Oo(e){const t=Number.isFinite(e)?Number(e.toFixed(2)):e,a=window.wbUnits;return a?.formatTokens?a.formatTokens(t):String(t)}function DG(e){return e.includes("福利")?r("福利日额度"):e.includes("对话")?r("对话 token"):e}function IG(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const t=e,a=Array.isArray(t.wallets)?t.wallets:[];if(!a.length)return null;const o=String(t.unit||r("积分")),c=[],d=[];for(const h of a){const b=String(h.displayName||h.type||r("明细")),y=Sr(h.creditRemaining),v=Sr(h.creditTotal),j=String(h.balanceView||"")||ss(h.balance),w=Sr(h.usedPercent);if(y!==null){const S=v!==null&&v>0,N=S?Math.max(0,Math.min(100,y/v*100)):null;c.push({name:b,view:S?r("剩 {remaining} / {total}",{remaining:ss(y),total:ss(v)}):r("剩 {remaining}",{remaining:ss(y)}),tone:y<=0?"muted":N!==null&&N<20?"warn":"ok",percent:N,over:!1,title:S?void 0:r("上游未给总量,画不出剩余比例")});continue}if(w!==null||Sr(h.allowanceTokens)!==null){const S=Sr(h.usedTokens)??0,N=Sr(h.allowanceTokens),k=N!==null&&N>1,A=k&&S>N,P=h.unlimited===!0,R=k?Math.max(0,Math.min(100,(1-S/N)*100)):null,C=P?r("无上限 · 已用 {used}",{used:Oo(S)}):k?r("剩 {remaining} / {total}",{remaining:Oo(Math.max(0,N-S)),total:Oo(N)}):S>0?r("已用 {used}",{used:Oo(S)}):r("未使用");d.push({name:DG(b),view:C,tone:A?"bad":!k&&!P?"muted":R!==null&&R<20?"warn":"ok",percent:R,over:A,title:[j,P?r("无上限按日计(上游到达上限后仍继续计数,超额如实显示)"):null].filter(Boolean).join(" · ")});continue}d.push({name:b,view:j,tone:"muted",percent:null,over:!1,title:j})}const f=t.subscription&&typeof t.subscription=="object"?t.subscription:{},p=[t.statisticsError?r("订阅统计未读到:{error}",{error:String(t.statisticsError)}):"",t.benefitError?r("福利网关未读到:{error}",{error:String(t.benefitError)}):""].filter(Boolean);return{credit:c,token:d,total:Sr(t.available),unit:o,plan:KA(f.planName),free:hj(f.planName),resetDate:String(f.resetDate||""),missing:p,benefitAbsent:t.benefitAbsent===!0}}function PG(e){const t=Rl(e);let a=null;for(const v of c$(e)){if(v.enabled===!1)continue;const j=Nf(v,t);if(!j)continue;const w=v.threshold>0?j.used/v.threshold:0;if(w>=1){a={rule:v,reading:j,ratio:w};break}(!a||w>a.ratio)&&(a={rule:v,reading:j,ratio:w})}if(!a)return null;const{rule:o,reading:c}=a,d=c.used>=o.threshold,f=pj(o),p=d?"":` · ${Zh(f.remainingMs,f.daily)}`,h=f.daily?r("今日已用"):r("周期 Token"),b=o.reset==="daily"?r("今天(本地 0 点重置)"):r("{period}窗口",{period:HA(o.period??0)}),y=r("限制器:{window}已用 {used} / {threshold} Token",{window:b,used:Math.round(c.used).toLocaleString("en-US"),threshold:Math.round(o.threshold).toLocaleString("en-US")})+(d?r(",已达到上限"):r(",{countdown}重置",{countdown:Zh(f.remainingMs,f.daily)}));return s.jsxs("span",{className:"usage-token-sub",title:y,children:[h," ",s.jsx("span",{className:d?"hit":void 0,children:El(c.used)})," ","/ ",El(o.threshold),p]})}function _G({account:e}){if(!Ea(e))return s.jsx("span",{className:"muted",title:r("该提供商没有余额查询"),children:"—"});const t=Wa(e),a=TG(t),o=Qh(e,t)?s.jsx(ze,{variant:"warning",shape:"tag",title:r("余额低于限制器的阈值,转发时会跳过该账号(余额回升自动恢复)"),children:r("余额不足 · 已跳过")}):fj(e,Rl(e))?s.jsx(ze,{variant:"warning",shape:"tag",title:r("本周期 Token 消耗达到限制器的上限,转发时会跳过该账号(窗口重置自动恢复)"),children:r("Token 限额 · 已跳过")}):null,c=PG(e),d=a.kind==="ok"||a.kind==="warn"?kG(t):[],f=d.length?s.jsx(ze,{variant:"warning",shape:"tag",title:CG(d),children:r("待生效 {n} 份",{n:d.length})}):null,p=a.kind==="ok"||a.kind==="warn"?Q6(t):[],h=GA(e)&&p.length?{rows:p,subscriptionLine:NG(t),kind:a.kind,title:a.title}:null,b=a.kind==="ok"||a.kind==="warn"?OG(t):[];if(b.length){const j=MG(t);return s.jsxs("span",{className:"usage-cell",title:a.title,children:[j?s.jsx("span",{className:"usage-plan",children:s.jsx("span",{className:`plan-chip${j.free?" free":""}`,children:j.text})}):null,b.map(w=>s.jsx(vO,{row:w},w.id||w.name)),o,f,c]})}if(x$(e)){const w=a.kind==="ok"||a.kind==="warn"?IG(t):null;return w?s.jsx(LG,{summary:a,detail:w,blockedBadge:o,tokenSub:c}):s.jsxs("span",{className:"usage-sum-wrap",children:[s.jsx("span",{className:`usage-sum ${a.kind}`,title:a.title,children:a.text}),o,f,c]})}const y=a.kind==="ok"||a.kind==="warn"?AG(t):null;if(!y)return s.jsxs("span",{className:"usage-sum-wrap",children:[h?s.jsx(AA,{variant:"sum",...h,children:a.text}):s.jsx("span",{className:`usage-sum ${a.kind}`,title:a.title,children:a.text}),o,f,c]});const v=s.jsxs(s.Fragment,{children:[y.percent!==null?s.jsx(cf,{value:y.percent,className:"usage-pool-bar"}):null,s.jsx("span",{className:`usage-pool-view ${a.kind}`,children:y.text})]});return s.jsxs("span",{className:"usage-pool",title:a.title,children:[y.planName?s.jsx("span",{className:"usage-pool-name",children:y.planName}):null,h?s.jsx(AA,{variant:"pool",...h,children:v}):s.jsx("span",{className:"usage-pool-line",children:v}),o,f,c]})}function LG({summary:e,detail:t,blockedBadge:a,tokenSub:o}){const[c,d]=x.useState(!1),f=e.kind==="ok"||e.kind==="warn";return s.jsxs("span",{className:c?"usage-cell open":"usage-cell",children:[s.jsxs("span",{className:"usage-plan",children:[t.plan?s.jsx("span",{className:`plan-chip${t.free?" free":""}`,children:t.plan}):null,t.resetDate?s.jsx("span",{className:"plan-sub",title:r("套餐积分的重置日期"),children:r("重置 {date}",{date:t.resetDate})}):null]}),s.jsxs(wf,{open:c,onOpenChange:d,children:[s.jsxs(Kh,{render:s.jsx("button",{type:"button",className:`usage-toggle ${e.kind}`,title:e.title,"aria-label":r("积分明细")}),children:[s.jsx("span",{className:"val",children:e.text}),s.jsx("span",{className:"caret","aria-hidden":!0,children:"▾"})]}),s.jsxs(Sf,{align:"end",sideOffset:6,className:"usage-pop w-[288px]",children:[f&&t.missing.length?t.missing.map(p=>s.jsx("div",{className:"usage-pop-missing",title:p,children:p},p)):null,t.credit.length?s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"usage-pop-group",children:r("积分")}),t.credit.map(p=>s.jsx(zG,{row:p},p.name))]}):null,t.total!==null?s.jsxs("div",{className:"usage-pop-total",children:[s.jsx("span",{className:"k",children:r("可用合计")}),s.jsxs("span",{className:"v",children:[ss(t.total)," ",s.jsx("small",{children:t.unit})]})]}):null,!t.credit.length&&t.total===null?s.jsx("div",{className:"usage-pop-empty",title:r("该账号的额度只有福利 token 池(见余额格那两行),订阅统计没有积分类计量表"),children:r("该账号没有积分类读数(额度只有福利 token 池)")}):null]})]}),t.token.map(p=>s.jsx(vO,{row:p},p.name)),t.benefitAbsent?s.jsxs("span",{className:"usage-flat-line",title:r("福利按限时活动下发,不是每个账号都有 —— 正常状态,不是查询失败"),children:[s.jsx("span",{className:"usage-flat-name",children:r("福利日额度")}),s.jsx("span",{className:"usage-flat-view muted",children:r("无福利额度")})]}):null,a,o]})}function zG({row:e}){return s.jsxs("div",{className:"usage-pop-row",title:e.title,children:[s.jsxs("div",{className:"usage-pop-line",children:[s.jsx("span",{className:"usage-pop-name",children:e.name}),s.jsx("span",{className:`usage-pop-view ${e.tone}`,children:e.view})]}),e.percent!==null?s.jsx("span",{className:`usage-pop-track${e.over?" over":""}`,children:s.jsx("i",{style:{width:`${e.percent}%`},"aria-label":r("剩余 {percent}%",{percent:Math.round(e.percent)})})}):null]})}function BG({account:e,namesHidden:t}){const a=Xh(e),o=cr(An(e)),c=hu(e)||r("未命名账号"),d=String(e.email||"").trim(),f=String(e.nickname||"").trim(),p=String(e.name||"").trim(),h=w=>t?L$(w):w,b=[d&&d!==c?r("邮箱 {email}",{email:h(d)}):"",a?`${o.identifier} ${a}`:"",!e.nameCustom&&p&&p!==d&&p!==f?r("备注名 {name}",{name:h(p)}):"",f&&f!==c&&f!==d?r("昵称 {name}",{name:h(f)}):"",kf(e)?r("桌面端实时登录态(凭证每次从客户端登录态文件读取)"):"",e.updatedAt?r("更新于 {time}",{time:Ls(e.updatedAt)}):"",e.source?r("来源 {source}",{source:e.source==="imported"?r("旧数据导入"):r("手动添加")}):""].filter(Boolean),y=d&&d!==c,v=e.proxy?.error,j=b.length?s.jsx(dV,{delay:0,children:s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("div",{className:"acct-name"}),children:s.jsx("span",{className:"name",children:h(c)})}),s.jsxs(Fi,{children:[s.jsx(fV,{}),b.map((w,S)=>s.jsx("div",{children:w},S))]})]})}):s.jsx("div",{className:"acct-name",children:s.jsx("span",{className:"name",children:h(c)})});return s.jsxs(s.Fragment,{children:[j,y?s.jsx("div",{className:"acct-sub",children:s.jsx("span",{className:"acct-email",title:r("账号邮箱"),children:h(d)})}):null,v?s.jsx("div",{className:"acct-note bad",title:r("代理不可用:{error}",{error:v}),children:r("代理不可用:{error}",{error:v})}):null]})}function HG({account:e}){const t=e.proxy,a=t?.config?.source||t?.source,o=t?.label||r(a==="custom"?"自定义代理":"已设置"),c=t?.error,d=H$(),f=Array.isArray(d)?d:[];let p="";a==="pool"&&t?.config?.proxyId?p=`${Qa}${t.config.proxyId}`:t&&(p=cg);const h=[{value:"",label:r("直连")}];for(const v of f)h.push({value:`${Qa}${v.id}`,label:du(v)});if(d===null?h.push({value:"__hint_pool__",label:r("正在读取代理列表…"),disabled:!0}):f.length||h.push({value:"__hint_pool__",label:U$()?r("代理列表读取失败(重试中)"):r("还没有代理(去「网络代理」页添加)"),disabled:!0}),p===cg){const v=a==="clash"?r("Clash 出口:"):a==="custom"?r("自定义:"):"";h.push({value:cg,label:`${v}${o}${c?r("(不可用)"):""}`})}else a==="pool"&&!f.some(v=>`${Qa}${v.id}`===p)&&h.push({value:p,label:`${o}${c?r("(不可用)"):""}`});h.push({value:AR,label:r("自定义代理…")});const b=c?r("代理不可用:{error}(转发时会回退直连);选「自定义代理…」去修改",{error:c}):a==="rotate"?r("当前:{label}(每条请求换一个出口);「自定义代理…」打开完整设置",{label:o}):a==="clash"||a==="custom"?r("当前:{label}(未经过代理池 —— 可在「网络代理」页把出口同步进池后来这里改选)",{label:o}):r("当前:{label};选项来自「网络代理」页;「自定义代理…」打开完整设置",{label:t?o:r("直连")}),y=h.find(v=>v.value===p);return s.jsxs(ut,{value:p,onValueChange:v=>{W$(e.id,String(v),p)},children:[s.jsx(ft,{className:Ue("w-full",c&&"border-destructive-bd"),title:b,"aria-label":r("出网代理"),children:s.jsx(dt,{children:y?.label||r("直连")})}),s.jsx(pt,{children:h.map(v=>s.jsx($e,{value:v.value,disabled:v.disabled,children:v.label},v.value))})]})}function UG({account:e,atFront:t}){const[a,o]=x.useState(!1),c=Ea(e),d=FA(e);return s.jsxs("div",{className:"acct-actions",children:[d?s.jsx(ne,{variant:"outline",size:"xs",title:h$(e)?g$(e):r("查看可领取的套餐与名下已有的套餐(每天一期,领取需过一次人机验证)"),onClick:()=>RR(e.id),children:r("领套餐")}):null,c?s.jsx(ne,{variant:"outline",size:"xs",disabled:a,title:r("查询该账号剩余余额(读数显示在余额列)"),onClick:()=>{o(!0),Q$(e.id).finally(()=>o(!1))},children:r("余额")}):null,s.jsx(ne,{variant:"outline",size:"xs",title:r("备注名 / 启用 / 代理"),onClick:()=>lg(e.id),children:r("设置")}),s.jsx(VG,{account:e,atFront:t})]})}function VG({account:e,atFront:t}){const[a,o]=x.useState(!1),c=ur(e),d=Number(e.maxConcurrent)||0,f="w-full justify-start px-2 font-normal",p=`${f} text-destructive hover:text-destructive`;return s.jsxs(wf,{open:a,onOpenChange:o,children:[s.jsx(Kh,{render:s.jsx(ne,{variant:"outline",size:"xs",title:r("更多操作")}),children:"⋯"}),s.jsx(Sf,{align:"end",sideOffset:4,className:"w-[172px] p-1.5",children:s.jsxs("div",{className:"flex flex-col gap-0.5",children:[s.jsx(ne,{variant:"ghost",size:"sm",className:p,onClick:()=>{o(!1),CR(e.id,!c)},children:r(c?"禁用":"启用")}),s.jsx(ne,{variant:"ghost",size:"sm",className:f,disabled:t,title:r(t?"已在全局队列第一位":"仅将优先级调整到全局第一位,不改变启用状态"),onClick:()=>{o(!1),Pe().wbApp?.runAccountAction?.("switch",e.id)},children:r("设为首选")}),s.jsx(ne,{variant:"ghost",size:"sm",className:f,title:r("在账号设置的「基本」分组里设置该账号同时最多处理的请求数"),onClick:()=>{o(!1),lg(e.id)},children:r("并发上限:{value}",{value:d>0?d:r("不限")})}),e.hasRefreshToken?s.jsx(ne,{variant:"ghost",size:"sm",className:f,onClick:()=>{o(!1),Pe().wbApp?.runAccountAction?.("refresh",e.id)},children:r("刷新 Token")}):null,s.jsx("div",{className:"my-1 h-px bg-hairline"}),s.jsx(ne,{variant:"ghost",size:"sm",className:p,title:kf(e)?r("删除这条账号记录(不会影响客户端自己的登录态;之后可再点「导入桌面端登录态」加回来)"):void 0,onClick:()=>{o(!1),Pe().wbApp?.runAccountAction?.("remove",e.id)},children:r("删除账号")})]})})]})}function FG({account:e,onClose:t,onClear:a}){const o=bj(e),c=s.jsx(ne,{variant:"ghost",size:"icon-xs",className:"panel-close",title:r("收起"),onClick:t,children:"✕"});return o.length?s.jsxs("div",{className:"row-panel limit-panel",children:[c,s.jsxs("div",{className:"lp-head",children:[s.jsx("b",{children:hu(e)}),s.jsx("span",{className:"muted",children:r("{n} 个模型限流中 · 记录来自上游 429 / 限额码,到恢复时间自动解除",{n:o.length})}),s.jsx(ne,{variant:"outline",size:"xs",title:r("清掉该账号全部模型的限流标记"),onClick:()=>a(""),children:r("全部清除")})]}),o.map(d=>{const f=jj(d.resetAt),p=d.message||(d.status?r("上游返回 {status}",{status:d.status}):"");return s.jsxs("div",{className:"lp-row",children:[s.jsx("span",{className:"lp-model",title:d.model,children:d.model}),s.jsx(ze,{variant:"warning",shape:"tag",children:r("限流中")}),s.jsx("span",{className:"lp-reset",title:r("到恢复时间后自动解除,无需手动操作"),children:f===yj?r("恢复时间未知"):r("{time} 恢复",{time:f})}),s.jsx("span",{className:"lp-reason",title:p,children:p}),s.jsx(ne,{variant:"outline",size:"2xs",title:r("清掉本机的限流标记,立刻重新尝试该模型(上游若仍在限流会再次被标记)"),onClick:()=>a(d.model),children:r("清除标记")})]},d.model)})]}):s.jsxs("div",{className:"row-panel limit-panel",children:[r("当前没有限流中的模型。"),c]})}function $G({account:e,colSpan:t,limitsOpen:a,onClear:o}){return a?s.jsx("tr",{className:"acct-panels","data-panels-for":e.id,children:s.jsx("td",{colSpan:t,children:s.jsx(FG,{account:e,onClose:()=>dR(e.id,"limits",!1),onClear:c=>o(e.id,c)})})}):null}function qG({namesHidden:e,allPicked:t,somePicked:a,disabled:o,onToggleAll:c}){const d=s.jsx("span",{className:"col-grip",title:r("拖动调整列宽(双击还原)")});return s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{className:"cell-pick","data-col":"pick",children:s.jsx(Pr,{id:"acct-select-all",checked:t,indeterminate:!t&&a,disabled:o,"aria-label":r("全选当前筛选结果"),title:r("全选 / 取消全选当前筛选结果(与批量栏同一个选择)"),onCheckedChange:f=>c(f)})}),s.jsxs("th",{className:"cell-order","data-col":"order",children:[s.jsx("span",{className:"th-label",title:r("组内先后:按住左边的把手上下拖动即可调整;整组的先后拖分组带的把手"),children:r("顺序")}),d]}),s.jsxs("th",{className:"cell-account","data-col":"account",children:[s.jsxs("span",{className:"th-label",children:[r("账号"),s.jsx(GG,{hidden:e})]}),d]}),s.jsxs("th",{className:"cell-proxy","data-col":"proxy",children:[s.jsx("span",{className:"th-label",title:r("该账号出网走的代理(Clash 出口 / 自定义 / 直连);点击可修改"),children:r("代理")}),d]}),s.jsxs("th",{className:"cell-connections","data-col":"connections",children:[s.jsx("span",{className:"th-label",title:r("此刻正在使用这个账号的请求数(含还在下发内容的流式请求);为 0 时不显示"),children:r("连接数")}),d]}),s.jsxs("th",{className:"cell-status","data-col":"status",children:[s.jsx("span",{className:"th-label",children:r("状态")}),d]}),s.jsxs("th",{className:"cell-limits","data-col":"limits",children:[s.jsx("span",{className:"th-label",title:r("该账号当前限流中的模型;点徽章看明细"),children:r("限流")}),d]}),s.jsxs("th",{className:"cell-expiry","data-col":"expiry",children:[s.jsx("span",{className:"th-label",children:r("有效期")}),d]}),s.jsxs("th",{className:"cell-usage","data-col":"usage",children:[s.jsx("span",{className:"th-label",children:r("余额")}),d]}),s.jsx("th",{className:"cell-actions","data-col":"actions",children:s.jsx("span",{className:"th-label",children:r("操作")})})]})})}function GG({hidden:e}){const t=r(e?"显示账号名":"隐藏账号名(名字显示为星号)");return s.jsx("button",{type:"button",className:`name-eye${e?" on":""}`,title:t,"aria-label":t,"aria-pressed":e,onClick:()=>_$(),dangerouslySetInnerHTML:{__html:Cg(e?"eyeOff":"eye",13)}})}const yO="dragging",Bf=["drop-before","drop-after"];let Ja=null;function jO(e){e.querySelectorAll(`.${Bf[0]}, .${Bf[1]}`).forEach(t=>{t.classList.remove(...Bf)})}function KG(e,t){if(t==="group"){const o=e.parentElement;return o?[...o.children].filter(c=>c.classList.contains("acct-group")):[]}const a=e.parentElement;return a?[...a.children].filter(o=>o.classList.contains("acct-row")):[]}function wO(e,t){for(let a=0;aa!==e.item);jO(e.container),t.length&&(e.index>=t.length?t[t.length-1].classList.add(Bf[1]):t[e.index].classList.add(Bf[0]))}function SO(e){if(!Ja)return;if(e.buttons===0){Tg(!1);return}const t=Ja.items.filter(o=>o!==Ja.item),a=wO(t,e.clientY);a!==Ja.index&&(Ja.index=a,YG(Ja))}function Tg(e){const t=Ja;t&&(Ja=null,window.removeEventListener("pointermove",SO),window.removeEventListener("pointerup",NO),window.removeEventListener("pointercancel",kO),window.removeEventListener("keydown",CO),document.body.classList.remove("queue-dragging"),t.item.classList.remove(yO),jO(t.container),e&&(t.kind==="group"?Qj?.onDrop({kind:"group",provider:t.provider,index:t.index}):Qj?.onDrop({kind:"row",provider:t.provider,accountId:t.accountId,index:t.index})))}function NO(){Tg(!0)}function kO(){Tg(!1)}function CO(e){e.key==="Escape"&&Tg(!1)}let Qj=null;function XG(e,t){Qj=t,e&&e.dataset.queueDragBound!=="1"&&(e.dataset.queueDragBound="1",e.addEventListener("pointerdown",a=>{if(a.button!==0||Ja)return;const o=a.target,c=o?.closest?.(".queue-grip"),d=o?.closest?.(".order-grip");if(!c&&!d)return;if(a.preventDefault(),c&&t.isLocked()){t.onLockedAttempt();return}const f=(c??d).closest("tbody.acct-group, tr.acct-row");if(!f)return;const p=c?"group":"row",h=f.dataset.provider||f.closest("tbody.acct-group")?.dataset.provider||"",b=f.dataset.id||"";if(p==="row"&&!b)return;const y=KG(f,p);if(y.length<2)return;const v=y.filter(j=>j!==f);Ja={kind:p,provider:h,accountId:b,item:f,container:f.parentElement||e,items:y,index:wO(v,a.clientY)},f.classList.add(yO),document.body.classList.add("queue-dragging"),window.addEventListener("pointermove",SO),window.addEventListener("pointerup",NO),window.addEventListener("pointercancel",kO),window.addEventListener("keydown",CO)}))}let Eg=null,TO=!1,Zj=0,Ag=null,EO="";function AO(){return Eg?Eg.apply(Oj):Oj}function RO(){window.wbAccountsView?.render?.()}function QG(){const e=AO(),t=`${Ag?"T":"F"}|${e.map(o=>`${o.key}:${o.align}`).join("|")}`;if(t===EO)return;EO=t,Pe().wbColSettings?.syncStaticHead("accounts",Ag);const a=[...Ag?.querySelectorAll("thead th")||[]];a.forEach((o,c)=>{const d=o.querySelector(".col-grip");d&&(d.style.display=c===a.length-1?"none":"")})}function ZG(){const e=x.useSyncExternalStore(sR,Gs),t=x.useRef(null),[,a]=x.useReducer(B=>B+1,0),o=!!Sj(),c=Al(),{groups:d,allGroups:f}=k$(Wa,Rl),p=C$(Wa,Rl),h=[{value:"all",label:r("全部({n})",{n:c.length})}].concat(rR().map(B=>({value:B.id,label:r("{label}({count})",{label:r(B.label),count:B.count})}))),b=d.flatMap(B=>B.accounts),y=T$(),v=AO(),j=hg(b.length,"accounts",{defaultSize:"all"}),w=j.paged?j.slice(b):b,S=ng()||j.paged,N=ng()?r("清除筛选"):r("把每页调回「全部」");x.useEffect(()=>{V$()}),x.useEffect(()=>{R$()},[e.version]),x.useLayoutEffect(()=>{if(!TO){if(!Pe().wbColSettings?.register){window.clearTimeout(Zj),Zj=window.setTimeout(()=>k(B=>B+1),50);return}TO=!0,Eg=Pe().wbColSettings?.register({id:"accounts",label:r("账号表"),columns:Oj.map(B=>({key:B.key,label:B.label,align:B.align,legacyAlign:B.legacyAlign})),mount:()=>document.querySelector("#batch-bar .batch-actions"),onChange:RO})||null,Eg&&a();return}QG()});const[,k]=x.useState(0);x.useEffect(()=>()=>window.clearTimeout(Zj),[]),x.useEffect(()=>{U8(t.current,RO)},[]);const A=b.map(B=>B.id),P=A.length>0&&A.every(B=>e.selected.has(B)),R=A.some(B=>e.selected.has(B)),C=[...e.selected].filter(B=>!A.includes(B)).length,E=e.selected.size>0,D=f.length>0&&f.every(B=>e.collapsed.has(B.provider)),I=new Map;for(const B of d)I.set(B.provider,w.filter(L=>An(L)===B.provider).map(L=>L.id));const O=x.useRef({displayed:d,all:f,renderedRows:I});x.useEffect(()=>{O.current={displayed:d,all:f,renderedRows:I}});const _=x.useRef({locked:!1,lockReason:"",onDrop:B=>{}}),z=x.useCallback(B=>{const{displayed:L,all:F}=O.current;if(B.kind==="group"){const Z=F.findIndex(te=>te.provider===B.provider);if(Z<0)return;const ae=F[Z],ce=F.filter((te,ke)=>ke!==Z),W=B.indexte.provider===W),ve=W===null||ue<0?ce.length:ue;if(ve===Z)return;const he=[...ce.slice(0,ve),ae,...ce.slice(ve)].flatMap(te=>te.members.map(ke=>ke.id));TR(he,r("{name} 移到第 {rank} 顺位",{name:ae.label,rank:ve+1}));return}const $=F.find(Z=>Z.provider===B.provider);if(!$)return;const X=$.members.findIndex(Z=>Z.id===B.accountId);if(X<0)return;const K=$.members[X],q=$.members.filter((Z,ae)=>ae!==X),Q=O.current.renderedRows.get(B.provider)||[],G=B.indexZ.id===G),Y=G===null||J<0?q.length:J;if(Y===X)return;const re=[...q.slice(0,Y),K,...q.slice(Y)],U=F.map(Z=>Z.provider===B.provider?{...Z,members:re}:Z).flatMap(Z=>Z.members.map(ae=>ae.id));TR(U,r("{name} 移到 {group} 组内第 {rank} 位",{name:String(K.name||K.id),group:r($.label),rank:Y+1}))},[]);x.useEffect(()=>{_.current={locked:S,lockReason:N,onDrop:z}}),x.useEffect(()=>{XG(t.current,{isLocked:()=>_.current.locked,onLockedAttempt:()=>Le(r("当前视图不能调整组顺位:{reason} 之后再拖动",{reason:_.current.lockReason}),"err"),onDrop:B=>_.current.onDrop(B)})},[]);function H(B,L,F){switch(B){case"pick":return s.jsx(Pr,{checked:F.picked,"data-pick":L.id,title:r("勾选后可批量操作"),"aria-label":r("勾选后可批量操作"),onCheckedChange:$=>D$(L.id,$)});case"order":return s.jsx(xG,{account:L,rank:F.rank});case"account":return s.jsx(BG,{account:L,namesHidden:e.namesHidden});case"proxy":return s.jsx(HG,{account:L});case"connections":return s.jsx(SG,{account:L});case"status":return s.jsx(yG,{account:L});case"limits":return s.jsx(jG,{account:L,open:F.limitsOpen});case"expiry":return s.jsx(wG,{account:L});case"usage":return s.jsx(_G,{account:L});case"actions":return s.jsx(UG,{account:L,atFront:F.seat.position<=1});default:return null}}return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel account-table",children:[s.jsxs("div",{className:"toolbar",children:[s.jsxs("div",{className:"group","data-provider-group":"1",children:[s.jsx("span",{className:"label",children:r("提供商")}),s.jsxs(ut,{value:e.filter.provider,onValueChange:B=>A$(String(B)),children:[s.jsx(ft,{className:"max-w-none min-w-0 w-full min-[768px]:max-w-[200px] min-[768px]:min-w-[130px] min-[768px]:w-auto","aria-label":r("按提供商筛选账号"),children:s.jsx(dt,{children:h.find(B=>B.value===e.filter.provider)?.label||r("全部")})}),s.jsx(pt,{children:h.map(B=>s.jsx($e,{value:B.value,children:B.label},B.value))})]})]}),s.jsx("div",{className:"divider","data-provider-divider":"1"}),s.jsxs("div",{className:"group",children:[s.jsx("span",{className:"label",children:r("搜索")}),s.jsx(Fe,{className:"acct-search",type:"search",value:e.filter.q,placeholder:r("账号名 / 邮箱 / 备注"),"aria-label":r("搜索账号"),onChange:B=>E$(B.currentTarget.value)})]}),s.jsx("div",{className:"divider"}),s.jsxs("div",{className:"group",children:[s.jsx("span",{className:"label",children:r("状态")}),s.jsx(En,{options:[{value:"all",label:r("全部"),count:p.enabledAll??0},{value:"enabled",label:r("启用"),count:p.enabled??0},{value:"disabled",label:r("禁用"),count:p.disabled??0}],value:e.filter.enabled,onValueChange:B=>aR("enabled",B),"aria-label":r("启用状态")})]}),s.jsxs("div",{className:"group",children:[s.jsx("span",{className:"label",children:r("限额")}),s.jsx(En,{options:[{value:"all",label:r("全部"),count:p.limitAll??0},{value:"normal",label:r("正常"),count:p.normal??0,disabled:e.filter.enabled==="disabled"},{value:"limited",label:r("已限流"),count:p.limited??0,disabled:e.filter.enabled==="disabled"}],value:e.filter.limit,onValueChange:B=>aR("limit",B),"aria-label":r("限额状态")})]}),s.jsxs("div",{className:"actions",children:[s.jsx(ne,{id:"btn-fold-groups",variant:"outline",disabled:!f.length,title:r(D?"展开全部分组":"折叠全部分组(只留组头)"),onClick:()=>O$(f.map(B=>B.provider),!D),children:r(D?"展开全部":"折叠全部")}),s.jsx(ne,{id:"btn-add-account-2",variant:"default",title:r("登录 / 导入一个新账号"),onClick:()=>{Pe().wbAddAccountModal?.open?.(),Pe().wbAccountAddForms?.syncAddProvider?.()},children:r("添加账号")}),s.jsx(ne,{id:"btn-query-usage",variant:"outline",disabled:e.usageBusy||!c.some(Ea),title:r("查询全部账号的余额(含已禁用账号 —— 禁用只表示不参与转发)"),onClick:()=>{NR()},children:e.usageBusy?r("查询中…"):r("查询余额")})]})]}),s.jsxs("div",{className:Ue("batch-bar",E&&"active"),id:"batch-bar",children:[s.jsxs("label",{className:"batch-select-all",children:[s.jsx(Pr,{id:"batch-select-all",checked:P,indeterminate:!P&&R,disabled:!A.length,"aria-label":r("全选当前筛选结果"),onCheckedChange:B=>cR(A,B)}),s.jsx("span",{id:"batch-select-label",children:A.length?r("全选当前筛选结果({n} 个)",{n:A.length}):r("没有可全选的账号")})]}),s.jsxs("span",{className:"batch-count",children:[r("已选")," ",s.jsx("b",{id:"batch-count",children:e.selected.size})," ",r("个 · 共")," ",s.jsx("b",{id:"accounts-count",children:c.length})," ",r("个")]}),s.jsx("span",{className:"batch-summary",id:"accounts-group-summary",children:d.length?r("{groups} 家 · 显示 {rows} 行",{groups:d.length,rows:A.length}):""}),S?s.jsx("span",{className:"batch-hidden",title:r("筛选 / 搜索 / 分页生效时组顺位不可拖动(别家的组整组不可见,落点没法定位)"),children:r("组顺位已锁定")}):null,ng()?s.jsx(ne,{id:"btn-clear-filter",variant:"ghost",size:"xs",title:r("清空搜索与三个筛选档位,回到全部账号"),onClick:()=>lR(),children:r("清除筛选")}):null,C?s.jsx("span",{className:"batch-hidden",id:"batch-hidden-hint",children:r("另有 {n} 个已勾选账号被当前筛选隐藏,仍会参与操作",{n:C})}):null,s.jsxs("div",{className:"batch-actions",children:[s.jsx(ne,{id:"btn-batch-open",variant:"outline",disabled:!E,onClick:()=>kj([...e.selected],"enable"),children:r("批量操作")}),s.jsx(ne,{id:"btn-batch-clear",variant:"outline",disabled:!E,onClick:()=>I$(),children:r("取消选择")})]})]}),s.jsx("div",{className:"acct-scroll",id:"account-list",ref:t,children:o?c.length?b.length?s.jsxs("table",{className:"acct-table",ref:WG,style:{minWidth:`${B8(v.map(B=>B.key))}px`},children:[s.jsx(JG,{}),s.jsx(qG,{namesHidden:e.namesHidden,allPicked:P,somePicked:R,disabled:!A.length,onToggleAll:B=>cR(A,B)}),d.map(B=>{const L=e.collapsed.has(B.provider),F=w.filter($=>An($)===B.provider);return s.jsxs("tbody",{className:"acct-group","data-provider":B.provider,children:[s.jsx(vG,{group:B,collapsed:L,colSpan:v.length}),L?null:F.map($=>{const X=B.members.findIndex(q=>q.id===$.id)+1,K=J$($,y,X>0?X:1);return s.jsxs(x.Fragment,{children:[s.jsx("tr",{className:Ue("acct-row",!ur($)&&"disabled",K.picked&&"selected"),"data-id":$.id,"data-provider":B.provider,"data-desktop":kf($)?"1":void 0,children:v.map(q=>s.jsx("td",{className:`cell-${q.key} ta-${q.align}`,children:H(q.key,$,K)},q.key))}),s.jsx($G,{account:$,colSpan:v.length,limitsOpen:uR($.id,"limits"),onClear:(q,Q)=>{Z$(q,Q)}})]},$.id)})]},B.provider)})]}):s.jsxs("div",{className:"empty",children:[r("当前筛选条件下没有账号"),ng()?s.jsx("button",{type:"button",className:"link-btn",onClick:()=>lR(),children:r("清除筛选")}):null]}):s.jsx("div",{className:"empty",children:r("暂无账号,请点击右上角「添加账号」")}):s.jsxs("div",{className:"empty",children:[s.jsx("span",{className:"spinner"}),r("正在加载…")]})}),s.jsx($i,{total:b.length,range:j.paged?{start:j.rangeStart,end:j.rangeEnd}:null,page:j.page,pageCount:j.pageCount,size:j.size,onSizeChange:j.setSize,onPageChange:j.goto})]}),s.jsx(O8,{})]})}function WG(e){Ag=e}function JG(){const e=z8(),t=a=>s.jsx("col",{"data-col":a,style:e[a]?{width:`${e[a]}px`}:void 0},a);return s.jsxs("colgroup",{children:[t("pick"),t("order"),t("account"),t("proxy"),t("connections"),t("status"),t("limits"),t("expiry"),t("usage"),t("actions")]})}const OO='.page[data-page="accounts"]';let Wj=null;function MO(){if(Wj)return;const e=document.querySelector(OO);e&&(e.replaceChildren(),Wj=jn.createRoot(e),Ts.flushSync(()=>{Wj.render(s.jsx(ZG,{}))}))}t8(),G$(),document.querySelector(OO)?MO():document.addEventListener("DOMContentLoaded",MO,{once:!0});const e7=64,t7=100,n7=r("OpenAI 兼容填到 /v1;Anthropic 填根地址"),s7=r("Anthropic 协议填根地址,不要带 /v1"),r7="https://open.bigmodel.cn/api/paas/v4",a7="https://api.anthropic.com",l7=[{value:"chat_completions",label:"OpenAI - Chat Completions"},{value:"responses",label:"OpenAI - Responses"},{value:"anthropic",label:"Anthropic - Messages"}],Cu="custom-protocol-select",Tu="custom-name-input",Eu="custom-baseurl-input",Hf="custom-apikey-input",Uf="custom-noauth-check",Au="custom-existing-select",Vf="custom-existing-apikey-input",Ff="custom-existing-noauth-check",$f="custom-existing-name-input",o7="custom-create-button",i7="custom-existing-button",c7="custom-existing-remove";let Jj=!1;const DO=()=>gt().wbProviders?.PROTOCOL_OPTIONS||l7,ew=()=>gt().wbProviders?.customList?.()||[],tw="custom-balance",nw="custom-existing-balance",qf=(e,t)=>`${e}-${t}-input`;function IO(e){if(!e)return"";const t=gt().wbPresetProviders?.presetOf?.(e);return String(t?.balance?.scheme||"")}function PO(e,t){const a=Mf(e);if(!a||!a.fields.length)return null;const o={};for(const c of a.fields){const d=dr(qf(t,c.key));d&&(o[c.key]=d)}return Object.keys(o).length?o:null}function _O(e,t){const a=Mf(e);if(a)for(const o of a.fields)To(qf(t,o.key),"")}function LO({scheme:e,prefix:t}){const a=Mf(e);return a?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{children:r("余额查询")}),s.jsxs("div",{className:"col-start-2 row-start-1 flex h-[30px] items-center",children:[s.jsx("span",{className:"text-xs text-subtle",children:r("方案:{label}",{label:a.label})}),s.jsx("span",{className:"ml-1.5 text-xs text-subtle",children:a.endpoint})]}),s.jsx("span",{className:"hint",children:a.note})]}),a.fields.map(o=>s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:qf(t,o.key),children:o.label}),s.jsx(Fe,{id:qf(t,o.key),type:o.secret?"password":"text",autoComplete:o.secret?"new-password":"off",placeholder:o.placeholder,..._r(qf(t,o.key))}),s.jsx("span",{className:"hint",children:o.hint})]},o.key))]}):null}async function sw(e,t){if(!Jj){Jj=!0,e(!0);try{await t()}finally{Jj=!1,e(!1)}}}async function zO(e){gt().wbAddAccountModal?.close?.(),gt().wbProviders?.refreshCustom?.(),await gt().wbApp?.refresh?.(),Ln(e)}function Gf(e,t){To(e,t?"1":"")}function Rg(e){return dr(e)==="1"}function BO({checked:e,note:t,onChange:a}){return s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{children:r("鉴权")}),s.jsx("div",{className:"col-start-2 row-start-1 flex h-[30px] items-center",children:s.jsxs("label",{className:"inline-flex cursor-pointer items-center gap-2.5",children:[s.jsx(Pr,{checked:e,"aria-label":r("该上游无需鉴权"),onCheckedChange:o=>a(o===!0)}),s.jsx("span",{className:"text-xs text-subtle",children:r("该上游无需鉴权(不发送鉴权头)")})]})}),s.jsx("span",{className:"hint",children:t})]})}function u7({mode:e,providerHint:t,presetKey:a,showToken:o,version:c}){const d=DO(),[f,p]=x.useState(()=>dr(Cu)||d[0].value),[h,b]=x.useState(""),[y,v]=x.useState(""),[j,w]=x.useState(()=>dr(Au)),[S,N]=x.useState(()=>Rg(Uf)),[k,A]=x.useState(()=>Rg(Ff)),P=x.useMemo(()=>ew(),[c]),C=(t&&P.some(B=>B.id===t)?t:"")||(P.some(B=>B.id===j)?j:P[0]?.id||""),E=P.find(B=>B.id===C)?.name||r("该提供商");x.useEffect(()=>{To(Au,C)},[C]),x.useEffect(()=>{if(!a)return;const B=gt().wbPresetProviders?.presetOf?.(a);if(!B)return;const L=B.account?.noAuth===!0;if(e!=="create"){A(L),Gf(Ff,L);return}To(Tu,B.name||""),To(Eu,B.baseUrl||""),B.protocol&&(p(B.protocol),To(Cu,B.protocol)),N(L),Gf(Uf,L),b(B.hint||""),v(B.placeholder||"")},[e,a,t,o]);const D=f==="anthropic",I=h||(D?s7:n7),O=y||(D?a7:r7),_=e==="create"?IO(a):"",z=e==="existing"?String(P.find(B=>B.id===C)?.balanceScheme||""):"",H=(B,L)=>F=>{L(F),Gf(B,F)};return s.jsxs(s.Fragment,{children:[s.jsxs(dn,{hidden:e!=="create",children:[s.jsxs("div",{className:"add-panel-head",children:[s.jsx("h3",{children:r("上游信息")}),s.jsx("span",{children:r("创建这个提供商,并同时建立它的第一个账号。")})]}),s.jsxs("div",{className:"add-form",children:[s.jsxs("div",{className:"add-field",children:[s.jsxs(Je,{htmlFor:Tu,children:[r("名称"),s.jsx("i",{className:"req","aria-hidden":"true",children:"*"})]}),s.jsx(Fe,{id:Tu,type:"text",maxLength:e7,"aria-required":"true",placeholder:r("如:智谱 GLM"),..._r(Tu)}),s.jsx("span",{className:"hint",children:r("1~64 个字符,账号列表里按它分组显示")})]}),s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:Cu,children:r("协议")}),s.jsxs(ut,{value:f,onValueChange:B=>{const L=String(B);p(L),To(Cu,L),b("")},children:[s.jsx(ft,{id:Cu,className:"col-start-2 row-start-1 w-full",children:s.jsx(dt,{children:d.find(B=>B.value===f)?.label||f})}),s.jsx(pt,{children:d.map(B=>s.jsx($e,{value:B.value,children:B.label},B.value))})]})]}),s.jsxs("div",{className:"add-field",children:[s.jsxs(Je,{htmlFor:Eu,children:["Base URL",s.jsx("i",{className:"req","aria-hidden":"true",children:"*"})]}),s.jsx(Fe,{id:Eu,type:"text","aria-required":"true",placeholder:O,..._r(Eu)}),s.jsx("span",{className:"hint",id:"custom-baseurl-hint",children:I})]}),s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:Hf,children:"API Key"}),s.jsx(Fe,{id:Hf,type:"password",autoComplete:"new-password",placeholder:"sk-…",disabled:S,..._r(Hf)}),s.jsx("span",{className:"hint",children:r(S?"不需要 Key:转发与拉取模型都不发送鉴权头":"上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)")})]}),s.jsx(BO,{checked:S,note:r(S?"已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头":"本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用"),onChange:H(Uf,N)}),s.jsx(LO,{scheme:_,prefix:tw})]})]}),s.jsxs(dn,{hidden:e!=="existing",children:[s.jsxs("div",{className:"add-panel-head",children:[s.jsx("h3",{children:r("账号信息")}),s.jsxs("span",{children:[r("添加到 "),s.jsx("b",{children:E}),r(" 同一家可以放多把 key,按优先级轮换。")]})]}),s.jsxs("div",{className:"add-form",children:[s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:Au,children:r("提供商")}),s.jsxs(ut,{value:C,onValueChange:B=>w(String(B)),children:[s.jsx(ft,{id:Au,className:"col-start-2 row-start-1 w-full",children:s.jsx(dt,{children:E})}),s.jsx(pt,{children:P.map(B=>s.jsx($e,{value:B.id,children:B.name||B.id},B.id))})]})]}),s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:Vf,children:"API Key"}),s.jsx(Fe,{id:Vf,type:"password",autoComplete:"new-password",placeholder:"sk-…",disabled:k,..._r(Vf)}),s.jsx("span",{className:"hint",children:r(k?"不需要 Key:转发与拉取模型都不发送鉴权头":"上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)")})]}),s.jsx(BO,{checked:k,note:r(k?"已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头":"同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)"),onChange:H(Ff,A)}),s.jsx(LO,{scheme:z,prefix:nw}),s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:$f,children:r("备注名")}),s.jsx(Fe,{id:$f,type:"text",maxLength:t7,placeholder:r("可选"),..._r($f)}),s.jsx("span",{className:"hint",children:r("留空则用提供商名称")})]})]})]})]})}function HO(e,t){const a=ko(t);Ln(r("添加失败:{reason}",{reason:a}),"err"),e.setHint(a)}async function d7(e){const t=dr(Tu),a=dr(Cu)||DO()[0].value,o=dr(Eu),c=dr(Hf),d=Rg(Uf);if(!t){Ln(r("请填写名称"),"err");return}if(!o){Ln(r("请填写 Base URL"),"err");return}await sw(e.setBusy,async()=>{const f={name:t,protocol:a,baseUrl:o},p=e.presetKey?gt().wbPresetProviders?.presetOf?.(e.presetKey):null,h=p?.quirks||{};h.urlSuffix&&(f.urlSuffix=h.urlSuffix),h.headers&&Object.keys(h.headers).length&&(f.headers={...h.headers}),h.anthropicToolType&&(f.anthropicToolType=h.anthropicToolType),p?.clientEmulation&&(f.clientEmulation=p.clientEmulation);const b=IO(e.presetKey);b&&(f.balanceScheme=b);const y=PO(b,tw);y&&(f.balanceQuery=y),d?f.noAuth=!0:c&&(f.apiKey=c),e.setHint("");try{const v=await gt().wbProviders?.customRequest?.("POST","/api/custom-providers",f);Lj([Tu,Eu,Hf]),_O(b,tw),Gf(Uf,!1);const j=v?.provider?.name||t;await zO(r("✅ 已创建自定义提供商「{name}」并添加账号",{name:j}))}catch(v){HO(e,v)}})}async function f7(e){const t=dr(Au);if(!t){Ln(r("请先选择一个自定义提供商"),"err");return}const a=dr(Vf),o=Rg(Ff),c=dr($f),d=String(ew().find(f=>f.id===t)?.balanceScheme||"");await sw(e.setBusy,async()=>{const f={provider:t};o?f.noAuth=!0:a&&(f.apiKey=a),c&&(f.name=c);const p=PO(d,nw);p&&(f.balanceQuery=p),e.setHint("");try{const h=await gt().wbProviders?.customRequest?.("POST","/api/accounts",f);Lj([Vf,$f]),_O(d,nw),Gf(Ff,!1);const b=h?.account?.name||ew().find(j=>j.id===t)?.name||"",y=b?`:${b}`:"",v=h?.created!==!1?r("✅ {label}账号已添加{name}",{label:"",name:y}):r("✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)",{name:y});await zO(v)}catch(h){HO(e,h)}})}async function p7(){const e=dr(Au);if(!e){Ln(r("请先选择一个自定义提供商"),"err");return}const t=gt().wbCustomProvidersUi?.remove;if(typeof t!="function"){Ln(r("删除功能不可用(脚本未就绪)"),"err");return}await sw(()=>{},async()=>{await t(e)&>().wbAddAccountModal?.close?.()})}function m7({mode:e,presetKey:t}){const[a,o]=x.useState(!1),[c,d]=x.useState(""),f={presetKey:t,setBusy:o,setHint:d};return s.jsxs(s.Fragment,{children:[s.jsx("span",{className:`add-foot-hint${c?" err":""}`,id:"add-form-foot-hint",children:c}),s.jsxs("span",{className:"add-foot-actions",id:"add-form-foot-actions",children:[e==="existing"?s.jsx(ne,{id:c7,variant:"destructive",title:r("级联删除名下全部账号,不可恢复"),onClick:()=>{p7()},children:r("删除此提供商")}):null,s.jsx(ne,{id:o7,hidden:e!=="create",disabled:a,onClick:()=>{d7(f)},children:r(a&&e==="create"?"提交中…":"创建并添加账号")}),s.jsx(ne,{id:i7,hidden:e!=="existing",disabled:a,onClick:()=>{f7(f)},children:r(a&&e==="existing"?"提交中…":"添加账号")})]})]})}const rw={step:"pick",accountType:Kj,search:"",provider:Gi,providerHint:"",presetKey:"",showToken:0},UO=()=>gt().wbProviders?.customList?.()||[];function h7({onClose:e,onReady:t}){const[a,o]=x.useState(rw),[c,d]=x.useState(0),f=x.useCallback(()=>d(R=>R+1),[]),p=x.useCallback(()=>{o(rw);const R=gt().wbProviders;(R?.all?.()||[]).length||R?.load?.().then(f),R?.refreshCustom?.().then(f)},[f]),h=x.useCallback(()=>{p(),o({...rw,step:"form",provider:ju})},[p]);x.useEffect(()=>(t({reset:p,openNewCustomForm:h}),()=>t(null)),[t,p,h]),x.useEffect(()=>{gt().wbWebLogin?.refresh?.()},[]),x.useEffect(()=>{gt().wbProviders?.refreshCustom?.().then(f)},[f]),x.useEffect(()=>{a.step!=="form"||a.provider!==ju||gt().wbProviders?.refreshCustom?.().then(f)},[a.step,a.provider,a.showToken,f]);const b=iq(a.provider),y=a.provider===ju,v=a.provider===Gi||y||!!b,j=a.providerHint?"existing":"create",w=a.providerHint?UO().find(R=>R.id===a.providerHint)?.name||"":a.presetKey&>().wbPresetProviders?.presetOf?.(a.presetKey)?.name||"",S=a.provider===Gi?Bj:r(gt().wbProviders?.labelOf?.(a.provider)||a.provider),N=y?a.providerHint||a.presetKey?r("登录 / 添加 {name} 账号",{name:w||r("自定义提供商")}):r("新建自定义提供商"):r("登录 / 添加 {name} 账号",{name:S});function k(R){if(!R)return;const C={step:"form",showToken:a.showToken+1};if(R===Xj)o(E=>({...E,...C,provider:ju,providerHint:"",presetKey:""}));else if(R.startsWith(zf)){const E=R.slice(zf.length),D=KR(gt().wbPresetProviders?.presetOf?.(E));o(I=>({...I,...C,provider:ju,providerHint:D?.id||"",presetKey:E}))}else UO().some(E=>E.id===R)?o(E=>({...E,...C,provider:ju,providerHint:R,presetKey:""})):o(E=>({...E,...C,provider:R,providerHint:"",presetKey:""}))}const A=()=>o(R=>({...R,step:"pick"})),P=a.accountType===iG;return s.jsx(Yt,{open:!0,onOpenChange:R=>{R||e()},children:s.jsxs(Xt,{className:"w-[min(1100px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("添加账号")})}),s.jsx(Lt,{children:s.jsx(gG,{accountType:a.accountType,onAccountTypeChange:R=>o(C=>({...C,accountType:R})),search:a.search,onSearchChange:R=>o(C=>({...C,search:R})),onPick:k,version:c,importing:P,importPanel:void 0})}),null,s.jsx(Yt,{open:a.step==="form",onOpenChange:R=>{R||A()},children:s.jsxs(Xt,{keepMounted:!0,overlayForceRender:!0,className:"w-[min(620px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:N})}),s.jsxs(Lt,{children:[s.jsx(oG,{active:a.provider===Gi}),JR.map(R=>s.jsx(nG,{config:R,active:a.provider===R.provider},R.provider)),s.jsx("div",{className:"add-provider-block",style:y?void 0:{display:"none"},children:s.jsx(u7,{mode:j,providerHint:a.providerHint,presetKey:a.presetKey,showToken:a.showToken,version:c})}),v?null:s.jsx("div",{className:"add-provider-block",children:s.jsxs(dn,{children:[s.jsx("h3",{children:r("该提供商账号添加功能即将上线")}),s.jsx("p",{children:r("「{name}」的账号添加功能还在开发中,敬请期待。",{name:S})})]})})]}),y?s.jsx(tn,{children:s.jsx(m7,{mode:j,presetKey:a.presetKey})}):null]})})]})})}let Mo=null,Ru=null,Xi=null,Og=null;function g7(){Mo&&(Mo.unmount(),Mo=null),Ru&&(Ru.remove(),Ru=null),Xi=null}function VO(){Ru=document.createElement("div"),document.body.append(Ru),Mo=jn.createRoot(Ru),Mo.render(s.jsx(h7,{onClose:FO,onReady:e=>{if(Xi=e,!e)return;const t=Og;Og=null,t?.()}}))}function FO(){gt().wbWebLogin?.cancelIfActive?.(""),gt().wbAutoclawOauth?.cancel?.(),g7()}function aw(){if(Mo){Xi?.reset();return}Og=()=>Xi?.reset(),VO()}function x7(){if(Mo){Xi?.openNewCustomForm();return}Og=()=>Xi?.openNewCustomForm(),VO()}for(const e of["btn-add-account","btn-add-account-2"])document.getElementById(e)?.addEventListener("click",aw);const $O=window;$O.wbAddAccountModal={open:aw,close:FO},$O.wbAccountAddForms={syncAddProvider:()=>{Mo?Xi?.reset():aw()},openNewCustomForm:x7};const b7=3065;let Ou=null;function qO(){return window.workbuddyDesktop}const v7="same-origin";let Mg=null;function y7(e){const t={};if(!e||typeof e!="object")return t;for(const[a,o]of Object.entries(e))typeof o=="string"&&o&&(t[a]=o);return t}async function j7(e=!1){if(Mg&&!e)return Mg;let t={};try{t=y7(await qO()?.directCredentials?.())}catch{}return Mg=t,t}async function GO(e=!1){if(Ou&&!e)return Ou;const t=qO();if(t?.platform==="web"){const o=typeof window>"u"?"":window.location?.origin;if(o&&o!=="null")return Ou=o,Ou}let a=0;try{const o=await t?.getBackendStatus?.(),c=Number(o?.port);Number.isFinite(c)&&c>0&&(a=c)}catch{}return a>0?(Ou=`http://127.0.0.1:${a}`,Ou):`http://127.0.0.1:${b7}`}async function KO(){const t=await window.workbuddyDesktop?.getModelManage?.(),a=Array.isArray(t?.models)?t.models:[],o=Array.isArray(t?.mappings)?t.mappings:[],c=new Set,d=[],f=new Set;for(const p of a){if(p.enabled!==!0)continue;const h=String(p.provider??""),b=String(p.id??"");!h||!b||(c.add(`${h}${b}`),f.has(b)||(f.add(b),d.push(b)))}for(const p of o){if(p.enabled!==!0||p.isDefault===!0)continue;const h=String(p.provider??""),b=String(p.target??""),y=String(p.alias??"");(!y||!f.has(y)&&c.has(`${h}${b}`))&&(f.add(y),d.push(y))}return d}const lw=`你是 Agent2API 的内置助手,帮用户管理本机的模型转发配置。 +`)})}function OG(e){if(e===void 0)return{text:r("未查询"),kind:"muted",title:r("尚未查询该账号的余额")};if(e===null)return{text:r("查询中…"),kind:"muted",title:r("正在查询")};const t=xu(e);if(t)return t.notConfigured?{text:r("未配置"),kind:"muted",title:r("{message}(去该账号的「设置」里填上查询凭证即可)",{message:t.message})}:{text:r("查询失败"),kind:"bad",title:t.message};if(typeof e!="object"||e===null)return{text:r("无数据"),kind:"muted",title:String(e)};const a=e;if(Object.prototype.hasOwnProperty.call(a,"totalLeft")){const o=a.unlimited?"∞":ss(a.totalLeft);return{text:r("可用 {total}",{total:o}),kind:"ok",title:r("总剩余 {total} · 套餐 {plan} · 奖励 {bonus}",{total:o,plan:ss(a.planLeft),bonus:ss(a.bonusLeft)})}}if(Object.prototype.hasOwnProperty.call(a,"available")||Array.isArray(a.wallets)){const o=String(a.unit||r("积分")),c=Array.isArray(a.wallets)?a.wallets:[],d=c.map(j=>`${j?.displayName||j?.type||r("明细")} ${j?.balanceView?String(j.balanceView):ss(j?.balance)}`).join(" · "),f=xO(a.subscription),p=[];if(c.length===0&&Array.isArray(a.plans)&&a.plans.length>0){const j=bO(a);p.push(j&&vO(j)?r("读数里没有额度桶,这里按套餐权益里的已用 / 总量显示(上游给的数)"):r("上游的余额读数里没有这个套餐的额度桶,剩余量读不到;余额列显示的是套餐发放的权益额度,不是剩余量"))}String(a.walletsFrom||"")==="monitor"&&p.push(r("额度窗口读数来自开放平台监控通道(套餐 JWT 那条通道没有额度桶):读的是每 N 小时 / 每周窗口的剩余比例"));const h=a.available==null?c.find(j=>j?.balance!=null):void 0,b=a.availableView?String(a.availableView):h?r("可用 {value} {unit}",{value:ss(h.balance),unit:String(h.unit||o)}):r("可用 {value} {unit}",{value:ss(a.available),unit:o}),y=[a.statisticsError?r("订阅统计未读到:{error}",{error:String(a.statisticsError)}):"",a.benefitError?r("福利网关未读到:{error}",{error:String(a.benefitError)}):""].filter(Boolean),v=a.benefitAbsent?[r("该账号没有福利模型额度(福利按活动下发,不是每个账号都有)")]:[];return{text:b+(y.length?" ⚠":""),kind:y.length?"warn":"ok",title:[b,d,f,...p,...v,...y].filter(Boolean).join(" · ")}}return{text:r("无数据"),kind:"muted",title:r("未返回可识别的余额数据")}}function bO(e){const t=Array.isArray(e.plans)?e.plans:[],a=o=>String(o?.state||"");return t.find(o=>a(o)==="active")||t.find(o=>a(o)==="pending")||t[0]||null}function MG(e){const t=Array.isArray(e.entitlements)?e.entitlements:[];let a=null;for(const o of t){const c=Number(o?.grantUnits);if(!Number.isFinite(c)||c<=0)continue;const d=String(o?.unitType||"").trim();(!a||c>a.units)&&(a={units:c,unit:d})}return a}function vO(e){const t=Array.isArray(e.entitlements)?e.entitlements:[];for(const a of t){const o=Nr(a?.totalUnits);if(o===null||o<=0)continue;const c=Nr(a?.usedUnits),d=Nr(a?.remainingUnits),f=c===null?d===null?null:Math.max(0,o-d):c;if(f!==null)return{used:f,total:o,unit:String(a?.unitType||"").trim()}}return null}function DG(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const t=e,a=Array.isArray(t.wallets)?t.wallets:[];let o=null;for(const p of a){const h=Number(p?.total);!Number.isFinite(h)||h<=0||(!o||h>Number(o.total))&&(o=p)}const c=t.subscription&&typeof t.subscription=="object"?t.subscription:{};if(!o){let p=null;for(const j of a){const w=Nr(j?.remainingPercent);w!==null&&(!p||w0?r("重置 {date}",{date:Ls(w)}):"";o.push({name:b,view:j,tone:v===null?"muted":v<20?"warn":"ok",percent:v,over:!1,title:[d||[b,h].filter(Boolean).join(" "),j,k].filter(Boolean).join(" · "),variant:"compact",percentText:v===null?"":`${Math.round(v)}%`,windowShort:h,id:String(c.key||"").trim()||b})}return o}function _G(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const t=e.subscription&&typeof e.subscription=="object"?e.subscription:{},a=String(t.planName||"").trim();return a?{text:KA(a),free:hj(a)}:null}function Mo(e){const t=Number.isFinite(e)?Number(e.toFixed(2)):e,a=window.wbUnits;return a?.formatTokens?a.formatTokens(t):String(t)}function LG(e){return e.includes("福利")?r("福利日额度"):e.includes("对话")?r("对话 token"):e}function zG(e){if(!e||typeof e!="object"||Array.isArray(e))return null;const t=e,a=Array.isArray(t.wallets)?t.wallets:[];if(!a.length)return null;const o=String(t.unit||r("积分")),c=[],d=[];for(const h of a){const b=String(h.displayName||h.type||r("明细")),y=Nr(h.creditRemaining),v=Nr(h.creditTotal),j=String(h.balanceView||"")||ss(h.balance),w=Nr(h.usedPercent);if(y!==null){const k=v!==null&&v>0,S=k?Math.max(0,Math.min(100,y/v*100)):null;c.push({name:b,view:k?r("剩 {remaining} / {total}",{remaining:ss(y),total:ss(v)}):r("剩 {remaining}",{remaining:ss(y)}),tone:y<=0?"muted":S!==null&&S<20?"warn":"ok",percent:S,over:!1,title:k?void 0:r("上游未给总量,画不出剩余比例")});continue}if(w!==null||Nr(h.allowanceTokens)!==null){const k=Nr(h.usedTokens)??0,S=Nr(h.allowanceTokens),N=S!==null&&S>1,R=N&&k>S,P=h.unlimited===!0,T=N?Math.max(0,Math.min(100,(1-k/S)*100)):null,C=P?r("无上限 · 已用 {used}",{used:Mo(k)}):N?r("剩 {remaining} / {total}",{remaining:Mo(Math.max(0,S-k)),total:Mo(S)}):k>0?r("已用 {used}",{used:Mo(k)}):r("未使用");d.push({name:LG(b),view:C,tone:R?"bad":!N&&!P?"muted":T!==null&&T<20?"warn":"ok",percent:T,over:R,title:[j,P?r("无上限按日计(上游到达上限后仍继续计数,超额如实显示)"):null].filter(Boolean).join(" · ")});continue}d.push({name:b,view:j,tone:"muted",percent:null,over:!1,title:j})}const f=t.subscription&&typeof t.subscription=="object"?t.subscription:{},p=[t.statisticsError?r("订阅统计未读到:{error}",{error:String(t.statisticsError)}):"",t.benefitError?r("福利网关未读到:{error}",{error:String(t.benefitError)}):""].filter(Boolean);return{credit:c,token:d,total:Nr(t.available),unit:o,plan:KA(f.planName),free:hj(f.planName),resetDate:String(f.resetDate||""),missing:p,benefitAbsent:t.benefitAbsent===!0}}function BG(e){const t=Rl(e);let a=null;for(const v of d$(e)){if(v.enabled===!1)continue;const j=Nf(v,t);if(!j)continue;const w=v.threshold>0?j.used/v.threshold:0;if(w>=1){a={rule:v,reading:j,ratio:w};break}(!a||w>a.ratio)&&(a={rule:v,reading:j,ratio:w})}if(!a)return null;const{rule:o,reading:c}=a,d=c.used>=o.threshold,f=pj(o),p=d?"":` · ${Wh(f.remainingMs,f.daily)}`,h=f.daily?r("今日已用"):r("周期 Token"),b=o.reset==="daily"?r("今天(本地 0 点重置)"):r("{period}窗口",{period:HA(o.period??0)}),y=r("限制器:{window}已用 {used} / {threshold} Token",{window:b,used:Math.round(c.used).toLocaleString("en-US"),threshold:Math.round(o.threshold).toLocaleString("en-US")})+(d?r(",已达到上限"):r(",{countdown}重置",{countdown:Wh(f.remainingMs,f.daily)}));return s.jsxs("span",{className:"usage-token-sub",title:y,children:[h," ",s.jsx("span",{className:d?"hit":void 0,children:El(c.used)})," ","/ ",El(o.threshold),p]})}function HG({account:e}){if(!Ea(e))return s.jsx("span",{className:"muted",title:r("该提供商没有余额查询"),children:"—"});const t=Wa(e),a=OG(t),o=Zh(e,t)?s.jsx(ze,{variant:"warning",shape:"tag",title:r("余额低于限制器的阈值,转发时会跳过该账号(余额回升自动恢复)"),children:r("余额不足 · 已跳过")}):fj(e,Rl(e))?s.jsx(ze,{variant:"warning",shape:"tag",title:r("本周期 Token 消耗达到限制器的上限,转发时会跳过该账号(窗口重置自动恢复)"),children:r("Token 限额 · 已跳过")}):null,c=BG(e),d=a.kind==="ok"||a.kind==="warn"?AG(t):[],f=d.length?s.jsx(ze,{variant:"warning",shape:"tag",title:RG(d),children:r("待生效 {n} 份",{n:d.length})}):null,p=a.kind==="ok"||a.kind==="warn"?W6(t):[],h=GA(e)&&p.length?{rows:p,subscriptionLine:EG(t),kind:a.kind,title:a.title}:null,b=a.kind==="ok"||a.kind==="warn"?PG(t):[];if(b.length){const j=_G(t);return s.jsxs("span",{className:"usage-cell",title:a.title,children:[j?s.jsx("span",{className:"usage-plan",children:s.jsx("span",{className:`plan-chip${j.free?" free":""}`,children:j.text})}):null,b.map(w=>s.jsx(yO,{row:w},w.id||w.name)),o,f,c]})}if(v$(e)){const w=a.kind==="ok"||a.kind==="warn"?zG(t):null;return w?s.jsx(UG,{summary:a,detail:w,blockedBadge:o,tokenSub:c}):s.jsxs("span",{className:"usage-sum-wrap",children:[s.jsx("span",{className:`usage-sum ${a.kind}`,title:a.title,children:a.text}),o,f,c]})}const y=a.kind==="ok"||a.kind==="warn"?DG(t):null;if(!y)return s.jsxs("span",{className:"usage-sum-wrap",children:[h?s.jsx(AA,{variant:"sum",...h,children:a.text}):s.jsx("span",{className:`usage-sum ${a.kind}`,title:a.title,children:a.text}),o,f,c]});const v=s.jsxs(s.Fragment,{children:[y.percent!==null?s.jsx(cf,{value:y.percent,className:"usage-pool-bar"}):null,s.jsx("span",{className:`usage-pool-view ${a.kind}`,children:y.text})]});return s.jsxs("span",{className:"usage-pool",title:a.title,children:[y.planName?s.jsx("span",{className:"usage-pool-name",children:y.planName}):null,h?s.jsx(AA,{variant:"pool",...h,children:v}):s.jsx("span",{className:"usage-pool-line",children:v}),o,f,c]})}function UG({summary:e,detail:t,blockedBadge:a,tokenSub:o}){const[c,d]=x.useState(!1),f=e.kind==="ok"||e.kind==="warn";return s.jsxs("span",{className:c?"usage-cell open":"usage-cell",children:[s.jsxs("span",{className:"usage-plan",children:[t.plan?s.jsx("span",{className:`plan-chip${t.free?" free":""}`,children:t.plan}):null,t.resetDate?s.jsx("span",{className:"plan-sub",title:r("套餐积分的重置日期"),children:r("重置 {date}",{date:t.resetDate})}):null]}),s.jsxs(wf,{open:c,onOpenChange:d,children:[s.jsxs(Yh,{render:s.jsx("button",{type:"button",className:`usage-toggle ${e.kind}`,title:e.title,"aria-label":r("积分明细")}),children:[s.jsx("span",{className:"val",children:e.text}),s.jsx("span",{className:"caret","aria-hidden":!0,children:"▾"})]}),s.jsxs(Sf,{align:"end",sideOffset:6,className:"usage-pop w-[288px]",children:[f&&t.missing.length?t.missing.map(p=>s.jsx("div",{className:"usage-pop-missing",title:p,children:p},p)):null,t.credit.length?s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"usage-pop-group",children:r("积分")}),t.credit.map(p=>s.jsx(VG,{row:p},p.name))]}):null,t.total!==null?s.jsxs("div",{className:"usage-pop-total",children:[s.jsx("span",{className:"k",children:r("可用合计")}),s.jsxs("span",{className:"v",children:[ss(t.total)," ",s.jsx("small",{children:t.unit})]})]}):null,!t.credit.length&&t.total===null?s.jsx("div",{className:"usage-pop-empty",title:r("该账号的额度只有福利 token 池(见余额格那两行),订阅统计没有积分类计量表"),children:r("该账号没有积分类读数(额度只有福利 token 池)")}):null]})]}),t.token.map(p=>s.jsx(yO,{row:p},p.name)),t.benefitAbsent?s.jsxs("span",{className:"usage-flat-line",title:r("福利按限时活动下发,不是每个账号都有 —— 正常状态,不是查询失败"),children:[s.jsx("span",{className:"usage-flat-name",children:r("福利日额度")}),s.jsx("span",{className:"usage-flat-view muted",children:r("无福利额度")})]}):null,a,o]})}function VG({row:e}){return s.jsxs("div",{className:"usage-pop-row",title:e.title,children:[s.jsxs("div",{className:"usage-pop-line",children:[s.jsx("span",{className:"usage-pop-name",children:e.name}),s.jsx("span",{className:`usage-pop-view ${e.tone}`,children:e.view})]}),e.percent!==null?s.jsx("span",{className:`usage-pop-track${e.over?" over":""}`,children:s.jsx("i",{style:{width:`${e.percent}%`},"aria-label":r("剩余 {percent}%",{percent:Math.round(e.percent)})})}):null]})}function FG({account:e,namesHidden:t}){const a=Qh(e),o=cr(An(e)),c=gu(e)||r("未命名账号"),d=String(e.email||"").trim(),f=String(e.nickname||"").trim(),p=String(e.name||"").trim(),h=w=>t?B$(w):w,b=[d&&d!==c?r("邮箱 {email}",{email:h(d)}):"",a?`${o.identifier} ${a}`:"",!e.nameCustom&&p&&p!==d&&p!==f?r("备注名 {name}",{name:h(p)}):"",f&&f!==c&&f!==d?r("昵称 {name}",{name:h(f)}):"",kf(e)?r("桌面端实时登录态(凭证每次从客户端登录态文件读取)"):"",e.updatedAt?r("更新于 {time}",{time:Ls(e.updatedAt)}):"",e.source?r("来源 {source}",{source:e.source==="imported"?r("旧数据导入"):r("手动添加")}):""].filter(Boolean),y=d&&d!==c,v=e.proxy?.error,j=b.length?s.jsx(pV,{delay:0,children:s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("div",{className:"acct-name"}),children:s.jsx("span",{className:"name",children:h(c)})}),s.jsxs(Fi,{children:[s.jsx(mV,{}),b.map((w,k)=>s.jsx("div",{children:w},k))]})]})}):s.jsx("div",{className:"acct-name",children:s.jsx("span",{className:"name",children:h(c)})});return s.jsxs(s.Fragment,{children:[j,y?s.jsx("div",{className:"acct-sub",children:s.jsx("span",{className:"acct-email",title:r("账号邮箱"),children:h(d)})}):null,v?s.jsx("div",{className:"acct-note bad",title:r("代理不可用:{error}",{error:v}),children:r("代理不可用:{error}",{error:v})}):null]})}function $G({account:e}){const t=e.proxy,a=t?.config?.source||t?.source,o=t?.label||r(a==="custom"?"自定义代理":"已设置"),c=t?.error,d=V$(),f=Array.isArray(d)?d:[];let p="";a==="pool"&&t?.config?.proxyId?p=`${Qa}${t.config.proxyId}`:t&&(p=ug);const h=[{value:"",label:r("直连")}];for(const v of f)h.push({value:`${Qa}${v.id}`,label:fu(v)});if(d===null?h.push({value:"__hint_pool__",label:r("正在读取代理列表…"),disabled:!0}):f.length||h.push({value:"__hint_pool__",label:F$()?r("代理列表读取失败(重试中)"):r("还没有代理(去「网络代理」页添加)"),disabled:!0}),p===ug){const v=a==="clash"?r("Clash 出口:"):a==="custom"?r("自定义:"):"";h.push({value:ug,label:`${v}${o}${c?r("(不可用)"):""}`})}else a==="pool"&&!f.some(v=>`${Qa}${v.id}`===p)&&h.push({value:p,label:`${o}${c?r("(不可用)"):""}`});h.push({value:AR,label:r("自定义代理…")});const b=c?r("代理不可用:{error}(转发时会回退直连);选「自定义代理…」去修改",{error:c}):a==="rotate"?r("当前:{label}(每条请求换一个出口);「自定义代理…」打开完整设置",{label:o}):a==="clash"||a==="custom"?r("当前:{label}(未经过代理池 —— 可在「网络代理」页把出口同步进池后来这里改选)",{label:o}):r("当前:{label};选项来自「网络代理」页;「自定义代理…」打开完整设置",{label:t?o:r("直连")}),y=h.find(v=>v.value===p);return s.jsxs(dt,{value:p,onValueChange:v=>{e8(e.id,String(v),p)},children:[s.jsx(pt,{className:Ue("w-full",c&&"border-destructive-bd"),title:b,"aria-label":r("出网代理"),children:s.jsx(ft,{children:y?.label||r("直连")})}),s.jsx(mt,{children:h.map(v=>s.jsx($e,{value:v.value,disabled:v.disabled,children:v.label},v.value))})]})}function qG({account:e,atFront:t}){const[a,o]=x.useState(!1),c=Ea(e),d=FA(e);return s.jsxs("div",{className:"acct-actions",children:[d?s.jsx(ne,{variant:"outline",size:"xs",title:x$(e)?b$(e):r("查看可领取的套餐与名下已有的套餐(每天一期,领取需过一次人机验证)"),onClick:()=>RR(e.id),children:r("领套餐")}):null,c?s.jsx(ne,{variant:"outline",size:"xs",disabled:a,title:r("查询该账号剩余余额(读数显示在余额列)"),onClick:()=>{o(!0),W$(e.id).finally(()=>o(!1))},children:r("余额")}):null,s.jsx(ne,{variant:"outline",size:"xs",title:r("备注名 / 启用 / 代理"),onClick:()=>og(e.id),children:r("设置")}),s.jsx(GG,{account:e,atFront:t})]})}function GG({account:e,atFront:t}){const[a,o]=x.useState(!1),c=ur(e),d=Number(e.maxConcurrent)||0,f="w-full justify-start px-2 font-normal",p=`${f} text-destructive hover:text-destructive`;return s.jsxs(wf,{open:a,onOpenChange:o,children:[s.jsx(Yh,{render:s.jsx(ne,{variant:"outline",size:"xs",title:r("更多操作")}),children:"⋯"}),s.jsx(Sf,{align:"end",sideOffset:4,className:"w-[172px] p-1.5",children:s.jsxs("div",{className:"flex flex-col gap-0.5",children:[s.jsx(ne,{variant:"ghost",size:"sm",className:p,onClick:()=>{o(!1),CR(e.id,!c)},children:r(c?"禁用":"启用")}),s.jsx(ne,{variant:"ghost",size:"sm",className:f,disabled:t,title:r(t?"已在全局队列第一位":"仅将优先级调整到全局第一位,不改变启用状态"),onClick:()=>{o(!1),Pe().wbApp?.runAccountAction?.("switch",e.id)},children:r("设为首选")}),s.jsx(ne,{variant:"ghost",size:"sm",className:f,title:r("在账号设置的「基本」分组里设置该账号同时最多处理的请求数"),onClick:()=>{o(!1),og(e.id)},children:r("并发上限:{value}",{value:d>0?d:r("不限")})}),e.hasRefreshToken?s.jsx(ne,{variant:"ghost",size:"sm",className:f,onClick:()=>{o(!1),Pe().wbApp?.runAccountAction?.("refresh",e.id)},children:r("刷新 Token")}):null,s.jsx("div",{className:"my-1 h-px bg-hairline"}),s.jsx(ne,{variant:"ghost",size:"sm",className:p,title:kf(e)?r("删除这条账号记录(不会影响客户端自己的登录态;之后可再点「导入桌面端登录态」加回来)"):void 0,onClick:()=>{o(!1),Pe().wbApp?.runAccountAction?.("remove",e.id)},children:r("删除账号")})]})})]})}function KG({account:e,onClose:t,onClear:a}){const o=bj(e),c=s.jsx(ne,{variant:"ghost",size:"icon-xs",className:"panel-close",title:r("收起"),onClick:t,children:"✕"});return o.length?s.jsxs("div",{className:"row-panel limit-panel",children:[c,s.jsxs("div",{className:"lp-head",children:[s.jsx("b",{children:gu(e)}),s.jsx("span",{className:"muted",children:r("{n} 个模型限流中 · 记录来自上游 429 / 限额码,到恢复时间自动解除",{n:o.length})}),s.jsx(ne,{variant:"outline",size:"xs",title:r("清掉该账号全部模型的限流标记"),onClick:()=>a(""),children:r("全部清除")})]}),o.map(d=>{const f=jj(d.resetAt),p=d.message||(d.status?r("上游返回 {status}",{status:d.status}):"");return s.jsxs("div",{className:"lp-row",children:[s.jsx("span",{className:"lp-model",title:d.model,children:d.model}),s.jsx(ze,{variant:"warning",shape:"tag",children:r("限流中")}),s.jsx("span",{className:"lp-reset",title:r("到恢复时间后自动解除,无需手动操作"),children:f===yj?r("恢复时间未知"):r("{time} 恢复",{time:f})}),s.jsx("span",{className:"lp-reason",title:p,children:p}),s.jsx(ne,{variant:"outline",size:"2xs",title:r("清掉本机的限流标记,立刻重新尝试该模型(上游若仍在限流会再次被标记)"),onClick:()=>a(d.model),children:r("清除标记")})]},d.model)})]}):s.jsxs("div",{className:"row-panel limit-panel",children:[r("当前没有限流中的模型。"),c]})}function YG({account:e,colSpan:t,limitsOpen:a,onClear:o}){return a?s.jsx("tr",{className:"acct-panels","data-panels-for":e.id,children:s.jsx("td",{colSpan:t,children:s.jsx(KG,{account:e,onClose:()=>dR(e.id,"limits",!1),onClear:c=>o(e.id,c)})})}):null}function XG({namesHidden:e,allPicked:t,somePicked:a,disabled:o,onToggleAll:c}){const d=s.jsx("span",{className:"col-grip",title:r("拖动调整列宽(双击还原)")});return s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{className:"cell-pick","data-col":"pick",children:s.jsx(_r,{id:"acct-select-all",checked:t,indeterminate:!t&&a,disabled:o,"aria-label":r("全选当前筛选结果"),title:r("全选 / 取消全选当前筛选结果(与批量栏同一个选择)"),onCheckedChange:f=>c(f)})}),s.jsxs("th",{className:"cell-order","data-col":"order",children:[s.jsx("span",{className:"th-label",title:r("组内先后:按住左边的把手上下拖动即可调整;整组的先后拖分组带的把手"),children:r("顺序")}),d]}),s.jsxs("th",{className:"cell-account","data-col":"account",children:[s.jsxs("span",{className:"th-label",children:[r("账号"),s.jsx(QG,{hidden:e})]}),d]}),s.jsxs("th",{className:"cell-proxy","data-col":"proxy",children:[s.jsx("span",{className:"th-label",title:r("该账号出网走的代理(Clash 出口 / 自定义 / 直连);点击可修改"),children:r("代理")}),d]}),s.jsxs("th",{className:"cell-connections","data-col":"connections",children:[s.jsx("span",{className:"th-label",title:r("此刻正在使用这个账号的请求数(含还在下发内容的流式请求);为 0 时不显示"),children:r("连接数")}),d]}),s.jsxs("th",{className:"cell-status","data-col":"status",children:[s.jsx("span",{className:"th-label",children:r("状态")}),d]}),s.jsxs("th",{className:"cell-limits","data-col":"limits",children:[s.jsx("span",{className:"th-label",title:r("该账号当前限流中的模型;点徽章看明细"),children:r("限流")}),d]}),s.jsxs("th",{className:"cell-expiry","data-col":"expiry",children:[s.jsx("span",{className:"th-label",children:r("有效期")}),d]}),s.jsxs("th",{className:"cell-usage","data-col":"usage",children:[s.jsx("span",{className:"th-label",children:r("余额")}),d]}),s.jsx("th",{className:"cell-actions","data-col":"actions",children:s.jsx("span",{className:"th-label",children:r("操作")})})]})})}function QG({hidden:e}){const t=r(e?"显示账号名":"隐藏账号名(名字显示为星号)");return s.jsx("button",{type:"button",className:`name-eye${e?" on":""}`,title:t,"aria-label":t,"aria-pressed":e,onClick:()=>z$(),dangerouslySetInnerHTML:{__html:Tg(e?"eyeOff":"eye",13)}})}const jO="dragging",Bf=["drop-before","drop-after"];let Ja=null;function wO(e){e.querySelectorAll(`.${Bf[0]}, .${Bf[1]}`).forEach(t=>{t.classList.remove(...Bf)})}function ZG(e,t){if(t==="group"){const o=e.parentElement;return o?[...o.children].filter(c=>c.classList.contains("acct-group")):[]}const a=e.parentElement;return a?[...a.children].filter(o=>o.classList.contains("acct-row")):[]}function SO(e,t){for(let a=0;aa!==e.item);wO(e.container),t.length&&(e.index>=t.length?t[t.length-1].classList.add(Bf[1]):t[e.index].classList.add(Bf[0]))}function NO(e){if(!Ja)return;if(e.buttons===0){Eg(!1);return}const t=Ja.items.filter(o=>o!==Ja.item),a=SO(t,e.clientY);a!==Ja.index&&(Ja.index=a,WG(Ja))}function Eg(e){const t=Ja;t&&(Ja=null,window.removeEventListener("pointermove",NO),window.removeEventListener("pointerup",kO),window.removeEventListener("pointercancel",CO),window.removeEventListener("keydown",TO),document.body.classList.remove("queue-dragging"),t.item.classList.remove(jO),wO(t.container),e&&(t.kind==="group"?Qj?.onDrop({kind:"group",provider:t.provider,index:t.index}):Qj?.onDrop({kind:"row",provider:t.provider,accountId:t.accountId,index:t.index})))}function kO(){Eg(!0)}function CO(){Eg(!1)}function TO(e){e.key==="Escape"&&Eg(!1)}let Qj=null;function JG(e,t){Qj=t,e&&e.dataset.queueDragBound!=="1"&&(e.dataset.queueDragBound="1",e.addEventListener("pointerdown",a=>{if(a.button!==0||Ja)return;const o=a.target,c=o?.closest?.(".queue-grip"),d=o?.closest?.(".order-grip");if(!c&&!d)return;if(a.preventDefault(),c&&t.isLocked()){t.onLockedAttempt();return}const f=(c??d).closest("tbody.acct-group, tr.acct-row");if(!f)return;const p=c?"group":"row",h=f.dataset.provider||f.closest("tbody.acct-group")?.dataset.provider||"",b=f.dataset.id||"";if(p==="row"&&!b)return;const y=ZG(f,p);if(y.length<2)return;const v=y.filter(j=>j!==f);Ja={kind:p,provider:h,accountId:b,item:f,container:f.parentElement||e,items:y,index:SO(v,a.clientY)},f.classList.add(jO),document.body.classList.add("queue-dragging"),window.addEventListener("pointermove",NO),window.addEventListener("pointerup",kO),window.addEventListener("pointercancel",CO),window.addEventListener("keydown",TO)}))}let Ag=null,EO=!1,Zj=0,Rg=null,AO="";function RO(){return Ag?Ag.apply(Oj):Oj}function OO(){window.wbAccountsView?.render?.()}function e7(){const e=RO(),t=`${Rg?"T":"F"}|${e.map(o=>`${o.key}:${o.align}`).join("|")}`;if(t===AO)return;AO=t,Pe().wbColSettings?.syncStaticHead("accounts",Rg);const a=[...Rg?.querySelectorAll("thead th")||[]];a.forEach((o,c)=>{const d=o.querySelector(".col-grip");d&&(d.style.display=c===a.length-1?"none":"")})}function t7(){const e=x.useSyncExternalStore(sR,Gs),t=x.useRef(null),[,a]=x.useReducer(B=>B+1,0),o=!!Sj(),c=Al(),{groups:d,allGroups:f}=T$(Wa,Rl),p=E$(Wa,Rl),h=[{value:"all",label:r("全部({n})",{n:c.length})}].concat(rR().map(B=>({value:B.id,label:r("{label}({count})",{label:r(B.label),count:B.count})}))),b=d.flatMap(B=>B.accounts),y=A$(),v=RO(),j=gg(b.length,"accounts",{defaultSize:"all"}),w=j.paged?j.slice(b):b,k=sg()||j.paged,S=sg()?r("清除筛选"):r("把每页调回「全部」");x.useEffect(()=>{$$()}),x.useEffect(()=>{M$()},[e.version]),x.useLayoutEffect(()=>{if(!EO){if(!Pe().wbColSettings?.register){window.clearTimeout(Zj),Zj=window.setTimeout(()=>N(B=>B+1),50);return}EO=!0,Ag=Pe().wbColSettings?.register({id:"accounts",label:r("账号表"),columns:Oj.map(B=>({key:B.key,label:B.label,align:B.align,legacyAlign:B.legacyAlign})),mount:()=>document.querySelector("#batch-bar .batch-actions"),onChange:OO})||null,Ag&&a();return}e7()});const[,N]=x.useState(0);x.useEffect(()=>()=>window.clearTimeout(Zj),[]),x.useEffect(()=>{F8(t.current,OO)},[]);const R=b.map(B=>B.id),P=R.length>0&&R.every(B=>e.selected.has(B)),T=R.some(B=>e.selected.has(B)),C=[...e.selected].filter(B=>!R.includes(B)).length,E=e.selected.size>0,D=f.length>0&&f.every(B=>e.collapsed.has(B.provider)),I=new Map;for(const B of d)I.set(B.provider,w.filter(L=>An(L)===B.provider).map(L=>L.id));const O=x.useRef({displayed:d,all:f,renderedRows:I});x.useEffect(()=>{O.current={displayed:d,all:f,renderedRows:I}});const _=x.useRef({locked:!1,lockReason:"",onDrop:B=>{}}),z=x.useCallback(B=>{const{displayed:L,all:F}=O.current;if(B.kind==="group"){const Z=F.findIndex(te=>te.provider===B.provider);if(Z<0)return;const ae=F[Z],ce=F.filter((te,ke)=>ke!==Z),W=B.indexte.provider===W),ve=W===null||ue<0?ce.length:ue;if(ve===Z)return;const he=[...ce.slice(0,ve),ae,...ce.slice(ve)].flatMap(te=>te.members.map(ke=>ke.id));TR(he,r("{name} 移到第 {rank} 顺位",{name:ae.label,rank:ve+1}));return}const $=F.find(Z=>Z.provider===B.provider);if(!$)return;const X=$.members.findIndex(Z=>Z.id===B.accountId);if(X<0)return;const K=$.members[X],q=$.members.filter((Z,ae)=>ae!==X),Q=O.current.renderedRows.get(B.provider)||[],G=B.indexZ.id===G),Y=G===null||J<0?q.length:J;if(Y===X)return;const re=[...q.slice(0,Y),K,...q.slice(Y)],U=F.map(Z=>Z.provider===B.provider?{...Z,members:re}:Z).flatMap(Z=>Z.members.map(ae=>ae.id));TR(U,r("{name} 移到 {group} 组内第 {rank} 位",{name:String(K.name||K.id),group:r($.label),rank:Y+1}))},[]);x.useEffect(()=>{_.current={locked:k,lockReason:S,onDrop:z}}),x.useEffect(()=>{JG(t.current,{isLocked:()=>_.current.locked,onLockedAttempt:()=>_e(r("当前视图不能调整组顺位:{reason} 之后再拖动",{reason:_.current.lockReason}),"err"),onDrop:B=>_.current.onDrop(B)})},[]);function H(B,L,F){switch(B){case"pick":return s.jsx(_r,{checked:F.picked,"data-pick":L.id,title:r("勾选后可批量操作"),"aria-label":r("勾选后可批量操作"),onCheckedChange:$=>P$(L.id,$)});case"order":return s.jsx(jG,{account:L,rank:F.rank});case"account":return s.jsx(FG,{account:L,namesHidden:e.namesHidden});case"proxy":return s.jsx($G,{account:L});case"connections":return s.jsx(TG,{account:L});case"status":return s.jsx(NG,{account:L});case"limits":return s.jsx(kG,{account:L,open:F.limitsOpen});case"expiry":return s.jsx(CG,{account:L});case"usage":return s.jsx(HG,{account:L});case"actions":return s.jsx(qG,{account:L,atFront:F.seat.position<=1});default:return null}}return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel account-table",children:[s.jsxs("div",{className:"toolbar",children:[s.jsxs("div",{className:"group","data-provider-group":"1",children:[s.jsx("span",{className:"label",children:r("提供商")}),s.jsxs(dt,{value:e.filter.provider,onValueChange:B=>O$(String(B)),children:[s.jsx(pt,{className:"max-w-none min-w-0 w-full min-[768px]:max-w-[200px] min-[768px]:min-w-[130px] min-[768px]:w-auto","aria-label":r("按提供商筛选账号"),children:s.jsx(ft,{children:h.find(B=>B.value===e.filter.provider)?.label||r("全部")})}),s.jsx(mt,{children:h.map(B=>s.jsx($e,{value:B.value,children:B.label},B.value))})]})]}),s.jsx("div",{className:"divider","data-provider-divider":"1"}),s.jsxs("div",{className:"group",children:[s.jsx("span",{className:"label",children:r("搜索")}),s.jsx(Fe,{className:"acct-search",type:"search",value:e.filter.q,placeholder:r("账号名 / 邮箱 / 备注"),"aria-label":r("搜索账号"),onChange:B=>R$(B.currentTarget.value)})]}),s.jsx("div",{className:"divider"}),s.jsxs("div",{className:"group",children:[s.jsx("span",{className:"label",children:r("状态")}),s.jsx(En,{options:[{value:"all",label:r("全部"),count:p.enabledAll??0},{value:"enabled",label:r("启用"),count:p.enabled??0},{value:"disabled",label:r("禁用"),count:p.disabled??0}],value:e.filter.enabled,onValueChange:B=>aR("enabled",B),"aria-label":r("启用状态")})]}),s.jsxs("div",{className:"group",children:[s.jsx("span",{className:"label",children:r("限额")}),s.jsx(En,{options:[{value:"all",label:r("全部"),count:p.limitAll??0},{value:"normal",label:r("正常"),count:p.normal??0,disabled:e.filter.enabled==="disabled"},{value:"limited",label:r("已限流"),count:p.limited??0,disabled:e.filter.enabled==="disabled"}],value:e.filter.limit,onValueChange:B=>aR("limit",B),"aria-label":r("限额状态")})]}),s.jsxs("div",{className:"actions",children:[s.jsx(ne,{id:"btn-fold-groups",variant:"outline",disabled:!f.length,title:r(D?"展开全部分组":"折叠全部分组(只留组头)"),onClick:()=>D$(f.map(B=>B.provider),!D),children:r(D?"展开全部":"折叠全部")}),s.jsx(ne,{id:"btn-add-account-2",variant:"default",title:r("登录 / 导入一个新账号"),onClick:()=>{Pe().wbAddAccountModal?.open?.(),Pe().wbAccountAddForms?.syncAddProvider?.()},children:r("添加账号")}),s.jsx(ne,{id:"btn-query-usage",variant:"outline",disabled:e.usageBusy||!c.some(Ea),title:r("查询全部账号的余额(含已禁用账号 —— 禁用只表示不参与转发)"),onClick:()=>{NR()},children:e.usageBusy?r("查询中…"):r("查询余额")})]})]}),s.jsxs("div",{className:Ue("batch-bar",E&&"active"),id:"batch-bar",children:[s.jsxs("label",{className:"batch-select-all",children:[s.jsx(_r,{id:"batch-select-all",checked:P,indeterminate:!P&&T,disabled:!R.length,"aria-label":r("全选当前筛选结果"),onCheckedChange:B=>cR(R,B)}),s.jsx("span",{id:"batch-select-label",children:R.length?r("全选当前筛选结果({n} 个)",{n:R.length}):r("没有可全选的账号")})]}),s.jsxs("span",{className:"batch-count",children:[r("已选")," ",s.jsx("b",{id:"batch-count",children:e.selected.size})," ",r("个 · 共")," ",s.jsx("b",{id:"accounts-count",children:c.length})," ",r("个")]}),s.jsx("span",{className:"batch-summary",id:"accounts-group-summary",children:d.length?r("{groups} 家 · 显示 {rows} 行",{groups:d.length,rows:R.length}):""}),k?s.jsx("span",{className:"batch-hidden",title:r("筛选 / 搜索 / 分页生效时组顺位不可拖动(别家的组整组不可见,落点没法定位)"),children:r("组顺位已锁定")}):null,sg()?s.jsx(ne,{id:"btn-clear-filter",variant:"ghost",size:"xs",title:r("清空搜索与三个筛选档位,回到全部账号"),onClick:()=>lR(),children:r("清除筛选")}):null,C?s.jsx("span",{className:"batch-hidden",id:"batch-hidden-hint",children:r("另有 {n} 个已勾选账号被当前筛选隐藏,仍会参与操作",{n:C})}):null,s.jsxs("div",{className:"batch-actions",children:[s.jsx(ne,{id:"btn-batch-open",variant:"outline",disabled:!E,onClick:()=>kj([...e.selected],"enable"),children:r("批量操作")}),s.jsx(ne,{id:"btn-batch-clear",variant:"outline",disabled:!E,onClick:()=>_$(),children:r("取消选择")})]})]}),s.jsx("div",{className:"acct-scroll",id:"account-list",ref:t,children:o?c.length?b.length?s.jsxs("table",{className:"acct-table",ref:n7,style:{minWidth:`${U8(v.map(B=>B.key))}px`},children:[s.jsx(s7,{}),s.jsx(XG,{namesHidden:e.namesHidden,allPicked:P,somePicked:T,disabled:!R.length,onToggleAll:B=>cR(R,B)}),d.map(B=>{const L=e.collapsed.has(B.provider),F=w.filter($=>An($)===B.provider);return s.jsxs("tbody",{className:"acct-group","data-provider":B.provider,children:[s.jsx(SG,{group:B,collapsed:L,colSpan:v.length}),L?null:F.map($=>{const X=B.members.findIndex(q=>q.id===$.id)+1,K=t8($,y,X>0?X:1);return s.jsxs(x.Fragment,{children:[s.jsx("tr",{className:Ue("acct-row",!ur($)&&"disabled",K.picked&&"selected"),"data-id":$.id,"data-provider":B.provider,"data-desktop":kf($)?"1":void 0,children:v.map(q=>s.jsx("td",{className:`cell-${q.key} ta-${q.align}`,children:H(q.key,$,K)},q.key))}),s.jsx(YG,{account:$,colSpan:v.length,limitsOpen:uR($.id,"limits"),onClear:(q,Q)=>{J$(q,Q)}})]},$.id)})]},B.provider)})]}):s.jsxs("div",{className:"empty",children:[r("当前筛选条件下没有账号"),sg()?s.jsx("button",{type:"button",className:"link-btn",onClick:()=>lR(),children:r("清除筛选")}):null]}):s.jsx("div",{className:"empty",children:r("暂无账号,请点击右上角「添加账号」")}):s.jsxs("div",{className:"empty",children:[s.jsx("span",{className:"spinner"}),r("正在加载…")]})}),s.jsx($i,{total:b.length,range:j.paged?{start:j.rangeStart,end:j.rangeEnd}:null,page:j.page,pageCount:j.pageCount,size:j.size,onSizeChange:j.setSize,onPageChange:j.goto})]}),s.jsx(D8,{})]})}function n7(e){Rg=e}function s7(){const e=H8(),t=a=>s.jsx("col",{"data-col":a,style:e[a]?{width:`${e[a]}px`}:void 0},a);return s.jsxs("colgroup",{children:[t("pick"),t("order"),t("account"),t("proxy"),t("connections"),t("status"),t("limits"),t("expiry"),t("usage"),t("actions")]})}const MO='.page[data-page="accounts"]';let Wj=null;function DO(){if(Wj)return;const e=document.querySelector(MO);e&&(e.replaceChildren(),Wj=jn.createRoot(e),Ts.flushSync(()=>{Wj.render(s.jsx(t7,{}))}))}s8(),Y$(),document.querySelector(MO)?DO():document.addEventListener("DOMContentLoaded",DO,{once:!0});const r7=64,a7=100,l7=r("OpenAI 兼容填到 /v1;Anthropic 填根地址"),o7=r("Anthropic 协议填根地址,不要带 /v1"),i7="https://open.bigmodel.cn/api/paas/v4",c7="https://api.anthropic.com",u7=[{value:"chat_completions",label:"OpenAI - Chat Completions"},{value:"responses",label:"OpenAI - Responses"},{value:"anthropic",label:"Anthropic - Messages"}],Tu="custom-protocol-select",Eu="custom-name-input",Au="custom-baseurl-input",Hf="custom-apikey-input",Uf="custom-noauth-check",Ru="custom-existing-select",Vf="custom-existing-apikey-input",Ff="custom-existing-noauth-check",$f="custom-existing-name-input",d7="custom-create-button",f7="custom-existing-button",p7="custom-existing-remove";let Jj=!1;const IO=()=>gt().wbProviders?.PROTOCOL_OPTIONS||u7,ew=()=>gt().wbProviders?.customList?.()||[],tw="custom-balance",nw="custom-existing-balance",qf=(e,t)=>`${e}-${t}-input`;function PO(e){if(!e)return"";const t=gt().wbPresetProviders?.presetOf?.(e);return String(t?.balance?.scheme||"")}function _O(e,t){const a=Mf(e);if(!a||!a.fields.length)return null;const o={};for(const c of a.fields){const d=dr(qf(t,c.key));d&&(o[c.key]=d)}return Object.keys(o).length?o:null}function LO(e,t){const a=Mf(e);if(a)for(const o of a.fields)Eo(qf(t,o.key),"")}function zO({scheme:e,prefix:t}){const a=Mf(e);return a?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{children:r("余额查询")}),s.jsxs("div",{className:"col-start-2 row-start-1 flex h-[30px] items-center",children:[s.jsx("span",{className:"text-xs text-subtle",children:r("方案:{label}",{label:a.label})}),s.jsx("span",{className:"ml-1.5 text-xs text-subtle",children:a.endpoint})]}),s.jsx("span",{className:"hint",children:a.note})]}),a.fields.map(o=>s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:qf(t,o.key),children:o.label}),s.jsx(Fe,{id:qf(t,o.key),type:o.secret?"password":"text",autoComplete:o.secret?"new-password":"off",placeholder:o.placeholder,...Lr(qf(t,o.key))}),s.jsx("span",{className:"hint",children:o.hint})]},o.key))]}):null}async function sw(e,t){if(!Jj){Jj=!0,e(!0);try{await t()}finally{Jj=!1,e(!1)}}}async function BO(e){gt().wbAddAccountModal?.close?.(),gt().wbProviders?.refreshCustom?.(),await gt().wbApp?.refresh?.(),Ln(e)}function Gf(e,t){Eo(e,t?"1":"")}function Og(e){return dr(e)==="1"}function HO({checked:e,note:t,onChange:a}){return s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{children:r("鉴权")}),s.jsx("div",{className:"col-start-2 row-start-1 flex h-[30px] items-center",children:s.jsxs("label",{className:"inline-flex cursor-pointer items-center gap-2.5",children:[s.jsx(_r,{checked:e,"aria-label":r("该上游无需鉴权"),onCheckedChange:o=>a(o===!0)}),s.jsx("span",{className:"text-xs text-subtle",children:r("该上游无需鉴权(不发送鉴权头)")})]})}),s.jsx("span",{className:"hint",children:t})]})}function m7({mode:e,providerHint:t,presetKey:a,showToken:o,version:c}){const d=IO(),[f,p]=x.useState(()=>dr(Tu)||d[0].value),[h,b]=x.useState(""),[y,v]=x.useState(""),[j,w]=x.useState(()=>dr(Ru)),[k,S]=x.useState(()=>Og(Uf)),[N,R]=x.useState(()=>Og(Ff)),P=x.useMemo(()=>ew(),[c]),C=(t&&P.some(B=>B.id===t)?t:"")||(P.some(B=>B.id===j)?j:P[0]?.id||""),E=P.find(B=>B.id===C)?.name||r("该提供商");x.useEffect(()=>{Eo(Ru,C)},[C]),x.useEffect(()=>{if(!a)return;const B=gt().wbPresetProviders?.presetOf?.(a);if(!B)return;const L=B.account?.noAuth===!0;if(e!=="create"){R(L),Gf(Ff,L);return}Eo(Eu,B.name||""),Eo(Au,B.baseUrl||""),B.protocol&&(p(B.protocol),Eo(Tu,B.protocol)),S(L),Gf(Uf,L),b(B.hint||""),v(B.placeholder||"")},[e,a,t,o]);const D=f==="anthropic",I=h||(D?o7:l7),O=y||(D?c7:i7),_=e==="create"?PO(a):"",z=e==="existing"?String(P.find(B=>B.id===C)?.balanceScheme||""):"",H=(B,L)=>F=>{L(F),Gf(B,F)};return s.jsxs(s.Fragment,{children:[s.jsxs(dn,{hidden:e!=="create",children:[s.jsxs("div",{className:"add-panel-head",children:[s.jsx("h3",{children:r("上游信息")}),s.jsx("span",{children:r("创建这个提供商,并同时建立它的第一个账号。")})]}),s.jsxs("div",{className:"add-form",children:[s.jsxs("div",{className:"add-field",children:[s.jsxs(Je,{htmlFor:Eu,children:[r("名称"),s.jsx("i",{className:"req","aria-hidden":"true",children:"*"})]}),s.jsx(Fe,{id:Eu,type:"text",maxLength:r7,"aria-required":"true",placeholder:r("如:智谱 GLM"),...Lr(Eu)}),s.jsx("span",{className:"hint",children:r("1~64 个字符,账号列表里按它分组显示")})]}),s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:Tu,children:r("协议")}),s.jsxs(dt,{value:f,onValueChange:B=>{const L=String(B);p(L),Eo(Tu,L),b("")},children:[s.jsx(pt,{id:Tu,className:"col-start-2 row-start-1 w-full",children:s.jsx(ft,{children:d.find(B=>B.value===f)?.label||f})}),s.jsx(mt,{children:d.map(B=>s.jsx($e,{value:B.value,children:B.label},B.value))})]})]}),s.jsxs("div",{className:"add-field",children:[s.jsxs(Je,{htmlFor:Au,children:["Base URL",s.jsx("i",{className:"req","aria-hidden":"true",children:"*"})]}),s.jsx(Fe,{id:Au,type:"text","aria-required":"true",placeholder:O,...Lr(Au)}),s.jsx("span",{className:"hint",id:"custom-baseurl-hint",children:I})]}),s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:Hf,children:"API Key"}),s.jsx(Fe,{id:Hf,type:"password",autoComplete:"new-password",placeholder:"sk-…",disabled:k,...Lr(Hf)}),s.jsx("span",{className:"hint",children:r(k?"不需要 Key:转发与拉取模型都不发送鉴权头":"上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)")})]}),s.jsx(HO,{checked:k,note:r(k?"已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头":"本地 Ollama、OpenCode Zen 免费档这类上游要勾上,否则账号不可用"),onChange:H(Uf,S)}),s.jsx(zO,{scheme:_,prefix:tw})]})]}),s.jsxs(dn,{hidden:e!=="existing",children:[s.jsxs("div",{className:"add-panel-head",children:[s.jsx("h3",{children:r("账号信息")}),s.jsxs("span",{children:[r("添加到 "),s.jsx("b",{children:E}),r(" 同一家可以放多把 key,按优先级轮换。")]})]}),s.jsxs("div",{className:"add-form",children:[s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:Ru,children:r("提供商")}),s.jsxs(dt,{value:C,onValueChange:B=>w(String(B)),children:[s.jsx(pt,{id:Ru,className:"col-start-2 row-start-1 w-full",children:s.jsx(ft,{children:E})}),s.jsx(mt,{children:P.map(B=>s.jsx($e,{value:B.id,children:B.name||B.id},B.id))})]})]}),s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:Vf,children:"API Key"}),s.jsx(Fe,{id:Vf,type:"password",autoComplete:"new-password",placeholder:"sk-…",disabled:N,...Lr(Vf)}),s.jsx("span",{className:"hint",children:r(N?"不需要 Key:转发与拉取模型都不发送鉴权头":"上游不要鉴权时留空,并勾选下面一项(留空又不勾会被当成未配置凭证)")})]}),s.jsx(HO,{checked:N,note:r(N?"已声明无需鉴权:账号会被正常选路,出网时不带任何鉴权头":"同一家可以混着放:有 Key 的账号与无鉴权账号各按各的规则走;无需鉴权的账号也能并存多条(各自可配不同的出网代理)"),onChange:H(Ff,R)}),s.jsx(zO,{scheme:z,prefix:nw}),s.jsxs("div",{className:"add-field",children:[s.jsx(Je,{htmlFor:$f,children:r("备注名")}),s.jsx(Fe,{id:$f,type:"text",maxLength:a7,placeholder:r("可选"),...Lr($f)}),s.jsx("span",{className:"hint",children:r("留空则用提供商名称")})]})]})]})]})}function UO(e,t){const a=Co(t);Ln(r("添加失败:{reason}",{reason:a}),"err"),e.setHint(a)}async function h7(e){const t=dr(Eu),a=dr(Tu)||IO()[0].value,o=dr(Au),c=dr(Hf),d=Og(Uf);if(!t){Ln(r("请填写名称"),"err");return}if(!o){Ln(r("请填写 Base URL"),"err");return}await sw(e.setBusy,async()=>{const f={name:t,protocol:a,baseUrl:o},p=e.presetKey?gt().wbPresetProviders?.presetOf?.(e.presetKey):null,h=p?.quirks||{};h.urlSuffix&&(f.urlSuffix=h.urlSuffix),h.headers&&Object.keys(h.headers).length&&(f.headers={...h.headers}),h.anthropicToolType&&(f.anthropicToolType=h.anthropicToolType),p?.clientEmulation&&(f.clientEmulation=p.clientEmulation);const b=PO(e.presetKey);b&&(f.balanceScheme=b);const y=_O(b,tw);y&&(f.balanceQuery=y),d?f.noAuth=!0:c&&(f.apiKey=c),e.setHint("");try{const v=await gt().wbProviders?.customRequest?.("POST","/api/custom-providers",f);Lj([Eu,Au,Hf]),LO(b,tw),Gf(Uf,!1);const j=v?.provider?.name||t;await BO(r("✅ 已创建自定义提供商「{name}」并添加账号",{name:j}))}catch(v){UO(e,v)}})}async function g7(e){const t=dr(Ru);if(!t){Ln(r("请先选择一个自定义提供商"),"err");return}const a=dr(Vf),o=Og(Ff),c=dr($f),d=String(ew().find(f=>f.id===t)?.balanceScheme||"");await sw(e.setBusy,async()=>{const f={provider:t};o?f.noAuth=!0:a&&(f.apiKey=a),c&&(f.name=c);const p=_O(d,nw);p&&(f.balanceQuery=p),e.setHint("");try{const h=await gt().wbProviders?.customRequest?.("POST","/api/accounts",f);Lj([Vf,$f]),LO(d,nw),Gf(Ff,!1);const b=h?.account?.name||ew().find(j=>j.id===t)?.name||"",y=b?`:${b}`:"",v=h?.created!==!1?r("✅ {label}账号已添加{name}",{label:"",name:y}):r("✅ 已更新已有账号{name}(同一把 API Key 只保留一条,重复添加会合并)",{name:y});await BO(v)}catch(h){UO(e,h)}})}async function x7(){const e=dr(Ru);if(!e){Ln(r("请先选择一个自定义提供商"),"err");return}const t=gt().wbCustomProvidersUi?.remove;if(typeof t!="function"){Ln(r("删除功能不可用(脚本未就绪)"),"err");return}await sw(()=>{},async()=>{await t(e)&>().wbAddAccountModal?.close?.()})}function b7({mode:e,presetKey:t}){const[a,o]=x.useState(!1),[c,d]=x.useState(""),f={presetKey:t,setBusy:o,setHint:d};return s.jsxs(s.Fragment,{children:[s.jsx("span",{className:`add-foot-hint${c?" err":""}`,id:"add-form-foot-hint",children:c}),s.jsxs("span",{className:"add-foot-actions",id:"add-form-foot-actions",children:[e==="existing"?s.jsx(ne,{id:p7,variant:"destructive",title:r("级联删除名下全部账号,不可恢复"),onClick:()=>{x7()},children:r("删除此提供商")}):null,s.jsx(ne,{id:d7,hidden:e!=="create",disabled:a,onClick:()=>{h7(f)},children:r(a&&e==="create"?"提交中…":"创建并添加账号")}),s.jsx(ne,{id:f7,hidden:e!=="existing",disabled:a,onClick:()=>{g7(f)},children:r(a&&e==="existing"?"提交中…":"添加账号")})]})]})}const rw={step:"pick",accountType:Kj,search:"",provider:Gi,providerHint:"",presetKey:"",showToken:0},VO=()=>gt().wbProviders?.customList?.()||[];function v7({onClose:e,onReady:t}){const[a,o]=x.useState(rw),[c,d]=x.useState(0),f=x.useCallback(()=>d(T=>T+1),[]),p=x.useCallback(()=>{o(rw);const T=gt().wbProviders;(T?.all?.()||[]).length||T?.load?.().then(f),T?.refreshCustom?.().then(f)},[f]),h=x.useCallback(()=>{p(),o({...rw,step:"form",provider:wu})},[p]);x.useEffect(()=>(t({reset:p,openNewCustomForm:h}),()=>t(null)),[t,p,h]),x.useEffect(()=>{gt().wbWebLogin?.refresh?.()},[]),x.useEffect(()=>{gt().wbProviders?.refreshCustom?.().then(f)},[f]),x.useEffect(()=>{a.step!=="form"||a.provider!==wu||gt().wbProviders?.refreshCustom?.().then(f)},[a.step,a.provider,a.showToken,f]);const b=fq(a.provider),y=a.provider===wu,v=a.provider===Gi||y||!!b,j=a.providerHint?"existing":"create",w=a.providerHint?VO().find(T=>T.id===a.providerHint)?.name||"":a.presetKey&>().wbPresetProviders?.presetOf?.(a.presetKey)?.name||"",k=a.provider===Gi?Bj:r(gt().wbProviders?.labelOf?.(a.provider)||a.provider),S=y?a.providerHint||a.presetKey?r("登录 / 添加 {name} 账号",{name:w||r("自定义提供商")}):r("新建自定义提供商"):r("登录 / 添加 {name} 账号",{name:k});function N(T){if(!T)return;const C={step:"form",showToken:a.showToken+1};if(T===Xj)o(E=>({...E,...C,provider:wu,providerHint:"",presetKey:""}));else if(T.startsWith(zf)){const E=T.slice(zf.length),D=KR(gt().wbPresetProviders?.presetOf?.(E));o(I=>({...I,...C,provider:wu,providerHint:D?.id||"",presetKey:E}))}else VO().some(E=>E.id===T)?o(E=>({...E,...C,provider:wu,providerHint:T,presetKey:""})):o(E=>({...E,...C,provider:T,providerHint:"",presetKey:""}))}const R=()=>o(T=>({...T,step:"pick"})),P=a.accountType===fG;return s.jsx(Yt,{open:!0,onOpenChange:T=>{T||e()},children:s.jsxs(Xt,{className:"w-[min(1100px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("添加账号")})}),s.jsx(Lt,{children:s.jsx(yG,{accountType:a.accountType,onAccountTypeChange:T=>o(C=>({...C,accountType:T})),search:a.search,onSearchChange:T=>o(C=>({...C,search:T})),onPick:N,version:c,importing:P,importPanel:void 0})}),null,s.jsx(Yt,{open:a.step==="form",onOpenChange:T=>{T||R()},children:s.jsxs(Xt,{keepMounted:!0,overlayForceRender:!0,className:"w-[min(620px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:S})}),s.jsxs(Lt,{children:[s.jsx(dG,{active:a.provider===Gi}),eO.map(T=>s.jsx(lG,{config:T,active:a.provider===T.provider},T.provider)),s.jsx("div",{className:"add-provider-block",style:y?void 0:{display:"none"},children:s.jsx(m7,{mode:j,providerHint:a.providerHint,presetKey:a.presetKey,showToken:a.showToken,version:c})}),v?null:s.jsx("div",{className:"add-provider-block",children:s.jsxs(dn,{children:[s.jsx("h3",{children:r("该提供商账号添加功能即将上线")}),s.jsx("p",{children:r("「{name}」的账号添加功能还在开发中,敬请期待。",{name:k})})]})})]}),y?s.jsx(tn,{children:s.jsx(b7,{mode:j,presetKey:a.presetKey})}):null]})})]})})}let Do=null,Ou=null,Xi=null,Mg=null;function y7(){Do&&(Do.unmount(),Do=null),Ou&&(Ou.remove(),Ou=null),Xi=null}function FO(){Ou=document.createElement("div"),document.body.append(Ou),Do=jn.createRoot(Ou),Do.render(s.jsx(v7,{onClose:$O,onReady:e=>{if(Xi=e,!e)return;const t=Mg;Mg=null,t?.()}}))}function $O(){gt().wbWebLogin?.cancelIfActive?.(""),gt().wbAutoclawOauth?.cancel?.(),y7()}function aw(){if(Do){Xi?.reset();return}Mg=()=>Xi?.reset(),FO()}function j7(){if(Do){Xi?.openNewCustomForm();return}Mg=()=>Xi?.openNewCustomForm(),FO()}for(const e of["btn-add-account","btn-add-account-2"])document.getElementById(e)?.addEventListener("click",aw);const qO=window;qO.wbAddAccountModal={open:aw,close:$O},qO.wbAccountAddForms={syncAddProvider:()=>{Do?Xi?.reset():aw()},openNewCustomForm:j7};const w7=3065;let Mu=null;function GO(){return window.workbuddyDesktop}const S7="same-origin";let Dg=null;function N7(e){const t={};if(!e||typeof e!="object")return t;for(const[a,o]of Object.entries(e))typeof o=="string"&&o&&(t[a]=o);return t}async function k7(e=!1){if(Dg&&!e)return Dg;let t={};try{t=N7(await GO()?.directCredentials?.())}catch{}return Dg=t,t}async function KO(e=!1){if(Mu&&!e)return Mu;const t=GO();if(t?.platform==="web"){const o=typeof window>"u"?"":window.location?.origin;if(o&&o!=="null")return Mu=o,Mu}let a=0;try{const o=await t?.getBackendStatus?.(),c=Number(o?.port);Number.isFinite(c)&&c>0&&(a=c)}catch{}return a>0?(Mu=`http://127.0.0.1:${a}`,Mu):`http://127.0.0.1:${w7}`}async function YO(){const t=await window.workbuddyDesktop?.getModelManage?.(),a=Array.isArray(t?.models)?t.models:[],o=Array.isArray(t?.mappings)?t.mappings:[],c=new Set,d=[],f=new Set;for(const p of a){if(p.enabled!==!0)continue;const h=String(p.provider??""),b=String(p.id??"");!h||!b||(c.add(`${h}${b}`),f.has(b)||(f.add(b),d.push(b)))}for(const p of o){if(p.enabled!==!0||p.isDefault===!0)continue;const h=String(p.provider??""),b=String(p.target??""),y=String(p.alias??"");(!y||!f.has(y)&&c.has(`${h}${b}`))&&(f.add(y),d.push(y))}return d}const lw=`你是 Agent2API 的内置助手,帮用户管理本机的模型转发配置。 说话简洁,别铺垫。配置项一律用等宽字写出准确的 ID(模型名、账号名、提供商名),不要用「那个模型」这类含糊说法。 调用改动类工具之前,先用一句话说清将要改动什么;确认卡由界面渲染,不要跳过它直接执行。 -拿不准的配置先去读(获取模型列表 / 查询账号余额),不要凭印象改。`;function YO(e,t){if(typeof e=="string"&&e.trim())return e.trim();if(e&&typeof e=="object"){const a=e.message;if(typeof a=="string"&&a.trim())return a.trim();try{return JSON.stringify(e)}catch{}}return`HTTP ${t}`}function w7(e,t){const a=e instanceof Error?e.message:String(e);return new Error(r("连接网关失败({base}):{message}",{base:t,message:a}))}async function ow(e,t,a=!1){const o=await GO(),c={...await j7()},d=t.body===void 0?void 0:JSON.stringify(t.body);d!==void 0&&(c["Content-Type"]="application/json");let f;try{f=await fetch(o+e,{method:t.method,headers:c,body:d,signal:t.signal,credentials:v7})}catch(p){throw t.signal?.aborted?p:w7(p,o)}return f.status===401&&!a?(await f.text().catch(()=>""),Mg=null,ow(e,t,!0)):f}async function XO(e,t,a){const o=await ow(t,{method:e,body:a}),c=await o.text();let d=null;try{d=c?JSON.parse(c):null}catch{d=null}const f=d;if(!o.ok||f?.success===!1){const h=f?.error??d?.error,b=YO(h,o.status);throw o.status===404?new Error(r("这一版网关还没有 AI 助手接口(HTTP 404):后端还是旧的,重新编译 / 重启客户端后再试。{message}",{message:b})):new Error(b)}return f&&typeof f=="object"&&"data"in f?f.data:d}async function QO(){const t=(await XO("GET","/api/assistant/config"))?.config;if(!t||typeof t!="object")throw new Error(r("配置响应不完整"));const a=typeof t.model=="string"?t.model:t.model?.id;return{model:typeof a=="string"&&a.trim()?a:null,systemPromptEnabled:t.systemPromptEnabled!==!1,systemPrompt:typeof t.systemPrompt=="string"?t.systemPrompt:"",tools:t.tools&&typeof t.tools=="object"?t.tools:{}}}async function ZO(e){const t=await XO("PUT","/api/assistant/config",{config:e});return t?.config&&typeof t.config=="object"?t.config:e}function S7(e){return e.map(t=>{if(t.role==="tool")return{role:"tool",tool_call_id:t.toolCallId,content:t.content};if(t.role==="assistant"){const a={role:"assistant",content:t.content||""};return t.toolCalls?.length&&(a.tool_calls=t.toolCalls.map(o=>({id:o.id,type:"function",function:{name:o.name,arguments:o.arguments}}))),a}return{role:"user",content:t.content}})}async function N7(e){const t={messages:S7(e.messages)};e.tools.length&&(t.tools=e.tools);const a=await ow("/api/assistant/chat",{method:"POST",body:t,signal:e.signal});if(!a.ok||!a.body){const y=await a.text().catch(()=>"");let v=null;try{v=y?JSON.parse(y):null}catch{}const j=v?.error,w=YO(j,a.status);throw a.status===404?new Error(r("这一版网关还没有 AI 助手接口(HTTP 404):后端还是旧的,重新编译 / 重启客户端后再试。{message}",{message:w})):new Error(w)}const o=a.body.getReader(),c=new TextDecoder;let d="";const f=new Map;let p="";const h=y=>{for(const v of y.split(` -`)){const j=v.trimEnd();if(!j.startsWith("data:"))continue;const w=j.slice(5).trim();if(!w)continue;if(w==="[DONE]")return!0;let S;try{S=JSON.parse(w)}catch{continue}const N=Array.isArray(S.choices)?S.choices[0]:void 0,k=N?.delta||{},A=typeof k.content=="string"?k.content:"";if(A&&e.onEvent({type:"delta",text:A}),Array.isArray(k.tool_calls))for(const P of k.tool_calls){const R=Number(P.index??0),C=f.get(R)||{id:"",name:"",arguments:""};typeof P.id=="string"&&P.id&&(C.id=P.id);const E=P.function||{};typeof E.name=="string"&&E.name&&(C.name=E.name),typeof E.arguments=="string"&&(C.arguments+=E.arguments),f.set(R,C)}typeof N?.finish_reason=="string"&&(p=N.finish_reason)}return!1};for(;;){const{done:y,value:v}=await o.read();if(y)break;d+=c.decode(v,{stream:!0});let j=d.indexOf(` +拿不准的配置先去读(获取模型列表 / 查询账号余额),不要凭印象改。`;function XO(e,t){if(typeof e=="string"&&e.trim())return e.trim();if(e&&typeof e=="object"){const a=e.message;if(typeof a=="string"&&a.trim())return a.trim();try{return JSON.stringify(e)}catch{}}return`HTTP ${t}`}function C7(e,t){const a=e instanceof Error?e.message:String(e);return new Error(r("连接网关失败({base}):{message}",{base:t,message:a}))}async function ow(e,t,a=!1){const o=await KO(),c={...await k7()},d=t.body===void 0?void 0:JSON.stringify(t.body);d!==void 0&&(c["Content-Type"]="application/json");let f;try{f=await fetch(o+e,{method:t.method,headers:c,body:d,signal:t.signal,credentials:S7})}catch(p){throw t.signal?.aborted?p:C7(p,o)}return f.status===401&&!a?(await f.text().catch(()=>""),Dg=null,ow(e,t,!0)):f}async function QO(e,t,a){const o=await ow(t,{method:e,body:a}),c=await o.text();let d=null;try{d=c?JSON.parse(c):null}catch{d=null}const f=d;if(!o.ok||f?.success===!1){const h=f?.error??d?.error,b=XO(h,o.status);throw o.status===404?new Error(r("这一版网关还没有 AI 助手接口(HTTP 404):后端还是旧的,重新编译 / 重启客户端后再试。{message}",{message:b})):new Error(b)}return f&&typeof f=="object"&&"data"in f?f.data:d}async function ZO(){const t=(await QO("GET","/api/assistant/config"))?.config;if(!t||typeof t!="object")throw new Error(r("配置响应不完整"));const a=typeof t.model=="string"?t.model:t.model?.id;return{model:typeof a=="string"&&a.trim()?a:null,systemPromptEnabled:t.systemPromptEnabled!==!1,systemPrompt:typeof t.systemPrompt=="string"?t.systemPrompt:"",tools:t.tools&&typeof t.tools=="object"?t.tools:{}}}async function WO(e){const t=await QO("PUT","/api/assistant/config",{config:e});return t?.config&&typeof t.config=="object"?t.config:e}function T7(e){return e.map(t=>{if(t.role==="tool")return{role:"tool",tool_call_id:t.toolCallId,content:t.content};if(t.role==="assistant"){const a={role:"assistant",content:t.content||""};return t.toolCalls?.length&&(a.tool_calls=t.toolCalls.map(o=>({id:o.id,type:"function",function:{name:o.name,arguments:o.arguments}}))),a}return{role:"user",content:t.content}})}async function E7(e){const t={messages:T7(e.messages)};e.tools.length&&(t.tools=e.tools);const a=await ow("/api/assistant/chat",{method:"POST",body:t,signal:e.signal});if(!a.ok||!a.body){const y=await a.text().catch(()=>"");let v=null;try{v=y?JSON.parse(y):null}catch{}const j=v?.error,w=XO(j,a.status);throw a.status===404?new Error(r("这一版网关还没有 AI 助手接口(HTTP 404):后端还是旧的,重新编译 / 重启客户端后再试。{message}",{message:w})):new Error(w)}const o=a.body.getReader(),c=new TextDecoder;let d="";const f=new Map;let p="";const h=y=>{for(const v of y.split(` +`)){const j=v.trimEnd();if(!j.startsWith("data:"))continue;const w=j.slice(5).trim();if(!w)continue;if(w==="[DONE]")return!0;let k;try{k=JSON.parse(w)}catch{continue}const S=Array.isArray(k.choices)?k.choices[0]:void 0,N=S?.delta||{},R=typeof N.content=="string"?N.content:"";if(R&&e.onEvent({type:"delta",text:R}),Array.isArray(N.tool_calls))for(const P of N.tool_calls){const T=Number(P.index??0),C=f.get(T)||{id:"",name:"",arguments:""};typeof P.id=="string"&&P.id&&(C.id=P.id);const E=P.function||{};typeof E.name=="string"&&E.name&&(C.name=E.name),typeof E.arguments=="string"&&(C.arguments+=E.arguments),f.set(T,C)}typeof S?.finish_reason=="string"&&(p=S.finish_reason)}return!1};for(;;){const{done:y,value:v}=await o.read();if(y)break;d+=c.decode(v,{stream:!0});let j=d.indexOf(` `);for(;j>=0;){const w=d.slice(0,j);if(d=d.slice(j+2),h(w)){await o.cancel().catch(()=>{}),d="",j=-1;break}j=d.indexOf(` -`)}}const b=[...f.entries()].sort((y,v)=>y[0]-v[0]).map(([,y])=>y);b.length&&e.onEvent({type:"toolCalls",calls:b}),e.onEvent({type:"done",finishReason:p})}function iw(e){const t=String(e||"").trim();if(!t)return{};try{const a=JSON.parse(t);return a&&typeof a=="object"&&!Array.isArray(a)?a:{}}catch{return{}}}function el(){const e=window.workbuddyDesktop;if(!e)throw new Error(r("桌面桥不可用(本页需要在 Agent2API 客户端里打开)"));return e}function Mu(){window.wbApp?.refresh?.()}function at(e,t=256){return typeof e=="string"?e.trim().slice(0,t):""}function Qi(e){return typeof e=="boolean"?e:void 0}function Kf(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function Du(e){return Array.isArray(e)?e.filter(t=>!!t&&typeof t=="object"):[]}function Dl(e){return(e instanceof Error?e.message:String(e)).replace(/^Error:\s*/,"")}async function Dg(){const e=await el().getState?.();return(Array.isArray(e?.accounts)?e.accounts:[]).slice().sort((a,o)=>Number(a.priority??0)-Number(o.priority??0))}function Yf(e){return at(e.name)||at(e.nickname)||at(e.id)||r("未命名账号")}function cw(e,t){const a=t.trim();if(!a)throw new Error(r("没给账号名"));const o=e.find(p=>at(p.id)===a);if(o)return o;const c=e.filter(p=>Yf(p)===a);if(c.length===1)return c[0];const d=e.filter(p=>Yf(p).includes(a));if(d.length===1)return d[0];const f=(c.length?c:d).map(Yf).slice(0,6);throw f.length?new Error(r("「{name}」匹配到多个账号:{list},请用完整账号名重试",{name:a,list:f.join("、")})):new Error(r("没有找到账号「{name}」",{name:a}))}const k7={id:"list_models",label:r("获取模型列表"),kind:"read",desc:"读取各提供商的模型清单(模型 ID、所属提供商、是否启用、已挂的映射名)以及全部映射。回答「有哪些模型」「哪些模型在多家重复」「某个名字挂在哪」这类问题之前先调用它。",params:{type:"object",properties:{provider:{type:"string",description:"只看某一家(提供商 id,如 codearts / workbuddy);不填 = 全部"},keyword:{type:"string",description:"按模型 ID 或映射名做子串过滤;不填 = 不过滤"},enabledOnly:{type:"boolean",description:"true = 只看已启用的模型"}}},run:async e=>{const t=at(e.provider,64).toLowerCase(),a=at(e.keyword,128).toLowerCase(),o=Qi(e.enabledOnly)===!0,c=await el().getModelManage?.(),f=(Array.isArray(c?.models)?c.models:[]).filter(p=>!(t&&at(p.provider).toLowerCase()!==t||o&&p.enabled!==!0||a&&![at(p.id),at(p.name),...Array.isArray(p.aliases)?p.aliases.map(b=>at(b)):[]].join(" ").toLowerCase().includes(a))).map(p=>({provider:at(p.provider),id:at(p.id),enabled:p.enabled===!0,aliases:Array.isArray(p.aliases)?p.aliases.map(h=>at(h)):[]}));return{text:JSON.stringify({total:f.length,models:f.slice(0,400)}),summary:r("{n} 个模型",{n:f.length})}}},C7={id:"list_account_balance",label:r("查询账号余额"),kind:"read",desc:"查询各账号的余额 / 剩余额度(会向各上游发起真实的余额查询)。回答「还剩多少」「哪个账号快用完了」这类问题之前先调用它。",params:{type:"object",properties:{account:{type:"string",description:"只查某个账号(账号名或 id);不填 = 全部账号"}}},run:async e=>{const t=at(e.account,128),a=t?at(cw(await Dg(),t).id):"",o=await el().getAllBalances?.(a||void 0),c=Array.isArray(o?.results)?o.results:o,d=Array.isArray(c)?c:[];return{text:JSON.stringify({accounts:d.slice(0,60)}).slice(0,12e3),summary:r("{n} 个账号",{n:d.length})}}},T7={id:"set_model_enabled",label:r("启用 / 禁用模型"),kind:"write",desc:"开启或关闭某几个模型在网关上的可用性(粒度是「提供商 × 模型」)。禁用后下游请求不再路由到它。一次可以改多个。",params:{type:"object",properties:{items:{type:"array",description:"要改的模型列表",items:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},id:{type:"string",description:"模型 ID"},enabled:{type:"boolean",description:"true = 启用,false = 禁用"}},required:["provider","id","enabled"]}}},required:["items"]},plan:e=>{const t=Du(e.items);return{lead:r("将修改 {n} 个模型的启停状态:",{n:t.length}),table:{head:[r("提供商"),r("模型"),r("改成")],rows:t.map(a=>[at(a.provider),at(a.id),Qi(a.enabled)===!1?r("禁用"):r("启用")])},note:r("改动立即生效;禁用后指向它的请求会落到下一个候选。")}},run:async e=>{const t=el(),a=Du(e.items),o=[];for(const c of a){const d=at(c.provider),f=at(c.id),p=Qi(c.enabled);if(!d||!f||p===void 0)throw new Error(r("参数不完整(需要 provider / id / enabled)"));await t.setModelState?.({provider:d,id:f,enabled:p}),o.push(`${p?"启用":"禁用"} ${d}/${f}`)}return Mu(),{text:JSON.stringify({ok:!0,changed:o}),summary:r("已修改 {n} 个模型",{n:o.length})}}},E7={id:"set_model_mapping",label:r("设置模型映射 ID"),kind:"write",desc:"给模型新增或删除映射名(对外名)。同一对外名可以在多个提供商各挂一条:下游用同一个名字请求,网关按账号优先级主备切换;也可以给不同家的同名模型各加前缀(如 ca/claude-sonnet-4.5)来精确指定某一家。一次可以改多条。删掉的映射名只是不再对外可用,不删任何模型。",params:{type:"object",properties:{items:{type:"array",description:"要改的映射列表",items:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},id:{type:"string",description:"上游模型 ID"},alias:{type:"string",description:"要新增 / 删除的映射名(对外名)"},action:{type:"string",enum:["add","remove"],description:"add = 新增映射,remove = 删除映射"}},required:["provider","id","alias","action"]}}},required:["items"]},plan:e=>{const t=Du(e.items),a=t.filter(d=>at(d.action)!=="remove").length,o=t.length-a,c=[];return a&&c.push(r("新增 {n} 条",{n:a})),o&&c.push(r("删除 {n} 条",{n:o})),{lead:r("将改动 {n} 条映射({parts}):",{n:t.length,parts:c.join("、")}),table:{head:[r("提供商"),r("上游模型"),r("操作"),r("映射名")],rows:t.map(d=>[at(d.provider),at(d.id),at(d.action)==="remove"?r("删除"):r("新增"),at(d.alias)])},note:r("只改映射名,不动上游模型 ID;映射立即生效(新对话即可用)。")}},run:async e=>{const t=el(),a=Du(e.items),o=[];for(const c of a){const d=at(c.provider),f=at(c.id),p=at(c.alias,128);if(!d||!f||!p)throw new Error(r("参数不完整(需要 provider / id / alias)"));at(c.action)==="remove"?(await t.removeModelMapping?.(p,f,d),o.push(`删除 ${p} → ${d}/${f}`)):(await t.addModelMapping?.(p,f,d),o.push(`新增 ${p} → ${d}/${f}`))}return Mu(),{text:JSON.stringify({ok:!0,changed:o}),summary:r("已改动 {n} 条映射",{n:o.length})}}},WO=["maxInputTokens","maxOutputTokens","supportsToolCall","supportsImages","supportsVideo","supportsReasoning"],uw={maxInputTokens:r("上下文窗口"),maxOutputTokens:r("最大输出 Token"),supportsToolCall:r("工具调用"),supportsImages:r("图片识别"),supportsVideo:r("视频识别"),supportsReasoning:r("深度推理")},A7={id:"set_model_capability",label:r("修改模型能力"),kind:"write",desc:"修改某个模型对下游声明的能力位:上下文窗口、最大输出 Token、工具调用 / 图片 / 视频 / 深度推理四个布尔位。只传要改的键;布尔位给 null 表示恢复上游原值。",params:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},id:{type:"string",description:"模型 ID"},capabilities:{type:"object",description:"要改的能力位(只写要改的键)",properties:{maxInputTokens:{type:["number","null"],description:"上下文窗口(token 数)"},maxOutputTokens:{type:["number","null"],description:"最大输出 token 数"},supportsToolCall:{type:["boolean","null"],description:"是否支持工具调用;null = 恢复上游原值"},supportsImages:{type:["boolean","null"],description:"是否支持图片识别;null = 恢复上游原值"},supportsVideo:{type:["boolean","null"],description:"是否支持视频识别;null = 恢复上游原值"},supportsReasoning:{type:["boolean","null"],description:"是否支持深度推理;null = 恢复上游原值"}}}},required:["provider","id","capabilities"]},plan:e=>{const t=e.capabilities&&typeof e.capabilities=="object"?e.capabilities:{},a=WO.filter(o=>o in t);return{lead:r("将修改 {model} 的 {n} 项能力:",{model:`${at(e.provider)} / ${at(e.id)}`,n:a.length}),table:{head:[r("能力"),r("改成")],rows:a.map(o=>{const c=t[o],d=c===null?r("恢复上游原值"):typeof c=="boolean"?r(c?"支持":"不支持"):String(c);return[uw[o]||o,d]})},note:r("能力位决定下游看到的声明(能不能贴图、能塞多少上下文),不改上游的真实行为。")}},run:async e=>{const t=at(e.provider),a=at(e.id),o=e.capabilities&&typeof e.capabilities=="object"?e.capabilities:{},c={};for(const d of WO){if(!(d in o))continue;const f=o[d];if(f===null){c[d]=null;continue}if(d==="maxInputTokens"||d==="maxOutputTokens"){const p=Kf(f);if(p===void 0)throw new Error(r("{key} 需要数字",{key:uw[d]}));c[d]=Math.round(p)}else{const p=Qi(f);if(p===void 0)throw new Error(r("{key} 需要 true / false / null",{key:uw[d]}));c[d]=p}}if(!t||!a||!Object.keys(c).length)throw new Error(r("参数不完整(需要 provider / id / capabilities)"));return await el().setModelCapabilities?.(t,a,c),Mu(),{text:JSON.stringify({ok:!0,provider:t,id:a,capabilities:c}),summary:r("已修改 {n} 项能力",{n:Object.keys(c).length})}}},R7={id:"test_model",label:r("发起模型测试"),kind:"run",desc:"对某个模型发一次真实的对话请求,回报连通性、耗时与首字延迟。会消耗该账号的额度。回答「这个模型通不通 / 快不快」时用它。",params:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},id:{type:"string",description:"模型 ID"},prompt:{type:"string",description:"测试用的用户提示词;不填 = 默认一句问候(最小请求)"}},required:["provider","id"]},plan:e=>({lead:r("将对 {model} 发起一次真实请求:",{model:`${at(e.provider)} / ${at(e.id)}`}),table:{head:[r("项"),r("值")],rows:[[r("提示词"),at(e.prompt)||r("(默认问候)")],[r("代价"),r("消耗该账号额度")]]},note:r("这是真实的上游请求,与生产走同一条链路(会记账,报表排除)。")}),run:async e=>{const t={provider:at(e.provider),model:at(e.id)},a=at(e.prompt,4e3);a&&(t.prompt=a);const o=await el().testModel?.(t),c=String(o?.status??""),d=o?.success===!0,f={ok:d,status:c,error:o?.error??null,reply:String(o?.reply??"").slice(0,1500),duration_ms:o?.duration_ms??null,ttfb_ms:o?.ttfb_ms??null,account:o?.account_name??null};return{text:JSON.stringify(f).slice(0,6e3),summary:d?r("连通 · {ms}ms",{ms:String(f.duration_ms??"")}):r("失败 · {status}",{status:c||"—"})}}},O7={id:"set_provider_order",label:r("调整提供商顺位"),kind:"write",desc:"调整某个提供商在账号全局队列里的**整组顺位**(第几组),决定路由时先试哪一家。这一家的所有账号会作为一整块移动。位置从 1 开始数。",params:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},position:{type:"number",description:"目标组顺位(1 = 最前)"}},required:["provider","position"]},plan:e=>({lead:r("将把「{provider}」整组移到第 {position} 顺位:",{provider:at(e.provider)||r("(未指定)"),position:String(Kf(e.position)??"?")}),note:r("队列是一次性整表提交(后端按新顺序重编优先级),移动会连带调整其它组的相对次序。")}),run:async e=>{const t=at(e.provider).toLowerCase(),a=Kf(e.position);if(!t||a===void 0)throw new Error(r("参数不完整(需要 provider / position)"));const o=await Dg(),c=[];for(const h of o){const b=at(h.id),y=at(h.provider).toLowerCase();if(!b)continue;const v=c[c.length-1];v&&v.provider===y?v.ids.push(b):c.push({provider:y,ids:[b]})}const d=c.findIndex(h=>h.provider===t);if(d<0)throw new Error(r("没有找到提供商「{provider}」的账号",{provider:t}));const f=Math.max(0,Math.min(c.length-1,Math.round(a)-1)),[p]=c.splice(d,1);return c.splice(f,0,p),await el().reorderAccounts?.(c.flatMap(h=>h.ids)),Mu(),{text:JSON.stringify({ok:!0,provider:t,from:d+1,to:f+1,moved:p.ids.length}),summary:r("已移到第 {n} 顺位",{n:f+1})}}},M7={id:"set_account_order",label:r("调整账号优先级"),kind:"write",desc:"把某个账号移动到账号全局队列的第 N 顺位(1 = 最前)。位置决定主备与切换顺序:越靠前越先被使用。",params:{type:"object",properties:{account:{type:"string",description:"账号名或账号 id"},position:{type:"number",description:"目标顺位(1 = 最前)"}},required:["account","position"]},plan:e=>({lead:r("将把账号「{account}」移到第 {position} 顺位:",{account:at(e.account)||r("(未指定)"),position:String(Kf(e.position)??"?")}),note:r("队列是一次性整表提交;位置越靠前,路由时越先被选中。")}),run:async e=>{const t=at(e.account,128),a=Kf(e.position);if(!t||a===void 0)throw new Error(r("参数不完整(需要 account / position)"));const o=await Dg(),c=cw(o,t),d=at(c.id),f=o.map(b=>at(b.id)).filter(Boolean),p=f.indexOf(d);if(p<0)throw new Error(r("账号不在当前队列里"));f.splice(p,1);const h=Math.max(0,Math.min(f.length,Math.round(a)-1));return f.splice(h,0,d),await el().reorderAccounts?.(f),Mu(),{text:JSON.stringify({ok:!0,account:Yf(c),from:p+1,to:h+1}),summary:r("已移到第 {n} 顺位",{n:h+1})}}},D7={id:"set_account_enabled",label:r("启用 / 禁用账号"),kind:"write",desc:"开启或关闭某几个账号的转发资格。禁用只是把它移出队列(余额仍可查),但**如果某条线路只剩它**,禁用会直接断供。一次可以改多个。",params:{type:"object",properties:{items:{type:"array",description:"要改的账号列表",items:{type:"object",properties:{account:{type:"string",description:"账号名或账号 id"},enabled:{type:"boolean",description:"true = 启用,false = 禁用"}},required:["account","enabled"]}}},required:["items"]},plan:e=>{const t=Du(e.items),a=t.filter(o=>Qi(o.enabled)===!1).length;return{lead:r("将修改 {n} 个账号的启用状态(其中禁用 {k} 个):",{n:t.length,k:a}),table:{head:[r("账号"),r("改成")],rows:t.map(o=>[at(o.account),Qi(o.enabled)===!1?r("禁用"):r("启用")])},note:r("禁用会把账号移出转发队列;若这条线路没有别的可用账号,请求会直接失败。")}},run:async e=>{const t=el(),a=Du(e.items),o=await Dg(),c=[];for(const d of a){const f=Qi(d.enabled);if(f===void 0)throw new Error(r("参数不完整(需要 account / enabled)"));const p=cw(o,at(d.account,128));await t.updateAccount?.(at(p.id),{enabled:f}),c.push(`${f?"启用":"禁用"} ${Yf(p)}`)}return Mu(),{text:JSON.stringify({ok:!0,changed:c}),summary:r("已修改 {n} 个账号",{n:c.length})}}},tl=[k7,C7,T7,E7,A7,R7,O7,M7,D7];function dw(e){return tl.find(t=>t.id===e)}function I7(e){return tl.filter(t=>e[t.id]).map(t=>({type:"function",function:{name:t.id,description:t.desc,parameters:t.params}}))}const JO=[{id:"list_models",label:r("获取模型列表"),desc:r("读各提供商的模型清单、映射名与启用状态。")},{id:"list_account_balance",label:r("查询账号余额"),desc:r("读各账号的额度 / 剩余用量。")},{id:"set_model_enabled",label:r("启用 / 禁用模型"),desc:r("开关模型的对外可用性,不改其它属性。")},{id:"set_model_mapping",label:r("设置模型映射 ID"),desc:r("新增 / 删除映射名,支持批量加前缀与同名合并到多家。")},{id:"set_model_capability",label:r("修改模型能力"),desc:r("改上下文窗口 / 最大输出 Token / 工具调用等能力位。")},{id:"test_model",label:r("发起模型测试"),desc:r("对指定模型发一次真实请求,回报连通性与耗时。"),tag:"cost"},{id:"set_provider_order",label:r("调整提供商顺位"),desc:r("改某一家的整组顺位(先试哪一家)。")},{id:"set_account_order",label:r("调整账号优先级"),desc:r("改账号在全局队列里的名次,决定主备与切换顺序。")},{id:"set_account_enabled",label:r("启用 / 禁用账号"),desc:r("禁用会把账号移出转发队列,线路可能因此断供。"),tag:"danger"}],eM=12;function Xf(e,t){return window.wbIcons?.icon?.(e,t)||""}function P7(e){const t=window.wbMarkdown;return t?.render?t.render(e):e.replace(/[&<>]/g,a=>({"&":"&","<":"<",">":">"})[a]||a)}function _7({tone:e}){return e==="plain"?s.jsx("span",{className:"asst-tc-ico",dangerouslySetInnerHTML:{__html:Xf("spark",13)}}):s.jsx("span",{className:Ue("asst-tc-ico",e),children:e==="warn"?"!":"✕"})}function L7({item:e,onConfirm:t}){const a=dw(e.call.name),o=a?.label||e.call.name,c=iw(e.call.arguments),d=Object.keys(c).length?JSON.stringify(c,null,2):"";return s.jsxs("div",{className:Ue("asst-tool-card",e.state==="confirm"&&"confirm",e.state==="confirm"&&a?.kind==="run"&&"danger",e.state==="failed"&&"failed",e.state==="running"&&"running"),children:[s.jsxs("div",{className:"asst-tc-head",children:[e.state==="running"?s.jsx("span",{className:"asst-tc-ico",children:s.jsx("span",{className:"spin"})}):s.jsx(_7,{tone:e.state==="failed"?"bad":e.state==="confirm"?"warn":"plain"}),s.jsx("span",{className:"asst-tc-name",children:o}),e.state==="confirm"&&s.jsx("span",{className:"badge tag warn",children:r("待确认")}),e.state==="done"&&s.jsxs("span",{className:"asst-tc-state",children:["✓ ",e.summary||r("完成")]}),e.state==="failed"&&s.jsx("span",{className:"asst-tc-state bad",children:r("失败")}),e.state==="cancelled"&&s.jsx("span",{className:"asst-tc-state plain",children:r("已取消")})]}),e.state==="confirm"&&e.plan&&s.jsxs("div",{className:"asst-tc-plan",children:[e.plan.lead,e.plan.table&&s.jsxs("table",{className:"asst-mini-table",children:[s.jsx("thead",{children:s.jsx("tr",{children:e.plan.table.head.map((f,p)=>s.jsx("th",{children:f},p))})}),s.jsx("tbody",{children:e.plan.table.rows.slice(0,20).map((f,p)=>s.jsx("tr",{children:f.map((h,b)=>s.jsx("td",{className:b===f.length-1?"mono hl":"",children:h},b))},p))})]}),e.plan.table&&e.plan.table.rows.length>20&&s.jsx("div",{className:"hint",children:r("(仅显示前 20 条,共 {n} 条)",{n:e.plan.table.rows.length})}),e.plan.note&&s.jsx("div",{className:"hint",children:e.plan.note})]}),e.state==="failed"&&e.error&&s.jsx("div",{className:"asst-tc-error",children:e.error}),e.state==="done"&&e.detail&&s.jsxs("details",{children:[s.jsx("summary",{className:"asst-tc-result",style:{cursor:"pointer"},children:r("查看结果")}),s.jsx("pre",{className:"asst-tc-json",children:e.detail})]}),e.state!=="confirm"&&d&&s.jsxs("details",{children:[s.jsx("summary",{className:"asst-tc-result",style:{cursor:"pointer"},children:r("查看参数")}),s.jsx("pre",{className:"asst-tc-json",children:d})]}),e.state==="confirm"&&s.jsxs("div",{className:"asst-tc-foot",children:[s.jsx("span",{className:Ue("hint",a?.kind==="run"&&"danger"),children:a?.kind==="run"?r("这会真实发起上游请求并消耗额度"):r("确认后立即生效")}),s.jsx(ne,{size:"sm",variant:a?.kind==="run"?"destructive":"default",onClick:()=>t(!0),children:r("执行")}),s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>t(!1),children:r("取消")})]})]})}function z7(){const[e,t]=x.useState(null),[a,o]=x.useState([]),[c,d]=x.useState([]),[f,p]=x.useState(!1),[h,b]=x.useState(!1),[y,v]=x.useState(""),[j,w]=x.useState(""),[S,N]=x.useState(!1),k=x.useRef([]),A=x.useRef([]),P=x.useRef(null),R=x.useRef(null),C=x.useRef(null),E=x.useRef(!1),D=x.useRef(0),I=x.useRef(null),O=x.useRef(0),_=x.useCallback(()=>{d(k.current.slice())},[]);x.useEffect(()=>{const M=C.current;if(!M)return;M.scrollHeight-M.scrollTop-M.clientHeight<160&&(M.scrollTop=M.scrollHeight)},[c]);const z=x.useCallback(async()=>{if(!E.current){E.current=!0;try{const M=await QO();t(M),N(!1),D.current=0}catch(M){N(!0),w(r("加载助手设置失败:{message}",{message:Dl(M)})),D.current<3&&(D.current+=1,E.current=!1,setTimeout(()=>{z()},4e3))}try{o(await KO())}catch(M){w(U=>U||r("读取模型清单失败:{message}",{message:Dl(M)}))}}},[]);x.useEffect(()=>{const M=window;return M.wbAssistant={activate:()=>{z()}},z(),()=>{delete M.wbAssistant}},[z]);const H=x.useMemo(()=>{const M={};for(const U of tl)M[U.id]=e?.tools?.[U.id]??!1;return M},[e]),B=x.useMemo(()=>I7(H),[H]),L=Object.values(H).filter(Boolean).length,F=e?.model??null,$=x.useCallback(async(M,U,Z)=>{for(let ae=U;ae{if(O.current>=eM){k.current.push({kind:"notice",text:r("这一轮来回已达 {n} 次上限,我先停下等你指示(可以换个说法,或拆成几步让我做)。",{n:eM}),bad:!0}),_();return}O.current+=1,p(!0),w("");const M=new AbortController;R.current=M;const U=k.current.push({kind:"bot",text:"",streaming:!0})-1;_();let Z=[],ae=!1;try{await N7({messages:A.current,tools:B,signal:M.signal,onEvent:ue=>{if(ue.type==="delta"){const ve=k.current[U];ve&&ve.kind==="bot"&&(k.current[U]={...ve,text:ve.text+ue.text},_())}ue.type==="toolCalls"&&(Z=ue.calls)}})}catch(ue){ae=!0;const ve=Dl(ue),ee=k.current[U],he=ee&&ee.kind==="bot"?ee.text:"";he?k.current[U]={kind:"bot",text:he}:k.current.splice(U,1);const te=M.signal.aborted;k.current.push({kind:"notice",text:te?r("已停止这次回答。"):r("请求失败:{message}",{message:ve}),bad:!te}),_()}finally{R.current=null}if(ae){p(!1);return}const ce=k.current[U];ce&&ce.kind==="bot"&&(k.current[U]={...ce,streaming:!1});const W=ce&&ce.kind==="bot"?ce.text:"";if(A.current.push({role:"assistant",content:W,toolCalls:Z.length?Z:void 0}),_(),!Z.length){p(!1);return}await $(Z,0,[])},[B,$,_]);I.current=X;const K=x.useCallback(async M=>{const U=P.current;if(!U)return;P.current=null,b(!1);const Z=U.calls[U.index],ae=dw(Z.name),ce=iw(Z.arguments);if(!M||!ae)k.current[U.cardIndex]={kind:"tool",call:Z,state:"cancelled"},U.collected.push({toolCallId:Z.id,content:"用户取消了这次操作,没有做任何改动。"}),_();else{k.current[U.cardIndex]={kind:"tool",call:Z,state:"running"},p(!0),_();try{const W=await ae.run(ce);k.current[U.cardIndex]={kind:"tool",call:Z,state:"done",summary:W.summary,detail:W.text},U.collected.push({toolCallId:Z.id,content:W.text})}catch(W){const ue=Dl(W);k.current[U.cardIndex]={kind:"tool",call:Z,state:"failed",error:ue},U.collected.push({toolCallId:Z.id,content:`工具执行失败:${ue}`})}_()}await $(U.calls,U.index+1,U.collected)},[$,_]),q=x.useCallback(async M=>{const U=M.trim();if(!(!U||f||h)){if(O.current=0,k.current.push({kind:"user",text:U}),A.current.push({role:"user",content:U}),v(""),_(),!e){k.current.push({kind:"notice",text:r("助手设置没读出来,现在还不能发消息 —— 看输入框下方的提示。"),bad:!0}),_();return}if(!e.model){k.current.push({kind:"notice",text:r("还没有选择对话模型:先在下方选一个(或去「设置 → AI 助手」里选)。"),bad:!0}),_();return}await X()}},[h,f,e,X,_]),Q=x.useCallback(()=>{R.current?.abort()},[]),G=x.useCallback(()=>{R.current?.abort(),P.current=null,k.current=[],A.current=[],b(!1),p(!1),w(""),_()},[_]),J=x.useCallback(async M=>{if(!M)return;if(!e){w(r("助手设置没读出来,暂时存不了对话模型 —— 看输入框下方的提示。"));return}const U={...e,model:M};t(U);try{await ZO(U)}catch(Z){w(r("保存对话模型失败:{message}",{message:Dl(Z)}))}},[e]),Y=f||h,re=x.useRef(null);return s.jsxs("div",{className:"asst-layout",children:[s.jsxs("div",{className:"asst-top",children:[s.jsxs(ut,{value:F??"",onValueChange:M=>{J(String(M))},children:[s.jsx(ft,{className:"asst-model-pick","aria-label":r("对话模型"),children:s.jsx(dt,{children:F?s.jsxs("span",{className:"flex items-center gap-2",children:[s.jsx("span",{className:Ue("dot","ok")}),s.jsx("span",{className:"mono",children:F})]}):r("选择模型…")})}),s.jsxs(pt,{children:[a.length===0&&s.jsx($e,{value:"none",disabled:!0,children:r("没有可用的模型")}),a.map(M=>s.jsx($e,{value:M,children:M},M))]})]}),s.jsx("span",{className:"asst-top-hint",children:r("助手走本地网关,消耗所选账号的额度")}),s.jsx("span",{className:"spacer"}),s.jsx(ne,{variant:"ghost",size:"sm",onClick:G,disabled:f||h||!c.length,children:r("新对话")})]}),s.jsxs("div",{className:"asst-scroll",ref:C,children:[c.length===0&&s.jsxs("div",{className:"asst-empty",children:[s.jsx("div",{className:"empty-logo",dangerouslySetInnerHTML:{__html:Xf("spark",26)||""}}),s.jsx("h3",{children:r("AI 助手")}),s.jsxs("p",{children:[r("用一句话让我查或改本机的模型转发配置。"),s.jsx("br",{}),r("我会在动手前把改动列给你确认。")]}),s.jsx("div",{className:"asst-suggests",children:[r("看看哪些模型在多家重复了"),r("测一下当前最快的模型通不通"),r("CodeArts 的账号余额还剩多少?"),r("把重复的模型加上家名前缀区分开")].map(M=>s.jsxs("button",{type:"button",onClick:()=>{q(M)},children:["“",M,"”"]},M))}),e!==null&&L===0&&s.jsx("div",{className:"asst-empty-warn",children:r("当前一个工具都没勾选,助手只能纯聊天。去「设置 → AI 助手 → 工具」里勾上需要的工具。")}),S&&s.jsx("div",{className:"asst-empty-warn bad",children:j||r("助手设置读取失败,工具可能已过时。")})]}),c.map((M,U)=>M.kind==="user"?s.jsx("div",{className:"asst-msg user",children:s.jsx("div",{className:"bubble",children:M.text})},U):M.kind==="bot"?!M.text&&M.streaming?s.jsxs("div",{className:"asst-msg bot",children:[s.jsxs("div",{className:"who",children:[s.jsx("span",{className:"ico",dangerouslySetInnerHTML:{__html:Xf("spark",14)||""}})," ",r("助手")]}),s.jsx("div",{className:"body",children:s.jsx("span",{className:"spin"})})]},U):s.jsxs("div",{className:"asst-msg bot",children:[s.jsxs("div",{className:"who",children:[s.jsx("span",{className:"ico",dangerouslySetInnerHTML:{__html:Xf("spark",14)||""}})," ",r("助手")]}),s.jsxs("div",{className:"body",children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:P7(M.text)}}),M.streaming&&s.jsx("span",{className:"asst-caret"})]})]},U):M.kind==="notice"?s.jsx("div",{className:"asst-msg bot",children:s.jsx("div",{className:Ue("asst-empty-warn",M.bad&&"bad"),style:{margin:0},children:M.text})},U):s.jsx(L7,{item:M,onConfirm:Z=>{K(Z)}},U))]}),s.jsxs("div",{className:"asst-composer",children:[s.jsxs("div",{className:"asst-ta-wrap",children:[s.jsx(Mi,{ref:re,rows:1,value:y,placeholder:r(Y?"等这一轮跑完…":"直接说要改什么 / 查什么…(Enter 发送,Shift+Enter 换行)"),disabled:Y,onChange:M=>{v(M.currentTarget.value);const U=M.currentTarget;U.style.height="auto",U.style.height=`${Math.min(U.scrollHeight,132)}px`},onKeyDown:M=>{M.key==="Enter"&&!M.shiftKey&&!M.nativeEvent.isComposing&&(M.preventDefault(),q(y))}}),f?s.jsx("button",{type:"button",className:"asst-send stop",title:r("停止"),onClick:Q,children:"■"}):s.jsx("button",{type:"button",className:"asst-send",title:r("发送"),disabled:Y||!y.trim(),onClick:()=>{q(y)},children:"➤"})]}),s.jsxs("div",{className:"asst-composer-foot",children:[s.jsxs("span",{className:"tools-state",children:[s.jsx("span",{className:"ico",dangerouslySetInnerHTML:{__html:Xf("settings",12)||""}}),r("已注入 {n} / {total} 个工具 · 系统提示词:{state}",{n:L,total:tl.length,state:e?.systemPromptEnabled?r("开"):r("关")})]}),s.jsx("span",{className:"spacer"}),j?s.jsxs("span",{className:"hint",children:[j,S&&s.jsx("button",{type:"button",className:"asst-tc-more",onClick:()=>{z()},children:r("重试")})]}):F?s.jsx("span",{className:"hint",children:r("回复由 {model} 生成 · 走本地网关",{model:F})}):null]})]})]})}const tM='.page[data-page="assistant"]';let fw=null;function nM(){if(fw)return;const e=document.querySelector(tM);e&&(e.replaceChildren(),fw=jn.createRoot(e),fw.render(s.jsx(z7,{})))}document.querySelector(tM)?nM():document.addEventListener("DOMContentLoaded",nM,{once:!0}),GO().catch(()=>{});function B7(e,t){return window.wbIcons?.icon?.(e,t)||""}function H7({id:e,label:t,checked:a,disabled:o,onCheckedChange:c}){return s.jsxs("label",{className:"switch",children:[s.jsx(ns,{id:e,checked:a,disabled:o,onCheckedChange:d=>c(d)}),s.jsx("span",{children:t})]})}function U7(){const[e,t]=x.useState(null),[a,o]=x.useState([]),[c,d]=x.useState(""),[f,p]=x.useState(!1),[h,b]=x.useState(!1),[y,v]=x.useState(!1),[j,w]=x.useState("");x.useEffect(()=>{let C=!0;return(async()=>{try{const E=await QO();if(!C)return;t(E)}catch(E){if(!C)return;p(!0),d(r("加载助手设置失败:{message}",{message:Dl(E)}))}try{const E=await KO();if(!C)return;o(E)}catch(E){if(!C)return;d(D=>D||r("读取模型清单失败:{message}",{message:Dl(E)}))}})(),()=>{C=!1}},[]);const S=x.useCallback(async(C,E)=>{t(C),b(!0);try{const D=await ZO(C);t(D),p(!1),d(E||r("已保存"))}catch(D){p(!0),d(r("保存失败:{message}",{message:Dl(D)}))}finally{b(!1)}},[]),N=e!==null,k=x.useMemo(()=>{const C={};for(const E of tl)C[E.id]=e?.tools?.[E.id]??!1;return C},[e]),A=Object.values(k).filter(Boolean).length,P=!!e?.systemPrompt?.trim(),R=(C,E)=>{if(!e)return;const D=JO.find(O=>O.id===C)?.label||C,I={...e,tools:{...e.tools,[C]:E}};S(I,E?r("已勾选「{label}」",{label:D}):r("已取消「{label}」",{label:D}))};return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("对话模型")}),s.jsx("span",{className:"panel-sub",children:r("助手自己用哪个模型生成回复")})]}),s.jsx("div",{className:"panel-body",children:s.jsxs("div",{className:"asst-row",children:[s.jsx("label",{children:r("模型")}),s.jsxs(ut,{value:e?.model??"",disabled:!N||h,onValueChange:C=>{if(!e)return;const E=String(C);E&&S({...e,model:E},r("对话模型已切换"))},children:[s.jsx(ft,{className:"asst-model-pick","aria-label":r("对话模型"),children:s.jsx(dt,{children:e?.model??r("选择模型…")})}),s.jsxs(pt,{children:[a.length===0&&s.jsx($e,{value:"none",disabled:!0,children:r("没有可用的模型")}),a.map(C=>s.jsx($e,{value:C,children:C},C))]})]}),s.jsx("span",{className:"hint",children:r("列表 = 模型管理页里所有已启用的模型。助手走本地网关发起对话,消耗所选账号的额度。")})]})})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("系统提示词")}),s.jsx("span",{className:"panel-sub",children:r("作为 system 消息注入给助手")})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"asst-row",children:[s.jsx(H7,{id:"settings-assistant-prompt",label:r("注入系统提示词"),checked:e?.systemPromptEnabled!==!1,disabled:!N||h,onCheckedChange:C=>{e&&S({...e,systemPromptEnabled:C},r(C?"系统提示词已开启":"系统提示词已关闭"))}}),s.jsxs(ne,{variant:"outline",size:"sm",disabled:!N,onClick:()=>{w(e?.systemPrompt?.trim()?e.systemPrompt:lw),v(!0)},children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:B7("settings",13)||""}}),r("编辑")]}),s.jsx("span",{className:"hint",children:r("点「编辑」弹窗改内容;开关关掉就整段不发。")})]}),s.jsx("div",{className:"settings-state",children:e?.systemPromptEnabled===!1?r("当前:已关闭(助手不收到任何系统提示词,工具定义照发)"):P?r("当前:已开启 · 自定义内容 {n} 字",{n:e?.systemPrompt.trim().length??0}):r("当前:已开启 · 使用内置默认提示词(还没自定义)")}),s.jsxs("div",{className:"asst-matrix",children:[s.jsx("div",{className:"mt-title",children:r("四种组合的实际效果")}),s.jsxs("table",{className:"asst-mini-table",children:[s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{children:r("提示词开关")}),s.jsx("th",{children:r("已勾选工具")}),s.jsx("th",{children:r("实际注入")})]})}),s.jsxs("tbody",{children:[s.jsxs("tr",{children:[s.jsx("td",{children:r("开")}),s.jsx("td",{children:r("有")}),s.jsx("td",{children:r("系统提示词 + 工具定义")})]}),s.jsxs("tr",{children:[s.jsx("td",{children:r("开")}),s.jsx("td",{children:s.jsx("b",{children:r("无")})}),s.jsx("td",{children:s.jsx("b",{children:r("都不注入(助手退化为纯聊天)")})})]}),s.jsxs("tr",{children:[s.jsx("td",{children:r("关")}),s.jsx("td",{children:r("有")}),s.jsx("td",{children:r("只注入工具定义")})]}),s.jsxs("tr",{children:[s.jsx("td",{children:r("关")}),s.jsx("td",{children:r("无")}),s.jsx("td",{children:r("都不注入")})]})]})]}),s.jsx("p",{className:"hint",children:r("「工具全不勾选 → 不注入系统提示词」:想当纯聊天用时,不必再去关上面的开关。")})]})]})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("工具")}),s.jsx("span",{className:"panel-sub",children:r("勾选即注入该工具;不勾选 = 助手看不到它")})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"asst-tools-bar",children:[s.jsx("span",{className:"badge brand",children:r("已勾选 {n} / {total}",{n:A,total:tl.length})}),s.jsx("span",{className:"spacer"}),s.jsx(ne,{variant:"ghost",size:"sm",disabled:!N||h,onClick:()=>{if(!e)return;const C={};for(const E of tl)C[E.id]=!1;S({...e,tools:C},r("已全部取消勾选"))},children:r("全不选")}),s.jsx(ne,{variant:"ghost",size:"sm",disabled:!N||h,onClick:()=>{if(!e)return;const C={};for(const E of tl)C[E.id]=E.kind==="read";for(const E of["set_model_enabled","set_model_mapping","set_model_capability","test_model"])C[E]=!0;S({...e,tools:C},r("已恢复推荐勾选"))},children:r("恢复推荐")})]}),["read","write"].map(C=>s.jsxs(x.Fragment,{children:[s.jsx("div",{className:"asst-tool-group",children:C==="read"?s.jsxs(s.Fragment,{children:[r("只读工具")," ",s.jsx("span",{className:"muted",children:r("· 不会改动任何配置")})]}):s.jsxs(s.Fragment,{children:[r("改动类工具")," ",s.jsx("span",{className:"muted",children:r("· 每次执行前列改动清单,等你确认")})]})}),JO.filter(E=>{const I=tl.find(O=>O.id===E.id)?.kind==="read";return C==="read"?I:!I}).map(E=>{const D=tl.find(O=>O.id===E.id),I=k[E.id]===!0;return s.jsxs("label",{className:"asst-tool",children:[s.jsx("input",{type:"checkbox",checked:I,disabled:!N||h,onChange:O=>R(E.id,O.currentTarget.checked)}),s.jsxs("span",{className:"tt",children:[s.jsxs("span",{className:"tt-name",children:[E.label,D?.kind==="read"&&s.jsx("span",{className:"badge tag plain",children:r("只读")}),E.tag==="cost"&&s.jsx("span",{className:"badge tag",children:r("消耗额度")}),E.tag==="danger"&&s.jsx("span",{className:"badge tag bad",children:r("高危")}),D?.kind==="write"&&!E.tag&&s.jsx("span",{className:"badge tag warn",children:r("影响转发")})]}),s.jsx("span",{className:"tt-desc",children:E.desc})]})]},E.id)})]},C)),s.jsx("div",{className:Ue("settings-state",f&&"text-destructive"),children:c})]})]}),s.jsx(Yt,{open:y,onOpenChange:C=>{C||v(!1)},children:s.jsxs(Xt,{className:"w-[min(680px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("编辑系统提示词")})}),s.jsxs(Lt,{children:[s.jsx(dn,{children:s.jsx("p",{children:r("这段文本作为 system 消息排在对话最前面。工具的定义与当前配置概览由网关自动附加,不用写在这里。")})}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"assistant-system-prompt",children:r("提示词正文")}),s.jsx(Mi,{id:"assistant-system-prompt",rows:14,className:"asst-prompt-ta min-h-[300px]",spellCheck:!1,value:j,onChange:C=>w(C.currentTarget.value)}),s.jsx("div",{className:"hint",children:r("清空 = 回到内置默认(与「恢复默认」等价)。")})]})]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",className:"mr-auto",onClick:()=>w(lw),children:r("恢复默认")}),s.jsx(ne,{variant:"outline",onClick:()=>v(!1),children:r("取消")}),s.jsx(ne,{variant:"default",onClick:()=>{if(!e)return;const C=j.trim()===lw.trim()?"":j;S({...e,systemPrompt:C},r("系统提示词已保存")),v(!1)},children:r("保存")})]})]})})]})}function Lr(){return Pe().workbuddyDesktop??{}}function sM(){return window}const rM="workbuddy-desktop-checkin-tab",V7=["center","schedule","records"];function F7(){try{const e=localStorage.getItem(rM);return V7.includes(e)?e:"center"}catch{return"center"}}function aM(e){if(e!==bs.tab){try{localStorage.setItem(rM,e)}catch{}sr({tab:e})}}async function Ig(e){aM(e),bs.loaded||await Il()}let bs={version:0,tab:F7(),snapshot:null,loaded:!1,loadError:"",expanded:new Set,runningAll:!1,autoSaving:!1,autoTimeDraft:null,keepaliveSaving:!1,keepaliveDraft:null,signing:new Set,onboarding:new Map,growth:new Map};const pw=new Set;function $7(){for(const e of pw)e()}function sr(e){bs={...bs,...e,version:bs.version+1},$7()}function fr(){return bs}function lM(e){return pw.add(e),()=>pw.delete(e)}function q7(e){const t=typeof e?.key=="string"?e.key:"";return t?{key:t,title:typeof e.title=="string"&&e.title?e.title:t,group:typeof e.group=="string"&&e.group?e.group:"",points:Number(e.points)||0,done:e.done===!0,blocked:e.blocked===!0}:null}function mw(e){return(Array.isArray(e)?e:[]).map(q7).filter(a=>a!==null)}function ps(e){return Number(e)||0}async function Il(){try{const e=await Lr().getCheckinCenter?.();if(!e)throw new Error(r("后端未返回签到中心数据"));sr({snapshot:e,loaded:!0,loadError:"",autoTimeDraft:null,keepaliveDraft:null}),G7(e.extras?.onboarding??[])}catch(e){sr({loaded:!0,loadError:mt(e)})}}function G7(e){for(const t of e){const a=t.settled;if(!a||typeof a!="object")continue;const o=bs.onboarding.get(t.id);if(o?.status==="loaded"&&o.unclaimed>0)continue;const c=mw(a.tasks),d=ps(a.at);Do(t.id,{status:"loaded",error:void 0,checkedAt:void 0,settled:!0,settledAt:d>0?d:void 0,tasks:c,unclaimed:0,earned:ps(a.earned),total:ps(a.total)})}}function oM(e){const t=new Set(bs.expanded);t.has(e)?t.delete(e):t.add(e),sr({expanded:t})}function hw(e){const t=`onb:${e}`,a=new Set(bs.expanded);a.has(t)?a.delete(t):a.add(t),sr({expanded:a})}function iM(e){return bs.expanded.has(`onb:${e}`)}async function K7(){if(!bs.runningAll){sr({runningAll:!0});try{const e=await Lr().runAutoCheckinNow?.();if(e){const t=ps(e.succeeded),a=ps(e.active),o=ps(e.total),c=ps(e.failedCount),d=a>0?r(",日活保活 {n} 个",{n:a}):"";c>0?Le(r("签到完成:{succeeded}/{total} 成功{active},{failed} 个失败",{succeeded:t,total:o,active:d,failed:c}),"err"):Le(r("✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}",{succeeded:t,total:o,active:d})),sM().wbAccountsView?.refreshUsageAfterCheckin?.(null)}}catch(e){Le(r("签到失败:{error}",{error:mt(e)}),"err")}finally{sr({runningAll:!1}),await Il(),cM(fr().snapshot?.extras.onboarding??[]),Pe().wbApp?.refresh?.()}}}async function Pg(e,t="checkin"){const a=`${e}:${t}`;if(bs.signing.has(a))return;const o=new Set(bs.signing);o.add(a),sr({signing:o});try{let c;t==="checkin"?c=(await Lr().checkinAllAccounts?.(e))?.results?.[0]:c=await Lr().runCheckinActivity?.(e,t)??void 0;const d=c?.claim,f=c?.activity,p=f?.report?.succeeded===!0,h=f?.webConversation?.succeeded===!0;c?.error?Le(r("签到失败:{error}",{error:String(c.error)}),"err"):t==="keepalive"?f?.pokeSucceeded===!0||h||p?Le(r("✅ {message}",{message:d?.msg||r("活跃保活完成")})):Le(d?.msg||r("活跃保活失败"),"err"):d?.success===!0?Le(r("✅ {message}",{message:d.msg||r("签到成功")})):d?.alreadyCompleted===!0?Le(d?.msg||r("今日已领取"),"err"):p?Le(r("✅ {message}",{message:d?.msg||r("活跃上报完成,但活动未开启")})):f?.pokeSucceeded===!0||h?Le(r("✅ {message}",{message:d?.msg||r("活跃保活完成,但活动未开启")})):Le(d?.msg||r("未领取"),"err"),sM().wbAccountsView?.refreshUsageAfterCheckin?.(e)}catch(c){Le(r("签到失败:{error}",{error:mt(c)}),"err")}finally{const c=new Set(fr().signing);c.delete(a),sr({signing:c}),await Il();const d=(fr().snapshot?.extras.onboarding??[]).filter(f=>f.id===e);cM(d),Pe().wbApp?.refresh?.()}}function _g(e){sr({keepaliveDraft:e.map(t=>t.trim()).filter(Boolean)})}async function Y7(e){const t=e.map(a=>a.trim()).filter(Boolean);if(!fr().keepaliveSaving){sr({keepaliveSaving:!0});try{const a=await Lr().saveCheckinKeepalive?.(t);if(a){const o=fr().snapshot;sr({snapshot:o&&{...o,keepalive:a},keepaliveDraft:null}),Le(r("已保存:保活模型链"))}}catch(a){Le(r("保存失败:{error}",{error:mt(a)}),"err")}finally{sr({keepaliveSaving:!1})}}}async function cM(e){for(const t of e)X7(t.id)||await gw(t.id);for(const t of e){const a=fr().onboarding.get(t.id);a?.status!=="loaded"||a.claiming||a.settled||(t.provider==="officeace"||a.unclaimed>0)&&await uM(t.id)}}function X7(e){return bs.onboarding.get(e)?.settled===!0}function Iu(e){return bs.onboarding.get(e)??{status:"idle",tasks:[],unclaimed:0,earned:0,total:0,claiming:!1}}function Do(e,t){const a=new Map(bs.onboarding);a.set(e,{...Iu(e),...t}),sr({onboarding:a})}async function gw(e,t){const a=Iu(e);if(!(a.status==="loading"||a.claiming)){Do(e,{status:"loading",error:void 0,settled:!1});try{const o=await Lr().getOnboardingTasks?.(e,t?.refresh===!0),c=mw(o?.tasks),d=o?.settled===!0;Do(e,{status:"loaded",checkedAt:Date.now(),tasks:c,unclaimed:c.filter(f=>!f.done&&!f.blocked).length,earned:ps(o?.earned),total:ps(o?.total),settled:d,settledAt:d&&ps(o?.settledAt)||void 0}),t?.expand===!0&&c.length>0&&!iM(e)&&hw(e)}catch(o){Do(e,{status:"error",error:mt(o),settled:!1})}}}async function uM(e){const t=Iu(e);if(!(t.claiming||t.status!=="loaded")){Do(e,{claiming:!0});try{Do(e,{tasks:Iu(e).tasks.map(v=>v.done?v:{...v,claiming:!0,error:void 0})});const a=await Lr().claimOnboardingTasks?.(e),o=new Map,c=Array.isArray(a?.results)?a.results:[];for(const v of c){const j=typeof v?.key=="string"?v.key:"";j&&v?.ok!==!0&&o.set(j,String(v?.error||r("领取失败")))}const d=mw(a?.tasks),f=(d.length?d:Iu(e).tasks).map(v=>({...v,claiming:!1,error:o.get(v.key)})),p=f.filter(v=>v.done&&!o.has(v.key)).length,h=a?.settled===!0;Do(e,{claiming:!1,checkedAt:Date.now(),tasks:f,unclaimed:f.filter(v=>!v.done&&!v.blocked).length,earned:ps(a?.earned),total:ps(a?.total),settled:h,settledAt:h&&ps(a?.settledAt)||void 0});const b=f.filter(v=>v.error&&!v.done).length,y=typeof a?.message=="string"?a.message.trim():"";b?Le(r("新手福利有 {n} 项领取失败,可重试",{n:b}),"err"):y?Le(y,"ok"):p&&Le(r("✅ 新手福利领取完成,累计 {n} 积分",{n:ps(a?.earned)}))}catch(a){const o=mt(a);Do(e,{claiming:!1,tasks:Iu(e).tasks.map(c=>({...c,claiming:!1,error:c.done?void 0:o}))}),Le(r("领取失败:{error}",{error:o}),"err")}finally{await Il()}}}function dM(e){return(Array.isArray(e)?e:[]).map(a=>{const o=a??{},c=typeof o.code=="string"?o.code:"";return c?{code:c,title:typeof o.title=="string"&&o.title?o.title:c,description:typeof o.description=="string"?o.description:"",status:typeof o.status=="string"?o.status:"",current:ps(o.current),target:ps(o.target),locked:o.locked===!0,unlockAt:o.unlockAt,supported:o.supported===!0,unforgeable:o.unforgeable===!0,unforgeableReason:typeof o.unforgeableReason=="string"?o.unforgeableReason:"",kind:typeof o.kind=="string"?o.kind:"",source:typeof o.source=="string"?o.source:""}:null}).filter(a=>a!==null)}function fM(e){return(Array.isArray(e)?e:[]).map(a=>{const o=a??{},c=typeof o.code=="string"?o.code:"";return c?{code:c,outcome:typeof o.outcome=="string"?o.outcome:"failed",message:typeof o.message=="string"?o.message:"",credit:ps(o.credit),energy:ps(o.energy)}:null}).filter(a=>a!==null)}function Zi(e){return bs.growth.get(e)??{status:"idle",energy:null,streak:null,tasks:[],travel:null,school:null,running:!1,runningSchool:!1,runningTravel:!1}}function zr(e,t){const a=new Map(bs.growth);a.set(e,{...Zi(e),...t}),sr({growth:a})}function Q7(e){return bs.expanded.has(`growth:${e}`)}function pM(e){const t=`growth:${e}`,a=new Set(bs.expanded);a.has(t)?a.delete(t):a.add(t),sr({expanded:a})}async function Lg(e){const t=Zi(e);if(!(t.status==="loading"||t.running)){zr(e,{status:"loading",error:void 0});try{const a=await Lr().getGrowthStatus?.(e),o=a?.tasks??{},c=a?.travel??null,d=a?.school??null;zr(e,{status:"loaded",checkedAt:Date.now(),energy:a?.energy===null||a?.energy===void 0?null:ps(a.energy),streak:a?.streak===null||a?.streak===void 0?null:ps(a.streak),tasks:dM(o.tasks),travel:c,school:d?{...d,tasks:dM(d.tasks)}:null,error:typeof o.error=="string"?o.error:void 0})}catch(a){zr(e,{status:"error",error:mt(a)})}}}async function mM(e,t){const a=Zi(e);if(a.running)return;const o=(a.tasks??[]).filter(h=>!h.supported||h.unforgeable===!0||h.locked===!0?!1:t==="claim"?h.status==="completed"||h.current>=h.target&&h.status!=="claimed":h.status!=="claimed");if(o.length===0){Le(r("没有需要执行的任务"));return}zr(e,{running:!0,results:[],error:void 0});let c=0,d=0,f=0,p=0;for(const h of o)try{const b=await Lr().runGrowthTask?.(e,h.code,t),y=fM([b])[0];y&&(zr(e,{results:[...Zi(e).results??[],y]}),c+=y.credit??0,d+=y.energy??0,(y.outcome==="done"||y.outcome==="already")&&(f+=1),y.outcome==="failed"&&(p+=1))}catch(b){p+=1,zr(e,{results:[...Zi(e).results??[],{code:h.code,outcome:"failed",message:mt(b),credit:0,energy:0}]})}zr(e,{running:!1}),p>0?Le(r("成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}",{done:f,failed:p,credit:c,energy:d}),"err"):Le(r("✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}",{credit:c,energy:d})),await Lg(e)}async function Z7(e,t){if(!Zi(e).runningSchool){zr(e,{runningSchool:!0,error:void 0});try{const o=await Lr().runGrowthSchool?.(e,t),c=fM(o?.results),d=o?.lottery??null;zr(e,{runningSchool:!1,results:c,schoolText:c.length?c.map(f=>`${f.code}:${f.message}`).join(";"):void 0,lotteryText:d?String(d.message??r("已抽 {n} 次",{n:ps(d.drawn)})):void 0,checkedAt:Date.now()}),Le(d?r("开学季执行完成:{message}",{message:String(d.message??"")}):r("✅ 开学季任务执行完成")),await Lg(e)}catch(o){zr(e,{runningSchool:!1,error:mt(o)}),Le(r("开学季执行失败:{error}",{error:mt(o)}),"err")}}}async function W7(e){if(!Zi(e).runningTravel){zr(e,{runningTravel:!0,error:void 0});try{const a=await Lr().runGrowthTravel?.(e),o=String(a?.message??""),c=String(a?.outcome??"");zr(e,{runningTravel:!1,checkedAt:Date.now()}),c==="failed"?Le(r("猫猫旅行失败:{message}",{message:o}),"err"):Le(r("猫猫旅行:{message}",{message:o})),await Lg(e)}catch(a){zr(e,{runningTravel:!1,error:mt(a)}),Le(r("猫猫旅行失败:{error}",{error:mt(a)}),"err")}}}function J7(e){return e.totalCount?e.doneCount>=e.totalCount?"done":e.doneCount>0?"part":"todo":"none"}function e9(e){const a=(Array.isArray(e?.schedules)?e.schedules:[]).filter(o=>o.enabled===!0).map(o=>Number(o.nextRunAt)).filter(o=>Number.isFinite(o)&&o>0);return a.length?Math.min(...a):null}let Io={version:0,data:null,loaded:!1,loadError:"",saving:!1,runningId:null,editingId:null};const xw=new Set;function t9(){for(const e of xw)e()}function Br(e){Io={...Io,...e,version:Io.version+1},t9()}function hM(){return Io}function n9(e){return xw.add(e),()=>xw.delete(e)}function Pu(){return Pe().workbuddyDesktop??{}}async function gM(){try{const e=await Pu().getCheckinSchedules?.();if(!e)throw new Error(r("后端未返回定时签到数据"));Br({data:e,loaded:!0,loadError:""})}catch(e){Br({loaded:!0,loadError:mt(e)})}}function zg(e){e&&Br({data:e,loadError:""}),Il()}async function s9(e){if(!Io.saving){Br({saving:!0});try{const t=await Pu().saveAutoCheckin?.({enabled:e});zg(t),Le(r(e?"✅ 定时签到已开启":"定时签到已关闭"))}catch(t){Le(r("保存失败:{error}",{error:mt(t)}),"err")}finally{Br({saving:!1})}}}async function xM(e){if(!Io.saving){Br({saving:!0});try{const t=await Pu().saveCheckinSchedule?.(e);zg(t),Br({editingId:null}),Le(r("已保存:定时条目"))}catch(t){Le(r("保存失败:{error}",{error:mt(t)}),"err")}finally{Br({saving:!1})}}}async function r9(e,t){await xM({id:e.id,label:e.label??"",enabled:t,time:e.time??"",providers:Array.isArray(e.providers)?e.providers:[]})}async function a9(e){if(!Io.saving){Br({saving:!0});try{await Pu().deleteCheckinSchedule?.(e),zg(await Pu().getCheckinSchedules?.()),Le(r("已删除定时条目"))}catch(t){Le(r("删除失败:{error}",{error:mt(t)}),"err")}finally{Br({saving:!1})}}}async function l9(e){if(!Io.runningId){Br({runningId:e});try{const t=await Pu().runCheckinSchedule?.(e)??void 0,a=o=>Number(o)||0;if(t){const o=a(t.succeeded),c=a(t.active),d=a(t.total),f=a(t.failedCount),p=c>0?r(",日活保活 {n} 个",{n:c}):"";f>0?Le(r("签到完成:{succeeded}/{total} 成功{active},{failed} 个失败",{succeeded:o,total:d,active:p,failed:f}),"err"):Le(r("✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}",{succeeded:o,total:d,active:p})),zg(t)}}catch(t){Le(r("执行失败:{error}",{error:mt(t)}),"err")}finally{Br({runningId:null}),await Il()}}}function bw(e){Br({editingId:e})}const o9=r("到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。错过时点开机后会自动补签,不会因为当时没开机而漏掉。各家签到接口都是幂等的,重复执行不会重复领取。");function i9(){const[e,t]=x.useState(hM());return x.useEffect(()=>n9(()=>t(hM())),[]),e}function c9(){const[e,t]=x.useState(fr());return x.useEffect(()=>lM(()=>t(fr())),[]),e}function bM(e,t){const a=Array.isArray(e.providers)?e.providers:[];return t.filter(o=>a.includes(o.id)).map(o=>o.label)}function u9(e,t){const a=bM(e,t);return a.length?t.length>0&&a.length>=t.length?r("全部 {n} 家",{n:t.length}):a.join(r("、")):r("未勾选提供商")}function d9(e,t){const a=bM(e,t);return a.length?a.join(r("、")):r("未勾选提供商")}function f9(e){const t=e.lastResult;if(!t)return r("还没执行过");const a=f=>Number(f)||0,o=[r("成功 {n}",{n:a(t.succeeded)})],c=a(t.active);c>0&&o.push(r("保活 {n}",{n:c}));const d=a(t.failedCount);return d>0&&o.push(r("失败 {n}",{n:d})),`${t.at?Ls(t.at):"—"}${t.reason?` · ${t.reason}`:""} —— ${o.join(r(" · "))}`}function vM({entry:e,store:t}){const a=Array.isArray(t.data?.providerOptions)?t.data.providerOptions:[],o=e===null,[c,d]=x.useState(e?.label??""),[f,p]=x.useState(e?.time??"00:01"),[h,b]=x.useState(new Set(o?a.map(S=>S.id):e?.providers??[]));x.useEffect(()=>{o&&a.length>0&&b(new Set(a.map(S=>S.id)))},[]);const y=f.trim()!==""&&h.size>0,v=()=>b(new Set(a.map(S=>S.id))),j=()=>b(new Set),w=async()=>{await xM({id:e?.id,label:c.trim(),enabled:e?.enabled??!0,time:f.trim(),providers:a.map(S=>S.id).filter(S=>h.has(S))})};return s.jsxs("div",{className:"ck-sched-editor",children:[s.jsxs("div",{className:"ck-set-line",children:[s.jsx("span",{className:"ck-set-k",children:r("名称")}),s.jsx("span",{className:"ck-set-v",children:s.jsx(Fe,{type:"text",className:"max-w-[220px]",placeholder:r("可选 · 缺省显示时刻"),value:c,disabled:t.saving,onChange:S=>d(S.currentTarget.value)})})]}),s.jsxs("div",{className:"ck-set-line",children:[s.jsx("span",{className:"ck-set-k",children:r("每天时刻")}),s.jsxs("span",{className:"ck-set-v flex items-center gap-2",children:[s.jsx(Fe,{type:"time",className:"w-[96px] max-w-[96px] font-mono tabular-nums",value:f,disabled:t.saving,onChange:S=>p(S.currentTarget.value)}),s.jsx("span",{className:"text-subtle text-xs",children:r("北京时间 · 错过时点开机后会自动补签")})]})]}),s.jsxs("div",{className:"ck-set-line ck-set-line-top",children:[s.jsx("span",{className:"ck-set-k",children:r("签到范围")}),s.jsxs("span",{className:"ck-set-v",children:[s.jsxs("div",{className:"ck-mini-row",children:[s.jsx("span",{className:"ck-mini-note",children:r("到点时逐个签到,已勾 {n} / {total} 家",{n:h.size,total:a.length})}),s.jsx("button",{type:"button",className:"ck-mini-btn",disabled:t.saving,onClick:v,children:r("全选")}),s.jsx("button",{type:"button",className:"ck-mini-btn",disabled:t.saving||h.size===0,onClick:j,children:r("清空")})]}),s.jsx("div",{className:"ck-range",children:a.map(S=>s.jsxs("label",{className:"ck-range-item",children:[s.jsx(Pr,{checked:h.has(S.id),disabled:t.saving,onCheckedChange:N=>{const k=new Set(h);N===!0?k.add(S.id):k.delete(S.id),b(k)}}),s.jsx("span",{className:"ck-range-name",title:S.label,children:S.label})]},S.id))}),h.size===0?s.jsx("div",{className:"ck-mini-warn",children:r("至少勾一家才能保存(不勾等于这条条目不签到)")}):null]})]}),s.jsxs("div",{className:"ck-sched-actions",children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:t.saving,onClick:()=>bw(null),children:r("取消")}),s.jsx(ne,{size:"sm",variant:"default",disabled:!y||t.saving,onClick:()=>{w()},children:t.saving?r("保存中…"):r("保存")})]})]})}function p9({store:e}){return s.jsxs("div",{className:"ck-sched-row open ck-sched-row-new",children:[s.jsxs("div",{className:"ck-sched-main",children:[s.jsx("span",{className:"ck-new-dot","aria-hidden":!0,children:"+"}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:r("新建定时条目")}),s.jsx("div",{className:"ck-prov-desc",children:r("填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)")})]})]}),s.jsx(vM,{entry:null,store:e})]})}function m9({entry:e,store:t}){const a=Array.isArray(t.data?.providerOptions)?t.data.providerOptions:[],o=t.editingId===e.id,c=t.runningId===e.id,d=t.data?.enabled===!0,f=Number(e.nextRunAt),p=async()=>{const h=Pe().wbConfirm?.ask;if(!h)return;const y=(e.displayLabel||e.time||e.id).replace(/&/g,"&").replace(//g,">");await h({title:r("删除定时条目"),html:r("确定删除「{name}」?删除后到点不再执行。",{name:y}),okText:r("删除"),okClass:"danger"})&&await a9(e.id)};return s.jsxs("div",{className:o?"ck-sched-row open":"ck-sched-row",children:[s.jsxs("div",{className:"ck-sched-main",children:[s.jsx(ns,{checked:e.enabled===!0,disabled:t.saving,onCheckedChange:h=>{r9(e,h===!0)}}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsxs("div",{className:"ck-prov-name",children:[e.displayLabel||e.time||e.id,e.enabled===!0?null:s.jsx(ze,{variant:"outline",shape:"tag",children:r("已停用")})]}),s.jsx("div",{className:"ck-prov-desc ck-sched-scope",title:d9(e,a),children:r("每天 {time} · {scope}",{time:e.time??"—",scope:u9(e,a)})}),s.jsx("div",{className:"ck-prov-desc",children:r("上次执行:{line}",{line:f9(e)})})]}),s.jsxs("div",{className:"ck-prov-right",children:[s.jsx("span",{className:"ck-sched-next",children:d&&e.enabled===!0&&Number.isFinite(f)&&f>0?r("下次 {date}",{date:Ls(f)}):"—"}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:c||t.runningId!==null,onClick:()=>{l9(e.id)},children:r(c?"执行中…":"立即执行")}),s.jsx(ne,{size:"sm",variant:"ghost",onClick:()=>bw(o?null:e.id),children:r(o?"收起":"编辑")}),s.jsx(ne,{size:"sm",variant:"ghost",className:"text-destructive",disabled:t.saving,onClick:()=>{p()},children:r("删除")})]})]}),o?s.jsx(vM,{entry:e,store:t}):null]})}function h9(e,t){return e.length===t.length&&e.every((a,o)=>a===t[o])}let Qf=null;function g9(e,t){for(let a=0;ah!==t.row),d=g9(c,e.clientY);if(d===t.from)return;const f=[...t.list],[p]=f.splice(t.from,1);f.splice(d,0,p),t.list=f,t.from=d,t.onChange(f)}function Zf(){const e=Qf;Qf=null,window.removeEventListener("pointermove",yM),window.removeEventListener("pointerup",Zf),window.removeEventListener("pointercancel",Zf),document.body.classList.remove("ck-chain-dragging"),e?.row.classList.remove("dragging")}function x9(e,t,a,o){if(e.button!==0||Qf||a.length<2)return;const c=e.currentTarget.closest(".ck-chain-row");c&&(e.preventDefault(),Qf={list:[...a],from:t,row:c,onChange:o},c.classList.add("dragging"),document.body.classList.add("ck-chain-dragging"),window.addEventListener("pointermove",yM),window.addEventListener("pointerup",Zf),window.addEventListener("pointercancel",Zf))}function b9({models:e,defaultModels:t,dirty:a,saving:o}){const[c,d]=x.useState(""),f=()=>{const p=c.trim();if(p){if(e.includes(p)){Le(r("清单里已经有「{name}」",{name:p}),"err");return}_g([...e,p]),d("")}};return s.jsxs("section",{className:"panel ck-chain-panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("保活模型链")}),s.jsx("span",{className:"panel-sub",children:r("WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关")}),s.jsx(ne,{size:"sm",variant:"default",className:"ml-auto",disabled:!a||o,onClick:()=>{Y7(e)},children:r(o?"保存中…":"保存")})]}),s.jsxs("div",{className:"p-4",children:[s.jsxs("div",{className:"ck-set-line ck-set-line-top",children:[s.jsx("span",{className:"ck-set-k",children:r("模型清单")}),s.jsxs("span",{className:"ck-set-v",children:[s.jsxs("div",{className:"ck-mini-row",children:[s.jsx("span",{className:"ck-mini-note",children:r("按序逐个尝试,共 {n} 个",{n:e.length})}),s.jsx("button",{type:"button",className:"ck-mini-btn",disabled:o||t.length===0,title:r("把缺省链填进清单,再点「保存」生效"),onClick:()=>_g([...t]),children:r("填入缺省链")})]}),s.jsxs("div",{className:"ck-chain",children:[e.map((p,h)=>s.jsxs("div",{className:"ck-chain-row",children:[s.jsx("span",{className:"ck-chain-grip",role:"button",tabIndex:-1,"aria-label":r("按住拖动调整顺序"),title:r("按住拖动,调整这个模型在链里的顺序"),onPointerDown:b=>x9(b,h,e,_g),dangerouslySetInnerHTML:{__html:Pe().wbIcons?.icon?.("gripVertical",14)||""}}),s.jsx("span",{className:"ck-chain-name",title:p,children:p}),s.jsxs("span",{className:"ck-chain-index",children:["#",h+1]}),s.jsx("button",{type:"button",className:"ck-chain-del",disabled:o,"aria-label":r("移除 {name}",{name:p}),title:r("从清单里移除"),onClick:()=>_g(e.filter((b,y)=>y!==h)),children:"×"})]},p)),e.length===0?s.jsx("div",{className:"ck-chain-empty",children:r("清单为空 —— 保存后恢复缺省链")}):null]}),s.jsxs("div",{className:"ck-chain-add",children:[s.jsx(Fe,{type:"text",className:"max-w-[260px] font-mono text-xs",placeholder:r("WorkBuddy 国际版保活模型,按顺序回退"),value:c,disabled:o,onChange:p=>d(p.currentTarget.value),onKeyDown:p=>{p.key==="Enter"&&(p.preventDefault(),f())}}),s.jsx(ne,{size:"sm",variant:"outline",disabled:o||c.trim()==="",onClick:f,children:r("添加模型")}),a?s.jsx("span",{className:"ck-chain-dirty",children:r("有未保存的改动")}):null]})]})]}),s.jsx("div",{className:"ck-note",children:r("「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。",{defaults:t.join(r("、"))})})]})]})}function v9(){const e=i9(),t=c9();if(x.useEffect(()=>{gM()},[]),!e.loaded)return s.jsxs("div",{className:"ck-loading",children:[s.jsx(of,{className:"size-5"}),s.jsx("span",{children:r("正在读取定时签到数据…")})]});const a=e.data,o=a?.enabled===!0,c=Array.isArray(a?.schedules)?a.schedules:[],d=t.snapshot?.keepalive,f=Array.isArray(d?.models)?d.models:[],p=Array.isArray(d?.defaultModels)?d.defaultModels:[],h=t.keepaliveDraft,b=h??f,y=h!==null&&!h9(h,f);return s.jsxs("div",{children:[e.loadError?s.jsxs("div",{className:"ck-page-error",children:[s.jsx("span",{children:r("读取定时签到数据失败:{error}",{error:e.loadError})}),s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>{gM()},children:r("重试")})]}):null,s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("定时签到")}),s.jsx("span",{className:"tip-q","data-tip":o9}),s.jsx("span",{className:"panel-sub",children:r("每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签")}),s.jsx(ne,{size:"sm",variant:"outline",className:"ml-auto flex-none",disabled:e.saving,onClick:()=>bw(e.editingId==="new"?null:"new"),children:e.editingId==="new"?r("收起新建"):r("添加条目")})]}),s.jsx("div",{className:"p-4",children:s.jsxs("div",{className:"ck-set-line",children:[s.jsx("span",{className:"ck-set-k",children:r("总开关")}),s.jsxs("span",{className:"ck-set-v flex items-center gap-2",children:[s.jsx(ns,{checked:o,disabled:e.saving,onCheckedChange:v=>{s9(v===!0)}}),s.jsx("span",{className:"text-subtle text-xs",children:r(o?"开着:启用的条目按各自时刻执行":"关着:所有条目都不执行")})]})]})}),s.jsxs("div",{children:[e.editingId==="new"?s.jsx(p9,{store:e}):null,c.map(v=>s.jsx(m9,{entry:v,store:e},v.id)),c.length===0?s.jsx("div",{className:"ck-empty",children:r("还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。")}):null]})]}),s.jsx(b9,{models:b,defaultModels:p,dirty:y,saving:t.keepaliveSaving})]})}const Bg="checkin-records",jM=["today","7","30","month","all"],_u="all",y9=[{value:"today",label:r("今天")},{value:"7",label:r("7 天")},{value:"30",label:r("30 天")},{value:"month",label:r("本月")},{value:"all",label:r("全部")}],wM="workbuddy-desktop-checkin-records-range";function Hg(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function SM(e){const t=new Date;switch(e){case"today":return Hg(t);case"7":return Hg(new Date(t.getFullYear(),t.getMonth(),t.getDate()-6));case"30":return Hg(new Date(t.getFullYear(),t.getMonth(),t.getDate()-29));case"month":return Hg(new Date(t.getFullYear(),t.getMonth(),1));default:return null}}function j9(){try{const e=localStorage.getItem(wM);return e!==null&&jM.includes(e)?e:_u}catch{return _u}}function NM(e){try{localStorage.setItem(wM,e)}catch{}}function kM(e){return typeof e=="number"&&e>0?e:xu}const vw={success:{label:"成功领取",variant:"success"},already:{label:"今日已领",variant:"brand"},pending:{label:"等待窗口",variant:"warning"},failed:{label:"失败",variant:"destructive"}},w9={schedule:"定时",startup:"补签",manual:"手动",single:"单签",activity:"活动"},yw=[{key:"time",label:r("时间")},{key:"account",label:r("账号")},{key:"provider",label:r("提供商")},{key:"source",label:r("来源")},{key:"outcome",label:r("结果")},{key:"detail",label:r("说明")}];let jw=null;function CM(){return jw?jw.apply([...yw]):yw.map(e=>({...e,align:e.align??"left"}))}function TM(){window.wbTableColumns?.repaint?.(Bg)}function EM(e){return(fr().snapshot?.auto?.providerOptions??[]).find(a=>a.id===e)?.label??e}function S9(e,t){const a=`ck-col-${t.key} ta-${t.align}`;switch(t.key){case"time":return s.jsxs("td",{className:a,children:[e.ts?Ls(e.ts):"—",s.jsx("span",{className:"ck-record-date",children:e.date||""})]},t.key);case"account":return s.jsx("td",{className:a,children:e.accountName||e.accountId||"—"},t.key);case"provider":return s.jsx("td",{className:a,children:e.provider?EM(e.provider):"—"},t.key);case"source":return s.jsxs("td",{className:a,children:[s.jsx("span",{className:"ck-record-source",children:w9[e.source??""]??e.source??"—"}),e.reason?s.jsx("span",{className:"ck-record-reason",children:e.reason}):null]},t.key);case"outcome":{const o=vw[e.outcome??""]??{label:e.outcome||"—",variant:"outline"};return s.jsxs("td",{className:a,children:[s.jsx(ze,{variant:o.variant,shape:"tag",children:o.label}),e.keptActive?s.jsx(ze,{variant:"outline",shape:"tag",className:"ml-1",children:r("保活")}):null]},t.key)}case"detail":return s.jsx("td",{className:e.error?`${a} ck-record-detail-fail`:a,children:e.error||e.message||"—"},t.key);default:return null}}function N9(){const[e,t]=x.useState([]),[a,o]=x.useState(0),[c,d]=x.useState(1),[f,p]=x.useState(()=>j9()),[h,b]=x.useState(()=>kM(pg(Bg,dg))),[y,v]=x.useState({outcome:"",provider:"",keyword:""}),[j,w]=x.useState(""),[S,N]=x.useState(!1),[k,A]=x.useState(""),[P,R]=x.useState(0),C=x.useRef(null),E=x.useRef(0),[,D]=x.useReducer(Q=>Q+1,0),I=fr().snapshot?.auto?.providerOptions??[],O=CM(),_=Math.max(1,Math.ceil(a/h)),z=Math.min(c,_),H=y.outcome!==""||y.provider!==""||y.keyword!==""||f!==_u,B=a?{start:(z-1)*h+1,end:Math.min(a,z*h)}:null,L=x.useCallback(async Q=>{const G=E.current+1;E.current=G,N(!0),A("");try{const Y=await Pe().workbuddyDesktop?.getCheckinRecords?.({limit:Q.size,offset:(Q.page-1)*Q.size,outcome:Q.filters.outcome,provider:Q.filters.provider,keyword:Q.filters.keyword,start:SM(Q.range)});if(G!==E.current)return;t(Array.isArray(Y?.records)?Y.records:[]),o(Number(Y?.total)||0)}catch(J){if(G!==E.current)return;A(J instanceof Error?J.message:String(J))}finally{G===E.current&&N(!1)}},[]);x.useEffect(()=>{L({page:c,size:h,range:f,filters:y})},[L,c,h,f,y]),x.useEffect(()=>{c>_&&d(_)},[c,_]),x.useLayoutEffect(()=>{const Q=Pe().wbColSettings;if(!Q?.register){const G=window.setTimeout(()=>R(J=>J+1),50);return()=>window.clearTimeout(G)}jw=Q.register({id:Bg,label:r("签到记录表"),columns:yw.map(G=>({key:G.key,label:G.label,align:G.align??"left"})),mount:()=>C.current,onChange:()=>{Ts.flushSync(()=>D()),TM()}}),D()},[P]),x.useLayoutEffect(()=>{TM()}),x.useEffect(()=>()=>{Pe().wbColSettings?.close()},[]);const F=Q=>{v(Q),d(1)},$=Q=>{const G=jM.includes(Q)?Q:_u;G!==f&&(NM(G),p(G),d(1))},X=Q=>{b(kM(Q)),mg(Bg,Q),d(1)},K=()=>{w(""),NM(_u),p(_u),F({outcome:"",provider:"",keyword:""})},q=async()=>{const Q=Pe().wbConfirm?.ask;if(!Q)return;const G=r(H?"确定清空当前筛选出的签到记录?清空后无法恢复。":"确定清空全部签到记录?清空后无法恢复。");if(await Q({title:r("清空签到记录"),html:G,okText:r("清空"),okClass:"danger"}))try{await Pe().workbuddyDesktop?.clearCheckinRecords?.(H?{outcome:y.outcome,provider:y.provider,keyword:y.keyword,start:SM(f)}:{all:"1"}),AM("签到记录已清空"),await L({page:1,size:h,range:f,filters:y}),d(1)}catch(J){AM(r("清空失败:{error}",{error:J instanceof Error?J.message:String(J)}),"err")}};return s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("签到记录")}),s.jsx("span",{className:"panel-sub",children:r("每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准")}),s.jsxs("div",{ref:C,className:"ml-auto flex items-center gap-2",children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:S,onClick:()=>{L({page:c,size:h,range:f,filters:y})},children:r(S?"刷新中…":"刷新")}),s.jsx(ne,{size:"sm",variant:"ghost",className:"text-destructive",onClick:()=>{q()},children:r("清空")})]})]}),s.jsxs("div",{className:"ck-records-filters",children:[s.jsx(En,{options:y9,value:f,onValueChange:$,"aria-label":r("签到记录时间范围"),className:"shrink-0"}),s.jsxs(ut,{value:y.outcome,onValueChange:Q=>F({...y,outcome:Q??""}),children:[s.jsx(ft,{className:"w-[128px] shrink-0","aria-label":r("按结果筛选"),children:s.jsx(dt,{children:y.outcome?vw[y.outcome]?.label??y.outcome:r("全部结果")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"",children:r("全部结果")}),Object.entries(vw).map(([Q,G])=>s.jsx($e,{value:Q,children:G.label},Q))]})]}),s.jsxs(ut,{value:y.provider,onValueChange:Q=>F({...y,provider:Q??""}),children:[s.jsx(ft,{className:"w-[148px] shrink-0","aria-label":r("按提供商筛选"),children:s.jsx(dt,{children:y.provider?EM(y.provider):r("全部提供商")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"",children:r("全部提供商")}),I.map(Q=>s.jsx($e,{value:Q.id,children:Q.label},Q.id))]})]}),s.jsx("div",{className:"spacer"}),s.jsx(Fe,{type:"search",className:"ck-records-search w-[200px] basis-[200px] min-w-[150px] grow-0 shrink",placeholder:r("搜账号 / 收益 / 错误 / 触发原因"),value:j,onChange:Q=>w(Q.currentTarget.value),onBlur:()=>{j!==y.keyword&&F({...y,keyword:j.trim()})},onKeyDown:Q=>{Q.key==="Enter"&&Q.currentTarget.blur(),Q.key==="Escape"&&(w(y.keyword),Q.currentTarget.blur())}}),H?s.jsx(ne,{size:"sm",variant:"ghost",onClick:K,children:r("清除筛选")}):null,s.jsx("span",{className:"panel-sub",children:S?r("读取中…"):r("{n} 条",{n:a})})]}),k?s.jsxs("div",{className:"ck-page-error",children:[s.jsx("span",{children:r("读取签到记录失败:{error}",{error:k})}),s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>{L({page:c,size:h,range:f,filters:y})},children:r("重试")})]}):null,e.length===0&&!S?s.jsx("div",{className:"ck-empty",children:r(H?"没有符合筛选条件的签到记录":"还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。")}):s.jsx("div",{className:"ck-records-scroll",children:s.jsxs("table",{className:"ck-table ck-records-table",children:[s.jsx("colgroup",{children:O.map(Q=>s.jsx("col",{"data-col":Q.key,className:`ck-col-${Q.key}`},Q.key))}),s.jsx("thead",{children:s.jsx("tr",{children:O.map(Q=>s.jsx("th",{"data-col":Q.key,className:`ck-col-${Q.key} ta-${Q.align}`,children:Q.label},Q.key))})}),s.jsx("tbody",{children:e.map(Q=>s.jsx("tr",{children:O.map(G=>S9(Q,G))},Q.rowId))})]})}),s.jsx($i,{total:a,range:B,page:z,pageCount:_,size:h,sizes:dg,onSizeChange:X,onPageChange:d,disabled:S})]})}function AM(e,t){Pe().wbApp?.toast?.(e,t)}window.wbCheckinRecords={visibleColumns:()=>CM().map(e=>({key:e.key}))};const RM={workbuddy:r("腾讯每日签到接口 · 仅国内版"),"workbuddy-intl":r("每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行"),raccoon:r("桌面端每日积分链路"),autoclaw:r("官方客户端的每日签到任务"),"autoclaw-intl":r("与国内版同一套任务接口 · 站点不同"),qoder:r("活动(campaign)领取 · 每天 10:00 刷新"),"qoder-intl":r("带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件"),trae:r("SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新"),loomy:r("无独立签到接口 · 每天替账号打一次首次登录积分"),kuku:r("「免费领积分」的每日任务 · 逐个领取"),officeace:r("一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证"),codearts:r("每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置"),chatglm:r("每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)")},k9=[{value:"center",label:r("签到中心")},{value:"schedule",label:r("定时签到")},{value:"records",label:r("签到记录")}];function C9(e){return r(e==="raccoon"?"小浣熊":e==="loomy"?"Loomy":e==="codearts"?"CodeArts":e==="officeace"?"OfficeAce 果办":e)}function T9(){const[e,t]=x.useState(fr());return x.useEffect(()=>lM(()=>t(fr())),[]),e}function E9({group:e}){const t=J7(e);return t==="none"?s.jsx(ze,{variant:"outline",shape:"tag",children:r("无账号")}):t==="done"?s.jsx(ze,{variant:"success",shape:"tag",children:r("已签")}):t==="part"?s.jsx(ze,{variant:"warning",shape:"tag",children:r("部分")}):s.jsx(ze,{variant:"brand",shape:"tag",children:r("待签")})}function Wf({id:e,label:t}){const a=kg[e==="workbuddy-intl"?"workbuddy":e];return s.jsx("span",{className:"ck-prov-logo",children:a?s.jsx("img",{src:a,alt:""}):t.slice(0,1)||"·"})}function A9({group:e}){const t=fr().signing,a=(o,c)=>t.has(`${o}:${c}`);return s.jsxs("table",{className:"ck-table",children:[s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{children:r("账号")}),s.jsx("th",{children:r("今日签到")}),s.jsx("th",{children:r("上次签到时间")}),s.jsx("th",{"aria-label":r("操作")})]})}),s.jsx("tbody",{children:e.accounts.map(o=>{const c=e.id==="workbuddy-intl";return s.jsxs("tr",{children:[s.jsx("td",{children:o.name||o.id}),s.jsx("td",{children:o.checkedInToday?s.jsx(ze,{variant:"success",shape:"tag",children:r("已签")}):s.jsx(ze,{variant:"brand",shape:"tag",children:r("待签")})}),s.jsx("td",{className:"text-subtle",children:o.checkinAt?Ls(o.checkinAt):"—"}),s.jsx("td",{className:"text-right",children:c?s.jsxs("span",{className:"inline-flex items-center gap-1",children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:a(o.id,"keepalive"),title:r("用免费模型与网页会话维持账号活跃 · 不领取奖励"),onClick:()=>{Pg(o.id,"keepalive")},children:a(o.id,"keepalive")?r("保活中…"):r("保活")}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:a(o.id,"claim"),title:r("探测活动并领取日活奖励 · 不做保活"),onClick:()=>{Pg(o.id,"claim")},children:a(o.id,"claim")?r("领取中…"):r("领取")}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:a(o.id,"full"),title:r("探测 + 领取 + 保活 · 与定时签到同一套组合"),onClick:()=>{Pg(o.id,"full")},children:a(o.id,"full")?r("执行中…"):r("保活+领取")})]}):s.jsx(ne,{size:"sm",variant:"ghost",disabled:a(o.id,"checkin"),onClick:()=>{Pg(o.id)},children:a(o.id,"checkin")?r("签到中…"):o.checkedInToday?r("重签"):r("签到")})})]},o.id)})})]})}function R9({group:e,expanded:t}){const a=e.totalCount>0;return s.jsxs("div",{className:t?"ck-prov-row open":"ck-prov-row",children:[s.jsxs("div",{className:"ck-prov-main",onClick:()=>a&&oM(e.id),onKeyDown:o=>{a&&(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),oM(e.id))},role:a?"button":void 0,tabIndex:a?0:-1,"aria-expanded":a?t:void 0,children:[s.jsx(Wf,{id:e.id,label:e.label}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:e.label}),s.jsx("div",{className:"ck-prov-desc",children:RM[e.id]??""})]}),s.jsxs("div",{className:"ck-prov-right",children:[s.jsx("span",{className:"ck-prov-count",children:a?r("{total} 账号 · {done} 已签",{total:e.totalCount,done:e.doneCount}):"—"}),s.jsx(E9,{group:e}),a?s.jsx("span",{className:"ck-chev","aria-hidden":!0,children:"›"}):null]})]}),e.id==="qoder-intl"?s.jsx(OM,{}):null,t?s.jsx("div",{className:"ck-prov-detail",children:s.jsx(A9,{group:e})}):null]})}function OM(){const[e,t]=x.useState(null),a=x.useCallback(async()=>{try{t(await Lr().getQoderUmid?.()??null)}catch{}},[]);x.useEffect(()=>{a()},[a]);const o=e?.installing===!0&&e.available!==!0;if(x.useEffect(()=>{if(!o)return;const d=window.setInterval(()=>{a()},3e3);return()=>{window.clearInterval(d)}},[o,a]),!e||e.available)return null;const c=async()=>{try{t(d=>d&&{...d,installing:!0}),await Lr().installQoderUmid?.(),Pe().wbApp?.toast?.(r("✅ UMID 组件已安装,下轮签到即可领取国际版积分"))}catch(d){Pe().wbApp?.toast?.(r("UMID 组件安装失败:{error}",{error:d instanceof Error?d.message:String(d)}),"err")}finally{a()}};return s.jsxs("div",{className:"flex flex-wrap items-center gap-2 pb-2.5 pl-[58px] pr-4 text-[12px] text-muted-foreground",children:[s.jsx("span",{children:r("国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。")}),e.installSupported?s.jsx(ne,{variant:"outline",size:"sm",disabled:e.installing===!0,onClick:()=>{c()},children:e.installing?r("安装中…"):r("一键安装组件")}):s.jsx("span",{children:r("安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。")})]})}function O9({row:e}){const t=e.provider??"loomy",a=fr().onboarding.get(e.id),o=a?.tasks??[],c=a?.unclaimed??0,d=a?.status==="loaded"&&o.length>0,f=d&&iM(e.id);return s.jsxs("div",{className:f?"ck-prov-row open":"ck-prov-row",children:[s.jsxs("div",{className:"ck-prov-main",onClick:d?()=>hw(e.id):void 0,onKeyDown:p=>{d&&(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),hw(e.id))},role:d?"button":void 0,tabIndex:d?0:-1,"aria-expanded":d?f:void 0,children:[s.jsx(Wf,{id:t,label:C9(t)}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:e.name||e.id}),s.jsxs("div",{className:"ck-prov-desc",children:[a?.status==="loaded"?r("已领 {claimed}/{total} · 累计 {earned} 积分",{claimed:o.length-c,total:o.length,earned:a.total?`${a.earned} / ${a.total}`:a.earned}):r("尚未查询任务状态"),a?.settled&&a.settledAt?` · ${r("结算于 {time}",{time:Ls(a.settledAt)})}`:a?.checkedAt?` · ${r("查询于 {time}",{time:Ls(a.checkedAt)})}`:""]})]}),s.jsxs("div",{className:"ck-prov-right",onClick:p=>p.stopPropagation(),children:[a?.status==="loaded"&&c>0?s.jsx(ze,{variant:"warning",shape:"tag",children:r("{n} 项待领",{n:c})}):a?.status==="loaded"?s.jsx(ze,{variant:"success",shape:"tag",children:r("全部领取")}):a?.status==="error"?s.jsx(ze,{variant:"destructive",shape:"tag",children:r("查询失败")}):null,s.jsx(ne,{size:"sm",variant:"outline",disabled:a?.status==="loading"||a?.claiming===!0,onClick:()=>{gw(e.id,{expand:!0,refresh:!0})},children:a?.status==="loading"?r("查询中…"):r("查询任务")}),s.jsx(ne,{size:"sm",variant:"outline",disabled:a?.status!=="loaded"||t!=="officeace"&&c===0||a?.claiming===!0,onClick:()=>{uM(e.id)},children:a?.claiming?r("领取中…"):c>0?r("一键领取({n})",{n:c}):r("领取")}),d?s.jsx("span",{className:"ck-chev","aria-hidden":!0,children:"›"}):null]})]}),a?.status==="error"?s.jsx("div",{className:"ck-fold-note",children:r("查询失败:{error}",{error:a.error??""})}):null,f?s.jsx("div",{className:"ck-prov-detail",children:o.map(p=>s.jsxs("div",{className:"ck-task-line",children:[s.jsx("span",{className:p.done?"ck-task-tick done":"ck-task-tick",children:p.done?"✓":"·"}),s.jsx("span",{children:p.title}),s.jsxs("span",{className:"ck-task-pts",children:["+",p.points]}),s.jsx("span",{className:"ck-task-st",children:p.claiming?s.jsx(ze,{variant:"warning",shape:"tag",children:r("领取中")}):p.done?s.jsx(ze,{variant:"success",shape:"tag",children:r("已领取")}):p.blocked?s.jsx(ze,{variant:"outline",shape:"tag",children:r("暂不可领")}):p.error?s.jsx(ze,{variant:"destructive",shape:"tag",children:p.error}):s.jsx(ze,{variant:"brand",shape:"tag",children:r("可领取")})})]},p.key))}):null]})}function M9({row:e}){const t=eg({claimPlans:e.claimPlans}),a=t.length>0;return s.jsxs("div",{className:"ck-welfare-row",children:[s.jsx(Wf,{id:"zcode",label:"ZCode"}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsxs("div",{className:"ck-prov-name",children:[e.name||e.id,a?s.jsx(ze,{variant:"success",shape:"tag",title:r("本地台账里今天(北京时间)领过的套餐:{plans}",{plans:t.join(r("、"))}),children:r("今天已领 {n} 份",{n:t.length})}):s.jsx(ze,{variant:"outline",shape:"tag",title:r("本地台账里今天还没领过;活动期内每天发一份新套餐"),children:r("今天未领")})]}),s.jsx("div",{className:"ck-prov-desc",children:a?r("点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领"):e.claimAt?r("上次领取 {time} · 领取需通过滑块验证码",{time:Ls(e.claimAt)}):r("限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码")})]}),s.jsx("div",{className:"ck-prov-right",children:s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>RR(e.id,e.name),children:r(a?"套餐明细":"去领取")})})]})}function D9({row:e}){const t=fr().growth.get(e.id),a=t?.tasks??[],o=a.filter(v=>v.supported&&!v.unforgeable),c=o.filter(v=>v.status!=="claimed"&&v.current0,f=d&&Q7(e.id),p=t?.travel,h=t?.school,b=t?.results??[],y=v=>b.find(j=>j.code===v);return s.jsxs("div",{className:f?"ck-prov-row open":"ck-prov-row",children:[s.jsxs("div",{className:"ck-prov-main",onClick:d?()=>pM(e.id):void 0,onKeyDown:v=>{d&&(v.key==="Enter"||v.key===" ")&&(v.preventDefault(),pM(e.id))},role:d?"button":void 0,tabIndex:d?0:-1,"aria-expanded":d?f:void 0,children:[s.jsx(Wf,{id:"workbuddy",label:"WorkBuddy"}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:e.name||e.id}),s.jsxs("div",{className:"ck-prov-desc",children:[t?.status==="loaded"?r("{total} 项任务 · {pending} 项可完成",{total:o.length,pending:c.length}):r("查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)"),t?.checkedAt?` · ${r("查询于 {time}",{time:Ls(t.checkedAt)})}`:""]})]}),s.jsxs("div",{className:"ck-prov-right",onClick:v=>v.stopPropagation(),children:[t?.status==="loaded"?c.length>0?s.jsx(ze,{variant:"warning",shape:"tag",children:r("{n} 项可完成",{n:c.length})}):s.jsx(ze,{variant:"success",shape:"tag",children:r("全部完成")}):t?.status==="error"?s.jsx(ze,{variant:"destructive",shape:"tag",children:r("查询失败")}):null,s.jsx(ne,{size:"sm",variant:"outline",disabled:t?.status==="loading"||t?.running===!0,onClick:()=>{Lg(e.id)},children:t?.status==="loading"?r("查询中…"):r("查询任务")}),s.jsx(ne,{size:"sm",variant:"outline",disabled:t?.status!=="loaded"||t?.running===!0,title:r("接单 + 点亮 + 领奖(只处理已实测沉淀的任务)"),onClick:()=>{mM(e.id,"full")},children:t?.running?r("执行中…"):r("一键完成")}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:t?.status!=="loaded"||t?.running===!0,title:r("只领取已完成任务的奖励(幂等,重复点不会重复入账)"),onClick:()=>{mM(e.id,"claim")},children:r("领取")}),d?s.jsx("span",{className:"ck-chev","aria-hidden":!0,children:"›"}):null]})]}),t?.status==="error"?s.jsx("div",{className:"ck-fold-note",children:r("查询失败:{error}",{error:t.error??""})}):null,f?s.jsxs("div",{className:"ck-prov-detail",children:[s.jsxs("div",{className:"ck-fold-note",children:[t?.energy!==null&&t?.energy!==void 0?r("能量 {n}",{n:t.energy}):"",t?.streak!==null&&t?.streak!==void 0?` · ${r("连登 {n} 天",{n:t.streak})}`:"",t?.energy===null&&t?.streak===null?r("(能量 / 连登读数本次未取到)"):""]}),a.map(v=>{const j=y(v.code);return s.jsxs("div",{className:"ck-task-line",children:[s.jsx("span",{className:v.status==="claimed"?"ck-task-tick done":"ck-task-tick",children:v.status==="claimed"?"✓":"·"}),s.jsxs("span",{title:v.description||v.source||v.code,children:[v.title||v.code,v.target>1?` (${v.current}/${v.target})`:""]}),j?s.jsx("span",{className:"ck-task-pts",children:j.message}):null,s.jsx("span",{className:"ck-task-st",children:v.unforgeable?s.jsx(ze,{variant:"outline",shape:"tag",children:r("需真实操作")}):v.supported?v.status==="claimed"?s.jsx(ze,{variant:"success",shape:"tag",children:r("已领取")}):v.status==="completed"?s.jsx(ze,{variant:"brand",shape:"tag",children:r("可领取")}):v.locked?s.jsx(ze,{variant:"outline",shape:"tag",children:r("未解锁")}):s.jsx(ze,{variant:"warning",shape:"tag",children:r("可完成")}):s.jsx(ze,{variant:"outline",shape:"tag",children:r("暂不支持")})})]},v.code)}),s.jsxs("div",{className:"ck-task-line",children:[s.jsx("span",{className:"ck-task-tick",children:"🐾"}),s.jsxs("span",{children:[r("猫猫旅行"),p&&p.hasBuddy===!0?`:${p.buddyName||r("已领养")} · ${p.state==="traveling"?r("在途"):p.state==="arrived"?r("可领奖"):p.state==="idle"?p.dailyLimitReached?r("今日已派出"):r("可派出"):p.state??""}`:p&&p.hasBuddy===!1?`:${r("未领养(领养需先完成当日对话量)")}`:":"+(p?.error?String(p.error):r("尚未查询"))]}),s.jsx("span",{className:"ck-task-st",children:s.jsx(ne,{size:"sm",variant:"ghost",disabled:t?.runningTravel===!0||t?.status!=="loaded",onClick:()=>{W7(e.id)},children:t?.runningTravel?r("执行中…"):r("巡检一次")})})]}),s.jsxs("div",{className:"ck-task-line",children:[s.jsx("span",{className:"ck-task-tick",children:"🎓"}),s.jsxs("span",{children:[r("开学季活动"),h&&h.inPeriod===!0?`:${r("进行中")}${h.lottery?.balance!==void 0&&h.lottery?.balance!==null?` · ${r("抽奖机会 {n} 次",{n:h.lottery.balance})}`:""}`:h&&h.inPeriod===!1?`:${r("非活动期")}`:":"+(h?.error?String(h.error):r("尚未查询"))]}),s.jsx("span",{className:"ck-task-st",children:s.jsx(ne,{size:"sm",variant:"ghost",disabled:t?.runningSchool===!0||t?.status!=="loaded",title:r("执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)"),onClick:()=>{Z7(e.id,!0)},children:t?.runningSchool?r("执行中…"):r("执行并抽奖")})})]}),t?.schoolText?s.jsx("div",{className:"ck-fold-note",children:t.schoolText}):null,t?.lotteryText?s.jsx("div",{className:"ck-fold-note",children:t.lotteryText}):null]}):null]})}function I9({group:e}){return s.jsxs("div",{className:"ck-prov-row",children:[s.jsxs("div",{className:"ck-prov-main",style:{cursor:"default"},children:[s.jsx(Wf,{id:e.id,label:e.label}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:e.label}),s.jsx("div",{className:"ck-prov-desc",children:RM[e.id]??""})]}),s.jsx("div",{className:"ck-prov-right",children:s.jsx(ze,{variant:"outline",shape:"tag",children:r("无账号")})})]}),e.id==="qoder-intl"?s.jsx(OM,{}):null]})}function P9({store:e}){const t=e.snapshot,[a,o]=x.useState(null);x.useEffect(()=>{let N=!0;return(async()=>{try{const A=await Pe().workbuddyDesktop?.getCheckinRecords?.({limit:1});N&&o(Number(A?.total)||0)}catch{}})(),()=>{N=!1}},[e.version]);const c=t?.daily,d=t?.auto,f=(c?.outOfScope??[]).reduce((N,k)=>N+(Number(k.count)||0),0),p=t?.extras.onboarding??[],h=p.filter(N=>e.onboarding.get(N.id)?.status==="loaded"),b=p.reduce((N,k)=>N+(e.onboarding.get(k.id)?.unclaimed??0),0),y=t?.extras.plans??[],v=t?.extras.growth??[],j=Array.isArray(d?.schedules)?d.schedules:[],w=j.filter(N=>N.enabled===!0).length,S=e9(d);return s.jsxs("div",{children:[s.jsxs("div",{className:"ck-stats",children:[s.jsxs("div",{className:"ck-stat",children:[s.jsx("div",{className:"ck-stat-label",children:r("今日签到进度")}),s.jsx("div",{className:"ck-stat-value",children:c?s.jsxs(s.Fragment,{children:[" ",c.todayDone,s.jsxs("small",{children:[" / ",c.todayEligible]})]}):s.jsx("span",{className:"ck-pending",children:"—"})}),s.jsx(cf,{className:"ck-stat-bar",value:c&&c.todayEligible>0?c.todayDone/c.todayEligible*100:0}),s.jsx("div",{className:"ck-stat-foot",children:f>0?r("另有 {n} 个账号不参与每日签到",{n:f}):r("全部账号均可签到")})]}),s.jsxs("div",{className:"ck-stat ck-stat-link",onClick:()=>{Ig("schedule")},role:"button",tabIndex:0,onKeyDown:N=>{N.key==="Enter"&&Ig("schedule")},children:[s.jsx("div",{className:"ck-stat-label",children:r("定时签到")}),s.jsx("div",{className:"ck-stat-value",children:d?s.jsxs(s.Fragment,{children:[w,s.jsxs("small",{children:[" / ",j.length," ",r("条启用")]})]}):s.jsx("span",{className:"ck-pending",children:"—"})}),s.jsx("div",{className:"ck-stat-foot",children:d?.enabled!==!0?r("总开关已关闭 · 在「定时签到」页打开"):S?r("下次 {date} · 点此管理条目",{date:Ls(S)}):r("暂无启用的条目 · 点此添加")})]}),s.jsxs("div",{className:"ck-stat",children:[s.jsx("div",{className:"ck-stat-label",children:r("待领新手福利")}),s.jsx("div",{className:"ck-stat-value",children:p.length?s.jsxs(s.Fragment,{children:[b,s.jsxs("small",{children:[" ",r("项")]})]}):s.jsx("span",{className:"ck-pending",children:r("无")})}),s.jsx("div",{className:"ck-stat-foot",children:p.length?r("已有结果 {checked} / 共 {total} 个账号",{checked:h.length,total:p.length}):r("没有支持新手福利的账号")})]}),s.jsxs("div",{className:"ck-stat ck-stat-link",onClick:()=>{Ig("records")},role:"button",tabIndex:0,onKeyDown:N=>{N.key==="Enter"&&Ig("records")},children:[s.jsx("div",{className:"ck-stat-label",children:r("累计签到记录")}),s.jsx("div",{className:"ck-stat-value",children:a===null?s.jsx("span",{className:"ck-pending",children:"—"}):a}),s.jsx("div",{className:"ck-stat-foot",children:r("每账号一条明细 · 点此查看「签到记录」")})]})]}),s.jsxs("div",{className:"ck-main",children:[s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("每日签到")}),s.jsx("span",{className:"panel-sub",children:r("点击行展开账号明细 · 单账号签到不受范围限制")}),s.jsx(ne,{size:"sm",variant:"default",className:"ml-auto",disabled:e.runningAll||d?.running===!0,onClick:()=>{K7()},children:e.runningAll||d?.running===!0?r("签到中…"):r("立即全部签到")})]}),s.jsxs("div",{children:[(c?.providers??[]).map(N=>N.totalCount>0?s.jsx(R9,{group:N,expanded:e.expanded.has(N.id)},N.id):s.jsx(I9,{group:N},N.id)),(c?.outOfScope??[]).length>0?s.jsx("div",{className:"ck-fold-note",children:r("不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。",{list:c.outOfScope.map(N=>r("{label} ×{count}({reason})",{label:N.label,count:N.count,reason:N.reason})).join(r(";"))})}):null]})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("新手福利")}),s.jsx("span",{className:"panel-sub",children:r("一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单")}),p.length>0?s.jsx(ne,{size:"sm",variant:"outline",className:"ml-auto",onClick:()=>{for(const N of p)N.settled&&typeof N.settled=="object"||gw(N.id)},children:r("全部查询")}):null]}),p.length?s.jsx("div",{children:p.map(N=>s.jsx(O9,{row:N},N.id))}):s.jsx("div",{className:"ck-empty",children:r("没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。")})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("活动福利")}),s.jsx("span",{className:"panel-sub",children:r("限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取")})]}),y.length>0?s.jsx("div",{children:y.map(N=>s.jsx(M9,{row:N},N.id))}):s.jsx("div",{className:"ck-empty",children:r("没有可领套餐的账号(ZCode 未添加)。")})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("成长任务")}),s.jsx("span",{className:"panel-sub",children:r("WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细")})]}),v.length>0?s.jsx("div",{children:v.map(N=>s.jsx(D9,{row:N},N.id))}):s.jsx("div",{className:"ck-empty",children:r("没有支持成长任务的账号(需要 WorkBuddy 国内版)。")})]})]})]})}function _9(){const e=T9(),t=e.snapshot;if(x.useEffect(()=>{Il()},[]),x.useEffect(()=>{window.wbApp?.renderTopbarStatus?.()},[e.version]),!e.loaded)return s.jsxs("div",{className:"ck-loading",children:[s.jsx(of,{className:"size-5"}),s.jsx("span",{children:r("正在读取签到数据…")})]});const a=t?.auto,o=a?.enabled===!0;return s.jsxs("div",{children:[e.loadError?s.jsxs("div",{className:"ck-page-error",children:[s.jsx("span",{children:r("读取签到数据失败:{error}",{error:e.loadError})}),s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>{Il()},children:r("重试")})]}):null,s.jsxs("div",{className:"ck-tabs",children:[s.jsx(En,{options:k9,value:e.tab,onValueChange:c=>aM(c),"aria-label":r("签到中心分区")}),s.jsx(ze,{id:"checkin-badge",className:"ml-auto",variant:a?o?"success":"outline":"destructive","data-tone":a?o?"ok":"":"bad",children:a?o?a?.lastFiredToday?r("今日已执行"):r("已开启"):r("已关闭"):r("不可用")})]}),e.tab==="center"?s.jsx(P9,{store:e}):null,e.tab==="schedule"?s.jsx(v9,{}):null,e.tab==="records"?s.jsx(N9,{}):null]})}const MM='.page[data-page="checkin"]';let DM=!1;function IM(){if(DM)return;const e=document.querySelector(MM);e&&(DM=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(_9,{})))}const PM=()=>Il();window.wbCheckinPanel={load:PM},document.querySelector(MM)?IM():document.addEventListener("DOMContentLoaded",IM,{once:!0}),Pe().wbApp?.currentPage==="checkin"&&PM();function L9(e){return String(e??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function z9({options:e,onSettle:t}){const{title:a="确认操作",html:o="",text:c="",okText:d="确定",okClass:f="primary",bodyClass:p="danger-zone",cancelText:h="取消"}=e,b=x.useRef(null);return x.useEffect(()=>{function y(v){v.key==="Escape"&&t(!1)}return document.addEventListener("keydown",y),()=>document.removeEventListener("keydown",y)},[t]),x.useEffect(()=>{function y(v){v.target?.dataset.slot==="alert-dialog-overlay"&&t(!1)}return document.addEventListener("click",y),()=>document.removeEventListener("click",y)},[t]),s.jsx(PV,{open:!0,onOpenChange:y=>{y||t(!1)},children:s.jsxs(BV,{initialFocus:b,showCloseButton:!0,children:[s.jsx(HV,{className:"pr-10",children:s.jsx(LV,{children:a})}),s.jsx(UV,{children:s.jsx(FV,{tone:p==="danger-zone"?"danger":"neutral",dangerouslySetInnerHTML:{__html:o||L9(c).replace(/\n/g,"
    ")}})}),s.jsxs(VV,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:b,variant:"outline",onClick:()=>t(!1),children:h}),s.jsx(ne,{variant:f==="danger"?"destructive":"default",onClick:()=>t(!0),children:d})]})]})})}let Jf=null,Lu=null,Ug=null;function B9(){Jf&&(Jf.unmount(),Jf=null),Lu&&(Lu.remove(),Lu=null)}function _M(e){const t=Ug;Ug=null,B9(),t?.(e)}function H9(e={}){return new Promise(t=>{Ug&&_M(!1),Ug=t,Lu=document.createElement("div"),document.body.append(Lu),Jf=jn.createRoot(Lu),Jf.render(s.jsx(z9,{options:e,onSettle:_M}))})}window.wbConfirm={ask:H9};const U9=r("Base URL 填进客户端的「API 地址 / Base URL」栏;对话协议按客户端支持的类型三选一(Chat Completions / Responses / Anthropic Messages),三者共用同一套模型与账号池,可随时切换;鉴权用「网关 Key」页里任一启用 Key。");function ep({id:e,name:t,note:a}){return s.jsxs("div",{className:"ep-row",children:[s.jsxs("div",{className:"ep-head",children:[s.jsx("span",{className:"ep-name",children:t}),s.jsx("span",{className:"ep-note",children:a})]}),s.jsxs("div",{className:"ep-line",children:[s.jsx("code",{className:"ep-value",id:e,children:"—"}),s.jsx(ne,{variant:"ghost",size:"icon-xs",className:"copy-btn size-[21px] rounded-[var(--r-xs)]","data-copy-from":e,title:r("复制地址"),children:"⧉"})]})]})}function V9(){return s.jsxs("section",{className:"panel ep-panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("接口地址")}),s.jsx("span",{className:"tip-q","data-tip":U9})]}),s.jsxs("div",{className:"ep-list",children:[s.jsx(ep,{id:"api-base",name:"Base URL",note:r("填进客户端的「API 地址 / Base URL」")}),s.jsx("div",{className:"ep-group",children:r("对话协议(按客户端支持的类型选一行)")}),s.jsx(ep,{id:"api-chat",name:"OpenAI Chat Completions",note:r("多数 OpenAI 兼容客户端的默认协议")}),s.jsx(ep,{id:"api-responses",name:"OpenAI Responses",note:r("OpenAI 新协议(Codex、新版 SDK)")}),s.jsx(ep,{id:"api-messages",name:"Anthropic Messages",note:r("Claude Code / Anthropic SDK(token 计数:/v1/messages/count_tokens)")}),s.jsx("div",{className:"ep-group",children:r("模型清单")}),s.jsx(ep,{id:"api-models",name:r("模型列表"),note:r("客户端自动拉取可用模型;不受鉴权限制,配 Key 之前就能拉")})]}),s.jsx("div",{className:"panel-foot",children:s.jsxs("span",{children:[r("鉴权用「网关 Key」页里任一"),s.jsx("b",{children:r("启用")}),r("的 Key:请求带 "),s.jsx("code",{children:"Authorization: Bearer "}),r(" 或 "),s.jsx("code",{children:"x-api-key: "}),r("。一把启用的 Key 都没有时不鉴权(默认网关只监听 127.0.0.1;在设置页开启「局域网访问」后监听所有网卡,鉴权与安全闸门随之启用)。")]})})]})}const LM='.page[data-page="docs"]';let zM=!1;function BM(){if(zM)return;const e=document.querySelector(LM);e&&(zM=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(V9,{})))}document.querySelector(LM)?BM():document.addEventListener("DOMContentLoaded",BM,{once:!0});function da(){return window}function ww(e){return e instanceof Error?e.message:String(e)}function tp(e,t){da().wbApp?.toast?.(e,t)}function F9(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t]??t)}const Sw=[{key:"name",label:r("名称")},{key:"key",label:"Key"},{key:"time",label:r("创建时间")},{key:"state",label:r("启用")},{key:"act",label:r("操作"),align:"right"}],$9={name:"cell-name",key:"cell-key",time:"cell-time",state:"cell-state state",act:"cell-act r"},HM='.page[data-page="keys"]';let Vg=null,Nw=null;function UM(){return Vg?Vg.apply([...Sw]):Sw.map(e=>({...e,align:e.align??"left"}))}function VM(){da().wbColSettings?.syncStaticHead?.("keys",document.querySelector("table.keys-table"))}function q9(){if(Vg)return;const e=da().wbColSettings?.register({id:"keys",label:r("网关 Key 表"),columns:Sw,mount:()=>document.querySelector('.page[data-page="keys"] .panel-head .head-actions'),onChange:()=>{VM(),Nw?.()}});e&&(Vg=e,VM())}function G9(e){return Array.isArray(e?.keys)?e.keys:[]}function K9(e){return Array.isArray(e?.providers)?e.providers:[]}function Y9(e){const t=e?.modelsByProvider;return t&&typeof t=="object"?t:{}}function kw(e){return r(da().wbProviders?.labelOf?.(e)||e)}function X9(e,t,a){const o=new Map,c=f=>{const p=String(f??"").trim();if(!p)return;const h=p.toLowerCase();o.has(h)||o.set(h,p)};t.forEach(f=>{const p=e[f]??e[String(f).toLowerCase()];Array.isArray(p)&&p.forEach(c)}),a.forEach(c);const d=[...o.values()].map(f=>({value:f,label:r(f)}));return d.sort((f,p)=>f.value.toLowerCase()String(t)):[]}function $M(e,t){const a=new Map(t.map(c=>[c.value.toLowerCase(),c.value])),o=new Set;return e.forEach(c=>{const d=a.get(String(c).toLowerCase());d&&o.add(d)}),t.filter(c=>o.has(c.value)).map(c=>c.value)}function J9({target:e,providers:t,modelsByProvider:a,onClose:o,onSaved:c}){const d=e?.id??null,f=!!d,[p,h]=x.useState(e?.name??""),[b,y]=x.useState(""),[v,j]=x.useState(""),[w,S]=x.useState(!1),N=x.useRef(!1),[k,A]=x.useState(()=>FM(e?.allowedProviders)),[P,R]=x.useState(()=>FM(e?.allowedModels)),C=x.useMemo(()=>t.map(H=>({value:String(H.id),label:r(String(H.label??H.id))})),[t]),E=x.useMemo(()=>$M(k,C),[k,C]),D=x.useMemo(()=>X9(a,E,P),[a,E,P]),I=x.useMemo(()=>$M(P,D),[P,D]),O=D.length?r("没有匹配的选项"):E.length?r("这几家当前没有可用模型(账号未登录或清单为空)"):r("请先在上面选择可用提供商");function _(){N.current=!1,S(!1)}async function z(){if(!N.current){N.current=!0,S(!0),j(r("保存中…"));try{const H=da().workbuddyDesktop;if(!H)throw new Error(r("后端桥不可用"));if(d){const F=await H.updateKey(d,{allowedProviders:E,allowedModels:I});_(),c(F),o(),tp(r("✅ 可用范围已保存"));return}const B=b.trim();if(B&&B.length<8){j(r("Key 至少需要 8 个字符"));return}const L=await H.createKey({name:p.trim(),key:B||void 0,allowedProviders:E,allowedModels:I});_(),c(L,L?.created?.id),o(),tp(r("✅ Key 已创建,记得复制给客户端"))}catch(H){j(r("保存失败:{reason}",{reason:ww(H)}))}finally{_()}}}return s.jsx(Yt,{open:!0,onOpenChange:(H,B)=>{if(!H){if(N.current){B.cancel();return}o()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:f?r("可用范围 · {name}",{name:e?.name||r("未命名")}):r("新建 API Key")})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{htmlFor:"key-name",className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("名称")}),s.jsx(Fe,{id:"key-name",type:"text",maxLength:60,placeholder:r("例如 Cursor / 公司电脑"),autoComplete:"off",value:p,disabled:f,onChange:H=>h(H.currentTarget.value)})]}),!f&&s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{htmlFor:"key-value",className:"text-[12.5px] whitespace-nowrap text-subtle",children:"Key"}),s.jsx(Fe,{id:"key-value",type:"text",placeholder:r("留空自动生成;手填至少 8 个字符"),autoComplete:"off",spellCheck:!1,value:b,onChange:H=>y(H.currentTarget.value),onKeyDown:H=>{H.key==="Enter"&&z()}})]}),s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("可用提供商")}),s.jsx(Gh,{value:E,onValueChange:A,options:C,placeholder:r("留空 = 不限制"),searchPlaceholder:r("搜索提供商…"),"aria-label":r("可用提供商"),className:"flex-auto min-w-[180px] max-w-[260px]"})]}),s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("可用模型")}),s.jsx(Gh,{value:I,onValueChange:R,options:D,placeholder:r("留空 = 不限制"),emptyHint:O,searchPlaceholder:r("搜索模型…"),"aria-label":r("可用模型"),className:"flex-auto min-w-[180px] max-w-[260px]"})]}),s.jsx("p",{children:r("留空表示不限制;同时设置时请求需同时满足两个条件(模型在白名单内且路由到允许的提供商)。 「可用模型」的候选跟着上面勾选的提供商走:没勾提供商时它是空的(还没有约束范围), 勾了几家就列出这几家能收的全部对外名。")}),s.jsx("p",{id:"key-restrict-summary",children:W9(E,I)})]}),s.jsx("div",{className:"min-h-[18px] text-[11.5px] text-muted-foreground",children:v})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:o,disabled:w,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:w,onClick:()=>{z()},children:r(f?"保存范围":"创建")})]})]})})}let Fg=null;async function eK(){await Fg?.load()}function tK(){Fg?.render()}function nK(){const[e,t]=x.useState(null),[a,o]=x.useState(()=>new Set),[c,d]=x.useState(()=>new Set),[f,p]=x.useState(null),[,h]=x.useState(0),b=x.useRef(new Set),y=x.useRef(!1),v=x.useCallback(z=>{t(z)},[]),j=x.useCallback(z=>{z&&Array.isArray(z.keys)&&v(z)},[v]),w=x.useCallback(async()=>{if(!y.current){y.current=!0;try{const z=da().workbuddyDesktop;if(!z)throw new Error(r("后端桥不可用"));v(await z.getKeys()??null)}catch(z){tp(r("读取 Key 列表失败:{reason}",{reason:ww(z)}),"err")}finally{y.current=!1}}},[v]);async function S(z,H,B){if(!b.current.has(z)){b.current.add(z),d(new Set(b.current));try{j(await H()),B&&tp(B)}catch(L){tp(r("操作失败:{reason}",{reason:ww(L)}),"err")}finally{b.current.delete(z),d(new Set(b.current))}}}function N(z){o(H=>{const B=new Set(H);return B.has(z)?B.delete(z):B.add(z),B})}async function k(z){const H=da().workbuddyDesktop,B=da().wbConfirm?.ask;if(!H||!B)return;const L=F9(z.name||z.masked||z.id);await B({title:r("删除网关 Key"),html:r("确定删除 Key「{name}」?使用它的客户端会立刻无法访问。",{name:L}),okText:r("删除"),okClass:"danger"})&&S(z.id,()=>H.deleteKey(z.id),r("Key 已删除"))}function A(z,H){const B=da().workbuddyDesktop;B&&S(z.id,()=>B.updateKey(z.id,{enabled:H}),r(H?"Key 已启用":"Key 已停用"))}x.useLayoutEffect(()=>(Fg={load:w,render:()=>h(z=>z+1)},Nw=()=>h(z=>z+1),q9(),h(z=>z+1),()=>{Fg=null,Nw=null}),[w]),x.useEffect(()=>{da().wbApp?.currentPage==="keys"&&w()},[w]),x.useEffect(()=>{da().wbApp?.renderTopbarStatus?.()},[e]);const P=G9(e),R=hg(P.length,"keys"),C=R.paged?R.slice(P):P,E=UM(),D=e?.authRequired===!0,I=C.filter(z=>z.enabled).length,O=D?r("已启用鉴权 · {n} 把 Key 生效",{n:I}):r("未启用鉴权");function _(z,H,B){switch(z){case"name":return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"mid",children:s.jsx("span",{className:"t",children:H.name||r("未命名")})}),s.jsx("div",{className:"mname",title:Z9(H),children:Q9(H)})]});case"key":{const L=a.has(H.id);return s.jsxs("div",{className:"keycell",children:[s.jsx("code",{className:"kv",children:L?H.key:H.masked}),s.jsx(ne,{size:"sm",variant:"ghost",onClick:()=>N(H.id),children:r(L?"隐藏":"显示")}),s.jsx(ne,{size:"sm",variant:"ghost","data-copy":H.key,title:r("复制 Key"),children:r("复制")})]})}case"time":return s.jsx("span",{className:"muted",children:H.createdAt?da().wbApp?.formatTime?.(H.createdAt):"—"});case"state":return s.jsx(ns,{checked:H.enabled===!0,disabled:B,"aria-label":r("启用「{name}」",{name:H.name||r("未命名")}),onCheckedChange:L=>A(H,L)});case"act":return s.jsxs("div",{className:"row-actions",children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:B,onClick:()=>p({key:H}),children:r("可用范围")}),s.jsx(ne,{size:"sm",variant:"destructive",disabled:B,onClick:()=>{k(H)},children:r("删除")})]});default:return null}}return s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("API Key 列表")}),s.jsx(ze,{id:"keys-status",variant:D?"success":"warning","data-tone":D?"ok":"warn",children:O}),s.jsx("div",{className:"head-actions",children:s.jsx(ne,{variant:"default",onClick:()=>p({key:null}),children:r("+ 新建 Key")})})]}),s.jsx("div",{className:"models-table-wrap",children:s.jsxs("table",{className:"models-table keys-table",children:[s.jsxs("colgroup",{children:[s.jsx("col",{className:"k-name","data-col":"name"}),s.jsx("col",{className:"k-key","data-col":"key"}),s.jsx("col",{className:"k-time","data-col":"time"}),s.jsx("col",{className:"k-state","data-col":"state"}),s.jsx("col",{className:"k-act","data-col":"act"})]}),s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{"data-col":"name",children:r("名称")}),s.jsx("th",{"data-col":"key",children:"Key"}),s.jsx("th",{"data-col":"time",children:r("创建时间")}),s.jsx("th",{"data-col":"state",children:r("启用")}),s.jsx("th",{className:"r","data-col":"act",children:r("操作")})]})}),s.jsx("tbody",{children:C.length?C.map(z=>{const H=c.has(z.id);return s.jsx("tr",{className:z.enabled?"":"off","data-id":z.id,children:E.map(B=>s.jsx("td",{className:`${$9[B.key]??""} ta-${B.align}`,children:_(B.key,z,H)},B.key))},z.id)}):s.jsx("tr",{children:s.jsx("td",{colSpan:E.length,className:"empty",children:r(e?"还没有 Key,当前不鉴权":"加载中…")})})})]})}),s.jsx($i,{leading:s.jsxs("span",{children:[r("客户端请求需带 "),s.jsx("code",{children:"Authorization: Bearer "}),r(" 或 "),s.jsx("code",{children:"x-api-key: "}),r("; 修改后立即生效,本程序自身会自动使用第一把启用的 Key。每把 Key 可单独限制"),s.jsx("b",{children:r("可用提供商")}),r("与"),s.jsx("b",{children:r("可用模型")}),r("(行内「可用范围」):留空 = 不限制,两个都设时 按交集生效 —— 被限制的模型对这把 Key 表现为「不存在」(拉 /v1/models 也看不到它), 提供它的家不在可用列表里时请求同样被拒。")]}),total:P.length,range:R.paged?{start:R.rangeStart,end:R.rangeEnd}:null,page:R.page,pageCount:R.pageCount,size:R.size,onSizeChange:R.setSize,onPageChange:R.goto}),f?s.jsx(J9,{target:f.key,providers:K9(e),modelsByProvider:Y9(e),onClose:()=>p(null),onSaved:(z,H)=>{H&&o(B=>new Set(B).add(H)),j(z)}}):null]})}let qM=!1;function GM(){if(qM)return;const e=document.querySelector(HM);e&&(qM=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(nK,{})))}document.querySelector(HM)?GM():document.addEventListener("DOMContentLoaded",GM,{once:!0}),window.wbKeysPanel={load:eK,render:tK,visibleColumns:UM};const sK="login-app",rK=x.createElement("panel-captcha",{id:"captcha"});function aK(){return s.jsxs("div",{className:"w-[min(400px,100%)] rounded-lg border border-border bg-card p-[36px_34px_30px] shadow-3",children:[s.jsxs("div",{className:"mb-[26px] flex flex-col items-center gap-3 text-center",children:[s.jsxs("svg",{viewBox:"0 0 24 24",role:"img","aria-label":"Agent2API",className:"size-[52px] rounded-[12px] shadow-[0_6px_18px_rgba(0,122,255,0.35)]",children:[s.jsx("rect",{width:"24",height:"24",rx:"5.4",fill:"#007AFF"}),s.jsxs("g",{fill:"none",stroke:"#fff",strokeWidth:"2.2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M5.23 9.24h10.71"}),s.jsx("path",{d:"M15.94 6.72 18.77 9.24 15.94 11.76"}),s.jsx("path",{d:"M18.77 14.76H8.06"}),s.jsx("path",{d:"M8.06 12.24 5.23 14.76 8.06 17.28"})]})]}),s.jsxs("div",{children:[s.jsx("h1",{className:"m-0 text-[21px] font-bold tracking-[0.2px]",children:"Agent2API"}),s.jsx("div",{className:"text-[12.5px] text-muted-foreground",children:r("OpenAI 兼容网关 · 管理面板")})]})]}),s.jsx("div",{id:"mode-tip",className:"mb-[18px] text-center text-[13px] text-muted-foreground"}),s.jsxs("form",{id:"form",autoComplete:"on",children:[s.jsx(Je,{htmlFor:"username",className:"mt-3.5 mb-[5px] text-[12.5px]",children:r("账号")}),s.jsx(Fe,{id:"username",autoComplete:"username",placeholder:r("管理员账号")}),s.jsx(Je,{htmlFor:"password",className:"mt-3.5 mb-[5px] text-[12.5px]",children:r("密码")}),s.jsx(Fe,{id:"password",type:"password",autoComplete:"new-password",placeholder:r("至少 8 位")}),rK,s.jsx(ne,{id:"submit",type:"submit",size:"lg",className:"w-full",children:r("继续")}),s.jsx("div",{id:"error",className:"mt-3 min-h-5 text-center text-[13px] whitespace-pre-wrap text-destructive"})]}),s.jsx("div",{className:"mt-[22px] text-center text-[12px] text-muted-foreground",children:r("登录后可在「网关 Key」页为 API 客户端创建密钥")})]})}function lK(){const e=document.getElementById(sK);e&&Ts.flushSync(()=>{jn.createRoot(e).render(s.jsx(aK,{}))})}lK();function Hr(){return window}function Cw(e){return e instanceof Error?e.message:String(e)}function $g(e,t){Hr().wbApp?.toast?.(e,t)}const KM=1e3,oK=fg,iK=500,YM="workbuddy-desktop-logs-range",Tw="workbuddy-desktop-logs-filters",cK=300,uK="~/.agent2api/logs.jsonl",Ew=["today","7","30","month","all"],Aw="all",dK={today:r("今天"),7:r("7 天"),30:r("30 天"),month:r("本月"),all:r("全部")},fK=Ew.map(e=>({value:e,label:dK[e]})),Rw=[{value:"",label:r("全部级别")},{value:"debug",label:r("debug 及以上")},{value:"info",label:r("info 及以上")},{value:"warn",label:r("warn 及以上")},{value:"error",label:r("仅 error")}],pK=r("全部级别"),XM=r("全部分类"),mK={debug:r("调试"),info:r("信息"),warn:r("警告"),error:r("错误")};let qg=KM,Gg=!0,Ow=!1,Mw=!1,Dw=!1,Iw=null,Po=null,Pw=null,Kg=null,_w=!1,Lw=!1;const zw={level:"",category:"",keyword:""};function hK(){const e=Hr().wbFilterMemory;if(!e)return{...zw};_w=!0;const t=e.load(Tw,{...zw});return{level:Rw.some(a=>a.value===t.level)?t.level:"",category:t.category,keyword:t.keyword}}function Yg(e){Hr().wbFilterMemory?.save(Tw,{level:e.level||"",category:e.category||"",keyword:e.keyword.trim()||""})}function gK(){try{const e=localStorage.getItem(YM);return e!==null&&Ew.includes(e)?e:Aw}catch{return Aw}}function xK(e){try{localStorage.setItem(YM,e)}catch{}}function Xg(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function bK(e){const t=new Date;switch(e){case"today":return Xg(t);case"7":return Xg(new Date(t.getFullYear(),t.getMonth(),t.getDate()-6));case"30":return Xg(new Date(t.getFullYear(),t.getMonth(),t.getDate()-29));case"month":return Xg(new Date(t.getFullYear(),t.getMonth(),1));default:return null}}function vK(e){if(!e)return"—";const t=new Date(e),a=d=>String(d).padStart(2,"0"),o=`${a(t.getHours())}:${a(t.getMinutes())}:${a(t.getSeconds())}`,c=`${a(t.getMonth()+1)}-${a(t.getDate())}`;return t.getFullYear()===new Date().getFullYear()?`${c} ${o}`:`${t.getFullYear()}-${c} ${o}`}function yK(e){const t=e.data;if(!t)return"";const a=[];return(t.from||t.to)&&a.push([t.from,t.to].filter(Boolean).join(" → ")),t.model&&a.push(r("模型 {model}",{model:t.model})),t.resetAtText?a.push(r("{time} 恢复",{time:t.resetAtText})):t.status&&!t.from&&!t.to&&a.push(`HTTP ${t.status}`),a.length?a.join(" · "):""}function Bw(e){return Array.isArray(e?.entries)?e.entries:[]}function Qg(e,t,a){const o=Math.max(1,a==="all"?1:Math.ceil(t.length/a));return Math.min(Math.max(1,e),o)}function Hw(e,t){return Object.hasOwn(e,t)}function jK(e){const t={};if(e&&typeof e=="object")for(const[a,o]of Object.entries(e))typeof o=="string"&&(t[a]=o);return t}function QM(e,t){const a=new URLSearchParams,o=e.keyword.trim(),c=bK(t);return e.level&&a.set("level",e.level),e.category&&a.set("category",e.category),o&&a.set("keyword",o),c!==null&&a.set("start",String(c)),a}function wK(e,t){const a=QM(e,t);return a.set("limit",String(iK)),a.toString()}function SK(e,t){return QM(e,t).toString()}function NK(e){Iw=e||null,Hr().wbApp?.updateLogsBadge?.(Iw)}async function kK(){if(!Ow)try{const e=await Hr().workbuddyDesktop?.getScheduledTasks(),t=(e?.tasks||[]).find(a=>a.id==="logsAutoRefresh");Uw(t||null),Ow=Array.isArray(e?.tasks)}catch(e){console.warn("读取日志自动刷新间隔失败,按默认 10 秒:",Cw(e)),Uw(null)}}function Uw(e){Ow=!0;const t=Number(e?.interval);!!e&&typeof e=="object"&&Number.isFinite(t)&&t>0&&(e.unit==="seconds"||e.unit==="minutes")?(Gg=e.enabled!==!1,qg=e.unit==="minutes"?t*6e4:t*1e3):(Gg=!0,qg=KM),Po?.applyAutoConfig(qg,Gg)}async function CK(e={}){await Po?.load(e)}function TK(e){if(!Po){Kg={data:e??null};return}Po.render(e)}function EK(){return Iw}async function AK(e){if(!Po){Pw=e;return}await Po.showCategory(e)}const RK={entries:[],total:0,matched:0,file:uK,categories:{},loaded:!1};function Vw(e,t){return{entries:Bw(e),total:Number(e?.total)||0,matched:Number(e?.matched)||0,file:e?.file||t.file,categories:Object.keys(t.categories).length?t.categories:jK(e?.categories),loaded:!0}}function OK(e){return e.loaded?e.total?r("没有符合筛选条件的日志"):r("暂无日志"):r("正在加载日志…")}function MK(){const[e,t]=x.useState(RK),[a,o]=x.useState(hK),[c,d]=x.useState(gK),[f,p]=x.useState(1),[h,b]=x.useState(()=>pg("logs")),[y,v]=x.useState(null),[j,w]=x.useState(()=>({ms:qg,enabled:Gg})),S=x.useRef(null),N=x.useRef(null),k=x.useRef(null),A=x.useRef(null),P=x.useRef(a),R=x.useRef(c),C=x.useRef(f),E=x.useRef(h),D=x.useRef(e),I=x.useCallback(le=>{const de={...P.current,...le};return P.current=de,o(de),de},[]),O=x.useCallback(le=>{R.current=le,d(le)},[]),_=x.useCallback(le=>{C.current=le,p(le)},[]),z=x.useCallback(le=>{E.current=le,b(le),mg("logs",le)},[]),H=x.useCallback(le=>{D.current=le,t(le)},[]),B=x.useCallback(()=>{if(_w)return;const le=Hr().wbFilterMemory;if(!le||(_w=!0,Lw))return;const de=le.load(Tw,{...zw});I({level:de.level,category:de.category,keyword:de.keyword})},[I]),L=x.useCallback(async(le={})=>{const{silent:de=!1,resetPage:Se=!1}=le;Se&&_(1),kK(),B();const Te=wK(P.current,R.current),_e=C.current;try{const Ae=Hr().workbuddyDesktop;if(!Ae)throw new Error(r("后端桥不可用"));const[oe,me]=await Promise.all([Ae.getLogs(Te),Ae.getLogStats()]),pe=Se?0:S.current?.scrollTop??0,Ce=Vw(oe,D.current);H(Ce),_(Qg(C.current,Bw(oe),E.current)),N.current=C.current===_e?pe:0,NK(me),Object.keys(Ce.categories).length&&P.current.category&&!Hw(Ce.categories,P.current.category)&&(Yg(I({category:""})),L({resetPage:!0}))}catch(Ae){de||(console.warn("读取运行日志失败:",Cw(Ae)),H(Vw(null,D.current)),_(Qg(C.current,[],E.current)))}},[H,_,B]),F=x.useCallback(le=>{le!==void 0&&(H(Vw(le,D.current)),_(Qg(C.current,Bw(le),E.current)))},[H,_]),$=x.useCallback(async le=>{if(Hw(D.current.categories,le)||await L({silent:!0}),!Hw(D.current.categories,le))return;const de=I({category:le});Yg(de),_(1),await L({resetPage:!0}),Hr().wbApp?.showPage?.("logs",{persist:!0})},[I,_,L]);x.useEffect(()=>{if(Po={load:L,render:F,showCategory:$,applyAutoConfig:(de,Se)=>w({ms:de,enabled:Se})},Kg){const de=Kg;Kg=null,F(de.data)}const le=Pw;return le!==null?(Pw=null,$(le)):L({silent:!0}),()=>{Po=null,k.current!==null&&window.clearTimeout(k.current),k.current=null}},[L,F,$]),x.useEffect(()=>{if(!j.enabled||j.ms<=0)return;const le=window.setInterval(()=>{document.hidden||Hr().wbApp?.currentPage!=="logs"||Mw||(Mw=!0,L({silent:!0}).finally(()=>{Mw=!1}))},j.ms);return()=>{window.clearInterval(le)}},[j,L]),x.useLayoutEffect(()=>{const le=N.current;if(le===null)return;N.current=null;const de=S.current;de&&(de.scrollTop=le)});async function X(le,de,Se){if(!Dw){Dw=!0,v({which:le,label:de});try{await Se()}catch(Te){$g(r("操作失败:{error}",{error:Cw(Te)}),"err")}finally{Dw=!1,v(null)}}}async function K(){const le=SK(P.current,R.current),de=le.length>0,Se=de?r("确定清空当前筛选出的 {count} 条日志?清空后无法恢复。",{count:Number(D.current.matched)||0}):r("确定清空全部运行日志?清空后无法恢复。"),Te=Hr().wbConfirm?.ask;Te&&await Te({title:r("清空运行日志"),html:Se,okText:r("清空"),okClass:"danger"})&&await X("clear",r("清空中…"),async()=>{const _e=Hr().workbuddyDesktop;if(!_e)throw new Error(r("后端桥不可用"));await _e.clearLogs(de?le:"all=1"),await L({resetPage:!0}),$g(r("运行日志已清空"))})}async function q(){await X("export",r("导出中…"),async()=>{const le=Hr().workbuddyDesktop;if(!le)throw new Error(r("后端桥不可用"));const de=await le.exportLogs();if(!(!de||de.canceled)){if(de.count===0){$g(r("暂无日志可导出"),"err");return}$g(r("✅ 已导出 {count} 条日志到 {file}",{count:String(de.count),file:String(de.file)}))}})}function Q(le){const de=Qg(le,D.current.entries,E.current);de!==C.current&&(_(de),N.current=0)}function G(le){if(le===E.current)return;const de=D.current.entries.length,Se=de?(C.current-1)*(E.current==="all"?de:E.current):0;z(le),_(le==="all"?1:Math.floor(Se/le)+1),N.current=0}function J(le){Lw=!0,Yg(I(le)),L({resetPage:!0})}function Y(le){Lw=!0,I({keyword:le}),k.current!==null&&window.clearTimeout(k.current),k.current=window.setTimeout(()=>{k.current=null,Yg(P.current),L({resetPage:!0})},cK)}function re(le){const de=Ew.includes(le)?le:Aw;de!==R.current&&(O(de),xK(de),L({resetPage:!0}))}const M=e.entries,U=h!=="all",Z=Math.max(1,U?Math.ceil(M.length/h):1),ae=Math.min(Math.max(1,f),Z),ce=U?M.slice((ae-1)*h,ae*h):M,W=M.length?U?(ae-1)*h+1:1:0,ue=M.length?U?W+ce.length-1:M.length:0,ve=e.categories,ee=e.matched===e.total?r("{n} 条",{n:e.total}):r("{matched} / {total} 条",{matched:e.matched,total:e.total});x.useEffect(()=>{const le=e.loaded?ee:"—";A.current!==le&&(A.current=le,Hr().wbApp?.renderTopbarStatus?.())},[e.loaded,ee]);function he(le,de){const Se=le.level||"",Te=yK(le);return s.jsxs("div",{className:`log-row ${Se}`,children:[s.jsx("span",{className:"log-rail",children:s.jsx("span",{className:`log-dot ${Se}`})}),s.jsxs("div",{className:"log-main",children:[s.jsxs("div",{className:"log-line",children:[s.jsx("span",{className:"log-cat",children:ve[le.category||""]||le.category}),s.jsx("span",{className:`log-lvl ${Se}`,children:mK[Se]||le.level}),s.jsx("span",{className:"msg",children:le.message})]}),Te?s.jsx("div",{className:"log-extra-wrap",children:s.jsx("span",{className:"extra",children:Te})}):null]}),s.jsx("span",{className:"time",children:vK(le.ts)})]},le.id??de)}const te=y?.which==="export",ke=y?.which==="clear";return s.jsxs("section",{className:"panel",id:"logs-panel-events",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("系统事件")}),s.jsx(ze,{id:"logs-badge",variant:"outline","data-tone":"",children:e.loaded?ee:"—"}),s.jsxs("div",{className:"head-actions",children:[s.jsx(ne,{id:"btn-logs-export",variant:"outline",disabled:y!==null,onClick:()=>{q()},children:te?y?.label:r("导出")}),s.jsx(ne,{id:"btn-logs-clear",variant:"destructive",disabled:y!==null,onClick:()=>{K()},children:ke?y?.label:r("清空")})]})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"log-filters",children:[s.jsx(En,{options:fK,value:c,onValueChange:re,"aria-label":r("事件日志时间范围"),className:"shrink-0"}),s.jsxs(ut,{value:a.level,onValueChange:le=>J({level:String(le??"")}),children:[s.jsx(ft,{id:"logs-level",className:"min-w-[120px]",title:r("按最低级别筛选"),"aria-label":r("按最低级别筛选"),children:s.jsx(dt,{children:Rw.find(le=>le.value===a.level)?.label??pK})}),s.jsx(pt,{children:Rw.map(le=>s.jsx($e,{value:le.value,children:le.label},le.value))})]}),s.jsxs(ut,{value:a.category,onValueChange:le=>J({category:String(le??"")}),children:[s.jsx(ft,{id:"logs-category",className:"min-w-[120px]",title:r("按分类筛选"),"aria-label":r("按分类筛选"),children:s.jsx(dt,{children:a.category?ve[a.category]||a.category:XM})}),s.jsxs(pt,{children:[s.jsx($e,{value:"",children:XM}),Object.entries(ve).map(([le,de])=>s.jsx($e,{value:le,children:de},le))]})]}),s.jsxs(Di,{className:"w-auto flex-auto",children:[s.jsx(Pi,{id:"logs-keyword",type:"search",placeholder:r("搜索消息关键词…"),autoComplete:"off","aria-label":r("搜索消息关键词"),value:a.keyword,onChange:le=>Y(le.currentTarget.value)}),s.jsx(Ii,{"aria-hidden":"true",children:"⌕"})]})]}),s.jsx("div",{className:"log-list",id:"log-list",ref:S,children:ce.length?ce.map((le,de)=>he(le,de)):s.jsx("div",{className:"log-empty",children:OK(e)})})]}),s.jsx($i,{total:M.length,range:U?{start:W,end:ue}:null,page:ae,pageCount:Z,size:h,sizes:oK,onSizeChange:G,onPageChange:Q})]})}const ZM='.page[data-page="logs"]';let WM=!1;function JM(){if(WM)return;const e=document.querySelector(ZM);e&&(WM=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(MK,{})))}document.querySelector(ZM)?JM():document.addEventListener("DOMContentLoaded",JM,{once:!0}),window.wbLogsPanel={load:CK,render:TK,lastStats:EK,applyAutoRefresh:Uw,showCategory:AK};const zu=["maxInputTokens","maxOutputTokens","supportsToolCall","supportsImages","supportsVideo","supportsReasoning"],np=["maxInputTokens","maxOutputTokens"],e2=["supportsToolCall","supportsImages","supportsVideo","supportsReasoning"],Bu={maxInputTokens:r("上下文窗口"),maxOutputTokens:r("最大输出 Token"),supportsToolCall:r("工具调用"),supportsImages:r("图片识别"),supportsVideo:r("视频识别"),supportsReasoning:r("支持思考")};r("工具"),r("图片"),r("视频"),r("思考");const DK=1e8;function Fw(e){return np.includes(e)}function $w(e,t){if(Fw(e)){const a=typeof t=="number"?t:Number(t);return!Number.isFinite(a)||a<1||a>DK?null:Math.trunc(a)}return typeof t=="boolean"?t:null}function t2(e){const t={};if(!e||typeof e!="object")return t;const a=e;for(const o of zu){const c=$w(o,a[o]);c!==null&&(t[o]=c)}return t}function qw(e){return Array.isArray(e)?zu.filter(t=>e.some(a=>a===t)):[]}function Gw(e){return t2(e?.capabilities)}function n2(e){const t=Number(e);if(!Number.isFinite(t)||t<=0)return"—";const a=o=>o.toFixed(1).replace(/\.0$/,"");return t>=1e6?`${a(t/1e6)}M`:t>=1e3?`${a(t/1e3)}K`:String(Math.round(t))}function sp(e){const t=Number(e);return!Number.isFinite(t)||t<=0?r("未声明"):Math.round(t).toLocaleString("en-US")}function Kw(e){return e===!0?"on":e===!1?"off":"unset"}function IK(e){const t=e?.reasoningLevels;if(!Array.isArray(t))return null;const a=t.filter(c=>typeof c=="string"&&c.trim()!=="");if(!a.length)return null;const o=e?.reasoningDefaultLevel;return{levels:a,defaultLevel:typeof o=="string"?o.trim():""}}function PK(e,t,a,o=""){const c=Bu[e],d=a?r("(已被手动覆盖,弹窗里可恢复继承)"):"",f=_K(o);if(Fw(e))return t==null?r("{label}:上游未声明{suffix}",{label:c,suffix:d}):r("{label}:{value}(对下游声明的精确值){origin}{suffix}",{label:c,value:sp(t),origin:f,suffix:d});const p=Kw(t);return p==="on"?r("{label}:支持{origin}{suffix}",{label:c,origin:f,suffix:d}):p==="off"?r("{label}:不支持{origin}{suffix}",{label:c,origin:f,suffix:d}):r("{label}:上游未声明(下游会按不支持处理){suffix}",{label:c,suffix:d})}function Hu(e,t){const a=e?.capSources?.[t];return a==="upstream"||a==="modelsdev"||a==="user"?a:""}function _K(e){return e==="modelsdev"?r("(由 models.dev 补齐)"):e==="user"?r("(手动设定)"):""}function LK(e){const t={};for(const a of zu){const o=e[a];Fw(a)?t[a]=$w(a,o.trim()):t[a]=o==="on"?!0:o==="off"?!1:null}return t}function rp(){return window}const s2=e=>String(e??"").trim().toLowerCase(),Ks=(e,t)=>s2(e)===s2(t);function as(e){return typeof e=="string"&&e.startsWith("custom-")}function Wi(){return(rp().wbProviders?.customList?.()||[]).filter(e=>as(e?.id))}function r2(){return rp().wbProviders?.customList?.()||[]}function _o(e){return Wi().find(t=>t.id===e)||null}function zK(e){const t=t2(e),a={};for(const o of zu){const c=t[o];(typeof c=="number"||typeof c=="boolean")&&(a[o]=c)}return Object.keys(a).length?a:void 0}function a2(e){const t=(Array.isArray(e?.models)?e.models:[]).map(c=>{const d={id:String(c?.id??"").trim(),enabled:c?.enabled!==!1,reasoning:typeof c?.reasoning=="string"?c.reasoning:""};return d.capabilities=zK(c?.capabilities),d}).filter(c=>c.id),a=(Array.isArray(e?.mappings)?e.mappings:[]).map(c=>({alias:String(c?.alias??"").trim(),target:String(c?.target??"").trim(),enabled:c?.enabled!==!1,reasoning:typeof c?.reasoning=="string"?c.reasoning:""})).filter(c=>c.alias&&c.target);for(const c of t){const d=a.find(f=>Ks(f.alias,c.id)&&Ks(f.target,c.id));d&&(c.enabled=c.enabled&&d.enabled,c.reasoning=d.reasoning||c.reasoning)}const o=a.filter(c=>!(Ks(c.alias,c.target)&&t.some(d=>Ks(d.id,c.target))));return{models:t,mappings:o}}function l2(e){const t=_o(e);if(!t)return null;const a=a2(t),o=t.name||e,c=[],d=[];for(const f of a.models)c.push({id:f.id,name:"",provider:e,providerLabel:o,source:"",enabled:f.enabled,aliases:[],capabilities:f.capabilities||{},capOverrides:[]}),d.push({alias:f.id,target:f.id,provider:e,enabled:f.enabled,reasoning:f.reasoning,isDefault:!0,dangling:!1,carried:!0});for(const f of a.mappings){const p=c.find(h=>Ks(h.id,f.target));d.push({alias:f.alias,target:f.target,provider:e,enabled:f.enabled,reasoning:f.reasoning,isDefault:!1,dangling:!p,carried:!!p}),p&&p.aliases.push(f.alias)}return{models:c,mappings:d}}async function Ji(e,t){const a=rp().wbProviders;if(!a?.customRequest)throw new Error(r("目录模块未就绪"));const o=_o(e);if(!o)throw new Error(r("该自定义提供商已不存在(可能已被删除),请刷新后重试"));const c=a2(o),d=t(c);return await a.customRequest("POST","/api/custom-providers/models",{providerId:e,models:c.models,mappings:c.mappings}),await a.refreshCustom?.(),d}async function o2(e,t,a,o={}){const{enabled:c,reasoning:d}=o;await Ji(e,f=>{if(Ks(t,a)){const h=f.models.find(b=>Ks(b.id,a));if(!h)throw new Error(r("该提供商的清单里没有模型「{name}」",{name:a}));return c!==void 0&&(h.enabled=!!c),d!==void 0&&(h.reasoning=String(d??"")),null}const p=f.mappings.find(h=>Ks(h.alias,t)&&Ks(h.target,a));if(p)return c!==void 0&&(p.enabled=!!c),d!==void 0&&(p.reasoning=String(d??"")),null;if(c===!1)throw new Error(r("映射「{alias} → {target}」不存在",{alias:t,target:a}));return f.mappings.push({alias:t,target:a,enabled:c??!0,reasoning:String(d??"")}),null})}async function i2(e,t,a){await Ji(e,o=>{const c=o.mappings.length;if(o.mappings=o.mappings.filter(d=>!(Ks(d.alias,t)&&Ks(d.target,a))),o.mappings.length===c)throw new Error(r("映射「{alias} → {target}」不存在",{alias:t,target:a}));return null})}async function c2(e,t){const a=String(t??"").trim();if(!a)throw new Error(r("请填写模型 ID"));await Ji(e,o=>{if(o.models.some(c=>Ks(c.id,a)))throw new Error(r("模型「{name}」已存在(忽略大小写判重)",{name:a}));return o.models.push({id:a,enabled:!0,reasoning:""}),null})}async function BK(e,t){const a=(Array.isArray(t)?t:[]).map(o=>String(o??"").trim()).filter(Boolean);if(!a.length)throw new Error(r("没有选中任何模型"));return Ji(e,o=>{let c=0;for(const d of a)o.models.some(f=>Ks(f.id,d))||(o.models.push({id:d,enabled:!0,reasoning:""}),c++);return c})}async function u2(e,t,a){await Ji(e,o=>{const c=o.models.find(f=>Ks(f.id,t));if(!c)throw new Error(r("该提供商的清单里没有模型「{name}」",{name:t}));const d={...c.capabilities||{}};for(const[f,p]of Object.entries(a))p==null?delete d[f]:d[f]=p;return c.capabilities=Object.keys(d).length?d:void 0,null})}async function d2(e,t){return Ji(e,a=>{const o=a.mappings.length;a.mappings=a.mappings.filter(d=>!Ks(d.target,t));const c=o-a.mappings.length;return a.models=a.models.filter(d=>!Ks(d.id,t)),{removedMappings:c}})}async function HK(e){const t=rp().wbProviders;if(!t?.customRequest)throw new Error(r("目录模块未就绪"));const a=await t.customRequest("POST","/api/custom-providers/fetch-models",{providerId:e}),o=(Array.isArray(a?.models)?a.models:[]).map(d=>String(d??"").trim()).filter(Boolean),c=await Ji(e,d=>{let f=0;for(const p of o)d.models.some(h=>Ks(h.id,p))||(d.models.push({id:p,enabled:!0,reasoning:""}),f++);return f});return{total:o.length,added:Number(c)||0}}rp().wbModelsCustom={isCustom:as,list:Wi,listSource:r2,record:_o,buildView:l2,setBinding:o2,removeMapping:i2,addModel:c2,addModels:BK,removeModel:d2,setCapabilities:u2,fetchModels:HK};const fa="__custom__",UK=["off","none","minimal","low","medium","high","xhigh","max"];function ap(e,t){const a=f2(t);if(a.length)return a;const o=e?.reasoningLevels;return Array.isArray(o)&&o.length?o.filter(c=>typeof c=="string"):[...UK]}function f2(e){const t=e?.reasoningLevels;return Array.isArray(t)?t.filter(a=>typeof a=="string"&&a.trim()!==""):[]}function VK(e,t){const a=t.map(f2).filter(f=>f.length>0);if(!a.length||a.length!==t.length)return ap(e);const[o,...c]=a,d=o.filter(f=>c.every(p=>p.includes(f)));return d.length?d:ap(e)}function p2(e,t,a){return`${String(e??"").trim().toLowerCase()}${String(t??"").trim().toLowerCase()}${String(a??"").trim().toLowerCase()}`}function FK(e){const t=new Map;for(const a of Array.isArray(e)?e:[]){const o=typeof a?.reasoning=="string"?a.reasoning.trim():"";o&&t.set(p2(a.alias,a.target,a.provider),o)}return(a,o,c)=>t.get(p2(a,o,c))||""}function Wt(){return window}function Lo(e){return e instanceof Error?e.message:String(e)}function Nr(e,t){Wt().wbApp?.toast?.(e,t)}function Yw(e){const t=Wt().wbApp?.esc;return t?t(e):String(e??"").replace(/[&<>"']/g,a=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[a]||a)}function $K(e){const t=Wt().formatTime??Wt().wbApp?.formatTime;return String(t?.(e)??"")}const m2=e=>String(e??"").trim().toLowerCase(),zo=(e,t)=>m2(e)===m2(t),h2=8,g2="workbuddy-desktop-models-filters",Xw=["all","enabled","disabled","mapped"],qK={all:r("全部"),enabled:r("已启用"),disabled:r("已禁用"),mapped:r("有映射")},GK=Xw.map(e=>({value:e,label:qK[e]})),Qw=["default","rate-asc","rate-desc"],KK={default:r("默认"),"rate-asc":r("倍率升序"),"rate-desc":r("倍率降序")},YK=Qw.map(e=>({value:e,label:KK[e]})),Zw=[{key:"check",label:r("选择"),align:"center"},{key:"model",label:r("上游模型")},{key:"rate",label:r("倍率")},{key:"source",label:r("来源")},{key:"budget",label:r("上下文 / 输出")},{key:"caps",label:r("能力")},{key:"alias",label:r("模型映射")},{key:"act",label:r("操作"),align:"right"}],x2=new Set(["rate","source"]),lp="custom-all",Ww={models:[],mappings:[]},b2={provider:"all",state:"all",search:"",sort:"default"};function v2(){const e=Wt().wbFilterMemory;if(!e)return{...b2};const t=e.load(g2,{...b2});return{provider:String(t.provider||"all"),state:Xw.includes(t.state)?t.state:"all",search:String(t.search||""),sort:Qw.includes(t.sort)?t.sort:"default"}}const Zg=v2();let y2=!!Wt().wbFilterMemory,Wg=!1,ls={provider:Zg.provider,stateFilter:Zg.state,search:Zg.search,sort:Zg.sort,data:null,expanded:new Set,pending:new Set,mapping:null,customModel:null,capability:null};const Jw=new Set;function op(){return ls}function XK(e){return Jw.add(e),()=>{Jw.delete(e)}}function zs(e){const t={...ls,...e},a=ex(t),o=ex(ls)!==a;ls=a===t.provider?t:{...t,provider:a},ZK(),o&&tx();for(const c of Jw)c()}function Jg(e){Wt().wbFilterMemory?.save(g2,e)}function j2(){if(y2||Wg||!Wt().wbFilterMemory)return;y2=!0;const e=v2();(e.provider!==ls.provider||e.state!==ls.stateFilter||e.search!==ls.search||e.sort!==ls.sort)&&zs(e)}function ex(e){const t=e.provider;return t==="all"||t===lp||Wi().some(a=>a.id===t)||Array.isArray(e.data?.models)&&e.data.models.some(a=>(a.provider||"")===t)||!e.data||!e0()?t:"all"}function Uu(){return ex(ls)}function e0(){return!!Wt().wbProviders}function Vu(){return Uu()===lp}function w2(){return Vu()||as(Uu())}let ip=null;function t0(e){const t=_o(e);return(!ip||ip.id!==e||ip.record!==t)&&(ip={id:e,record:t,view:l2(e)||Ww}),ip.view}let cp=null;function QK(){const e=r2();if(cp&&cp.directory===e)return cp.view;const t=[],a=[];for(const o of Wi()){const c=t0(String(o.id||""));t.push(...c.models||[]),a.push(...c.mappings||[])}return cp={directory:e,view:t.length||a.length?{models:t,mappings:a}:Ww},cp.view}function n0(){const e=Uu();return as(e)?t0(e):e===lp?QK():ls.data||Ww}function up(){const e=n0();return Array.isArray(e.models)?e.models:[]}function S2(){const e=n0();return Array.isArray(e.mappings)?e.mappings:[]}let N2=(e,t,a)=>"";function ZK(){N2=FK(S2())}function s0(){const e=new Map,t=Array.isArray(ls.data?.models)?ls.data.models:[];for(const a of t){const o=a.provider||"";if(!o)continue;const c=e.get(o)||{label:a.providerLabel||o,n:0};c.n++,e.set(o,c)}return e}function WK(){const e=new Map;for(const t of Wi()){const a=String(t.id||"");if(!a)continue;const o=t0(a);e.set(a,{label:String(t.name||a),n:(o.models||[]).length})}return e}function JK(){return[...s0().keys()]}function eY(e){const a=(Array.isArray(ls.data?.models)?ls.data.models:[]).find(o=>o.provider===e);return Number(a?.refreshedAt)||0}function r0(){const e=new Map;for(const t of up()){const a=t.provider||"";a&&!e.has(a)&&e.set(a,r(t.providerLabel||a))}return[...e].map(([t,a])=>({id:t,label:a}))}function k2(e){return e?up().filter(t=>(t.provider||"")===e).sort((t,a)=>+(t.enabled===!1)-+(a.enabled===!1)).map(t=>({id:t.id,label:t.name&&t.name!==t.id?r("{id}({name})",{id:t.id,name:t.name}):t.id,off:t.enabled===!1})):[]}function tY(){const e=[],t=Wt().wbProviders?.all?.();if(Array.isArray(t))for(const a of t){const o=String(a?.id||"");o&&e.push({id:o,label:r(String(a?.label||o))})}for(const a of Wi()){const o=String(a.id||"");o&&e.push({id:o,label:String(a.name||o)})}return e.length?e:r0()}let dp=null,a0=null;function C2(){const e=dp?dp.apply(Zw):Zw;return w2()?e.filter(t=>!x2.has(t.key)):e}function tx(){Wt().wbColSettings?.syncStaticHead("models",a0,w2()?x2:null)}function nY(){if(dp)return;dp=Wt().wbColSettings?.register({id:"models",label:r("模型管理表"),columns:Zw,mount:()=>document.querySelector('.page[data-page="gateway"] .panel-head .head-actions'),buttonPlacement:"last",onChange:()=>{tx(),ec()}})||null,dp&&ec()}let nx=0,l0=!1;async function sx({force:e=!1}={}){if(l0&&!e)return;const t=++nx;l0=!0,j2();try{const a=await Wt().workbuddyDesktop?.getModelManage();if(t!==nx)return;zs({data:a&&Array.isArray(a.models)?a:null})}catch(a){if(t!==nx)return;ec(),Nr(r("读取模型清单失败:{message}",{message:Lo(a)}),"err")}finally{t===nx&&(l0=!1)}}async function T2(){try{await Wt().wbProviders?.refreshCustom?.()}catch{}await sx({force:!0})}function ec(){zs({})}function tc(e){const t=e;if(t&&Array.isArray(t.models)){zs({data:t});return}ec()}async function rx(e,t,a,o){if(as(e))return o2(e,t,a,o);const c=Wt().workbuddyDesktop;if(!c)throw new Error(r("后端桥不可用"));return c.addModelMapping(t,a,e,o.reasoning,o.enabled)}async function sY(e,t,a){if(as(e))return i2(e,t,a);const o=Wt().workbuddyDesktop;if(!o)throw new Error(r("后端桥不可用"));return o.removeModelMapping(t,a,e)}async function rY(e,t){if(as(e))return c2(e,t);const a=Wt().workbuddyDesktop;if(!a)throw new Error(r("后端桥不可用"));return a.addCustomModel(e,t)}async function E2(e,t){if(as(e))return d2(e,t);const a=Wt().workbuddyDesktop;if(!a)throw new Error(r("后端桥不可用"));return a.removeCustomModel(e,t)}async function aY(e,t,a){if(as(e))return u2(e,t,a);const o=Wt().workbuddyDesktop;if(!o)throw new Error(r("后端桥不可用"));return o.setModelCapabilities(e,t,a)}async function o0(e,t,a){if(!ls.pending.has(e)){zs({pending:new Set(ls.pending).add(e)});try{tc(await t()),a&&Nr(a)}catch(o){Nr(r("操作失败:{message}",{message:Lo(o)}),"err")}finally{const o=new Set(ls.pending);o.delete(e),zs({pending:o})}}}function fp(e){return Fu(e).some(t=>t.enabled!==!1)}function Fu(e){const t=e.provider||"",a=S2().filter(p=>zo(p.target,e.id)&&(!p.provider||zo(p.provider,t))),o=new Map;for(const p of a){const h=String(p.alias).toLowerCase();(!o.has(h)||p.provider)&&o.set(h,p)}const c=String(e.id).toLowerCase(),d=o.get(c);o.delete(c);const f=[{alias:e.id,target:e.id,provider:t,enabled:e.enabled!==!1&&d?.enabled!==!1,isDefault:!0}];return f.push(...o.values()),f}const nc=e=>`${e.provider||""}:${e.id}`,i0=(e,t,a)=>`${e}:${t}:${a||""}`;function lY(e){zs({expanded:new Set(ls.expanded).add(e)})}function oY(e){const t=new Set(ls.expanded);t.delete(e),zs({expanded:t})}function iY(e){const t=Xw.includes(e)?e:"all";t!==ls.stateFilter&&(Wg=!0,zs({stateFilter:t}),Jg({state:t}))}function cY(e){const t=Qw.includes(e)?e:"default";t!==ls.sort&&(Wg=!0,zs({sort:t}),Jg({sort:t}))}function uY(e){Wg=!0,zs({search:e}),Jg({search:e})}function pp(e){zs({provider:String(e??"").trim()||"all"}),Jg({provider:ls.provider}),tx()}async function dY(e){const t=Wt().wbCustomProvidersUi;if(!t?.remove){Nr(r("删除入口未就绪,请重试或重启应用"),"err");return}await t.remove(e)&&await sx({force:!0})}function fY(){Wt().wbAccountAddForms?.openNewCustomForm?.()}function A2(e){zs({mapping:e})}function pY(){zs({mapping:null})}function mY(){const e=Uu(),t=as(e);zs({customModel:{provider:t||e!=="all"&&e!==lp?e:"",locked:t}})}function hY(){zs({customModel:null})}function R2(e,t){zs({capability:{provider:e,id:t}})}function gY(){zs({capability:null})}function O2(e,t){return up().find(a=>(a.provider||"")===e&&zo(a.id,t))||null}function c0(e){if(as(e)){const t=_o(e)?.name;return typeof t=="string"&&t||e}return r(Wt().wbProviders?.labelOf?.(e)||e)}function M2(){const e=Uu(),t=as(e),a=t?_o(e)?.name||e:r("内置提供商");Wt().wbModelsFetchModal?.open({providerId:e===lp?"":e,custom:t,name:a,onDone:()=>ec(),onRefreshed:()=>{sx({force:!0})}})}window.wbModelsPanel={render:ec,load:sx,refreshAll:T2,refreshModels:M2,visibleColumns:C2,selectProvider:pp,builtinProviders:JK,providerRefreshedAt:eY};function u0(e,t,a){return N2(e,t,a)}function xY(e){a0=e}function bY(){const e=a0;if(!e)return;const t=o=>Object.keys(o).some(c=>c.startsWith("__reactFiber$")||c.startsWith("__reactInternalInstance$"));for(const o of[...e.children])o.tagName==="TBODY"?o.id!=="models"&&o.remove():o.tagName==="TR"&&!t(o)&&o.remove();const a=e.querySelector("tbody#models");if(a)for(const o of[...a.children])t(o)||o.remove()}const vY=e=>[{value:"inherit",label:e},{value:"on",label:r("支持")},{value:"off",label:r("不支持")}];function yY(e){const t=Kw(e);return r(t==="on"?"支持":t==="off"?"不支持":"未声明")}function D2(e,t,a,o,c=""){const d=t!=null,f=np.includes(e)?sp(t):yY(t);return a?o?r("已填写:对下游声明 {value}",{value:f}):r("已覆盖:对下游声明 {value}",{value:f}):o?r("未填写(下游按未声明处理)"):d?c==="modelsdev"?r("models.dev 补齐:对下游声明 {value}",{value:f}):r("继承上游:{value}",{value:f}):r("上游未声明(下游会按不支持处理)")}function jY(e,t,a){return a?zu.filter(o=>{const c=e[o];return c!=null}):t}function wY(e,t){const a={};for(const o of zu){const c=t.includes(o),d=e[o];np.includes(o)?a[o]=c&&typeof d=="number"?String(d):"":a[o]=c?d===!0?"on":"off":"inherit"}return a}function SY({context:e,onClose:t}){const a=as(e.provider),o=O2(e.provider,e.id),c=IK(o),d=Gw(o),f=jY(d,qw(o?.capOverrides),a),[p,h]=x.useState(()=>wY(d,f)),[b,y]=x.useState(""),[v,j]=x.useState(!1);if(!o)return s.jsx(Yt,{open:!0,onOpenChange:E=>{E||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("模型能力")})}),s.jsx(Lt,{children:s.jsx("p",{className:"text-sm leading-[1.7] text-subtle",children:r("这一行已不在当前清单里(模型被移除、或目录刷新后上游不再提供它)。关闭后刷新列表再试。")})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")})]})]})});const w=o.id,S=o.providerLabel||c0(e.provider),N=r(a?"未声明":"继承上游"),k=r(a?"清除":"恢复继承");function A(E){const D=d[E];return P(E)?"":a?r("未填写"):typeof D=="number"?r("继承上游 {value}",{value:sp(D)}):r("上游未声明")}function P(E){return f.includes(E)}function R(E,D){h(I=>({...I,[E]:D}))}async function C(){if(!v){for(const E of np){const D=p[E].trim();if(D&&$w(E,D)===null){y(r("{label}要填 1 ~ 1 亿之间的整数(留空 = {inherit})",{label:Bu[E],inherit:N}));return}}j(!0),y(r("保存中…"));try{tc(await aY(e.provider,e.id,LK(p))),t(),Nr(r("✅ 已保存 {id} 的能力位({provider})",{id:w,provider:S}))}catch(E){y(r("保存失败:{message}",{message:Lo(E)})),j(!1)}}}return s.jsx(Yt,{open:!0,onOpenChange:(E,D)=>{if(!E){if(v){D.cancel();return}t()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("模型能力")})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"rounded-md border border-border bg-surface-inset px-3 py-2.5 font-mono text-[12px] text-subtle",children:[s.jsx("b",{className:"text-primary-fg",children:o.id}),r("({provider})",{provider:S})]}),np.map(E=>s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-[7px]",children:[s.jsx(Je,{htmlFor:`cap-${E}`,children:Bu[E]}),P(E)?s.jsx(ne,{variant:"ghost",size:"2xs",disabled:v,title:r(a?"清除这一项(回到未声明)":"清除覆盖,回到上游声明值"),onClick:()=>R(E,""),children:k}):null]}),s.jsx(Fe,{id:`cap-${E}`,inputMode:"numeric",autoComplete:"off",spellCheck:!1,placeholder:A(E),disabled:v,value:p[E],onChange:D=>R(E,D.currentTarget.value),onKeyDown:D=>{D.key==="Enter"&&(D.preventDefault(),C())}}),s.jsx("p",{className:"text-xs leading-[1.6] text-subtle",children:D2(E,d[E]??null,P(E),a,Hu(o,E))})]},E)),e2.map(E=>s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{children:Bu[E]}),s.jsx(En,{options:vY(N),value:p[E],"aria-label":Bu[E],className:"self-start",onValueChange:D=>R(E,String(D))}),s.jsx("p",{className:"text-xs leading-[1.6] text-subtle",children:D2(E,d[E]??null,P(E),a,Hu(o,E))})]},E)),c?s.jsxs("div",{className:"rounded-md border border-border bg-surface-inset px-3 py-2.5 text-xs leading-[1.7] text-subtle",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-x-2 gap-y-1",children:[s.jsx("span",{children:r("可配思考档位")}),s.jsx("span",{className:"font-mono text-[12px] text-primary-fg",children:c.levels.join(" / ")}),c.defaultLevel?s.jsxs("span",{children:[r("(默认 "),s.jsx("span",{className:"font-mono text-[12px] text-primary-fg",children:c.defaultLevel}),r(")")]}):null]}),s.jsx("div",{className:"mt-1",children:r("这是模型自己能配的档位(来自上游目录),只读;要改某一档请到映射弹窗里选。")})]}):null,s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("这几项是给"),s.jsx("b",{children:r("下游客户端")}),r("看的能力声明("),s.jsx("code",{children:"/v1/models"}),r(" 里的 "),s.jsx("code",{children:"max_input_tokens"})," / ",s.jsx("code",{children:"supports_*"}),r(" 与 "),s.jsx("code",{children:"input_modalities"}),r("),下游按它们决定发不发图片、按多大的窗口堆历史。"),s.jsx("b",{children:r("不影响网关的转发与路由")}),r("。上游清单给的值不准时,在这里改;"),r(a?"这家的清单是你自己登记的,不填的项下游按未声明处理。":"「恢复继承」会把这一项交还给上游清单的值。")]}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:b})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:v,onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:v,onClick:()=>{C()},children:r("保存")})]})]})})}function mp(){return window}const NY="你好",I2=4e3,kY=[{value:"chat_completions",label:"OpenAI - Chat Completions"},{value:"responses",label:"OpenAI - Responses"},{value:"anthropic",label:"Anthropic - Messages"}],CY={chat_completions:"Chat Completions",responses:"Responses",anthropic:"Anthropic Messages"},TY="direct",EY={remote:r("远程目录"),builtin:r("内置清单"),manual:r("手动登记")},AY=[{test:e=>e===429,hint:r("该账号对这个模型正在限额冷却,等一会儿自己会好;也可以先测别的账号。")},{test:e=>e===401||e===403,hint:r("上游拒绝了这条登录态:重新登录一次,或把这条账号删掉。")},{test:e=>e===404,hint:r("上游不认识这个模型名:先点「获取模型」刷新清单,或核对默认绑定指向的上游模型。")},{test:e=>e===504,hint:r("上游没在预算内给完回答。可以只勾一个账号再测一次,看是普遍慢还是某一个账号慢。")},{test:e=>e>=500,hint:r("多半是上游自己的问题,过一会儿再试。同一个错误出现在所有账号上时,先查模型目录与映射。")}];function P2(){return mp().wbApp?.getState?.()?.accounts?.accounts||[]}function _2(e){return P2().filter(t=>(t.provider||pu)===e&&t.available!==!1&&t.enabled!==!1).sort(Wh)}function L2(e){const t=String(e.email||"").trim();return t&&cr(e.provider).emailAsName?t:hu(e)||t||r("未命名账号")}function RY(){const e=globalThis.crypto?.randomUUID?.();if(e)return e;const t=a=>Array.from({length:a},()=>Math.floor(Math.random()*16).toString(16)).join("");return`${t(8)}-${t(4)}-4${t(3)}-a${t(3)}-${t(12)}`}function d0(e){const t=Number(e);return!Number.isFinite(t)||t<=0?"—":t<1e3?`${Math.round(t)} ms`:`${(t/1e3).toFixed(t<1e4?2:1)} s`}function OY(e,t){return _2(e).length?"":r("该提供商没有可用账号(要在账号页启用一个、且凭证完整),一行都发不出去")}function z2({children:e,plain:t=!1}){return s.jsxs("p",{className:t?"flex items-center gap-2 text-xs leading-[1.6] text-subtle":"flex gap-2 rounded-md border border-border bg-surface-2 px-3 py-2.5 text-xs leading-[1.65] text-subtle",children:[s.jsx("span",{"aria-hidden":"true",className:t?"size-4 flex-none rounded-full border border-border-strong text-center text-[10px] leading-[14px]":"mt-px size-4 flex-none rounded-full border border-border-strong text-center text-[10px] leading-[14px]",children:"i"}),s.jsx("span",{children:e})]})}function MY({open:e,label:t,text:a,onToggle:o}){return s.jsxs("div",{className:"overflow-hidden rounded-sm border border-border",children:[s.jsxs(ne,{variant:"ghost",size:"xs",className:"w-full","aria-expanded":e,onClick:o,children:[s.jsx("span",{className:"truncate",children:t}),s.jsx("span",{"aria-hidden":"true",className:"ml-auto text-[10px]",children:e?"▴":"▾"})]}),e?s.jsx("div",{className:"border-t border-hairline bg-surface px-2.5 py-2",children:s.jsx("pre",{className:"whitespace-pre-wrap font-mono text-[11.5px] leading-[1.65] text-subtle",children:a})}):null]})}function DY(e){const[t,a]=x.useState(()=>Date.now());return x.useEffect(()=>{if(!e)return;a(Date.now());const o=window.setInterval(()=>a(Date.now()),400);return()=>window.clearInterval(o)},[e]),t}function B2(e){if(e.transport||!e.result||e.result.error)return!1;const t=Number(e.result.status)||0;return t>=200&&t<300}function IY({target:e,onClose:t}){const a=e.provider,o=O2(a,e.id),c=_2(a),d=vj(P2()),[f,p]=x.useState(""),[h,b]=x.useState(NY),[y,v]=x.useState("chat_completions"),[j,w]=x.useState(""),[S,N]=x.useState(null),[k,A]=x.useState(""),[P,R]=x.useState(""),[C,E]=x.useState(!0),[D,I]=x.useState(()=>{const te=c.find(ke=>!Cf(ke,e.id))||c[0];return te?[te.id]:[]}),[O,_]=x.useState([]),[z,H]=x.useState(()=>new Set),B=x.useRef(0),L=x.useRef([]);L.current=O;const F=O.some(te=>te.state==="running"),$=DY(F);x.useEffect(()=>{let te=!0;return(async()=>{try{const ke=mp().workbuddyDesktop?.getProxyPool;if(typeof ke!="function")throw new Error(r("当前环境不支持代理池"));const le=await ke();if(!te)return;if(!le||typeof le!="object"||!Array.isArray(le.items))throw new Error(r("代理池响应异常"));N(le.items),A("")}catch(ke){if(!te)return;N([]),A(Lo(ke))}})(),()=>{te=!1}},[]);const X=x.useCallback((te=!1)=>{const ke=L.current.filter(le=>le.state==="running");B.current+=1;for(const le of ke)mp().workbuddyDesktop?.terminateStatsRequest?.(le.testId)?.catch(()=>{});_([]),ke.length&&!te&&Nr(r("已中止在途测试({n} 个账号)",{n:ke.length}))},[]);x.useEffect(()=>()=>{X(!0)},[X]);async function K(te,ke){const le={provider:a,model:e.id,account_id:te.accountId,prompt:h.trim(),system_prompt:f.trim(),reasoning:P,stream:C,protocol:y,...j?{proxy:j}:{},test_id:te.testId},de=Se=>{B.current===ke&&_(Te=>Te.map(_e=>_e.testId===te.testId?{..._e,...Se}:_e))};try{const Se=await mp().workbuddyDesktop?.testModel(le);if(!Se){de({state:"done",transport:r("桥接调用返回空(本机网关没有响应这次测试)")});return}de({state:"done",result:Se})}catch(Se){de({state:"done",transport:Lo(Se)})}}function q(){const te=c.filter(Se=>D.includes(Se.id));if(!te.length){Nr(r("至少选一个测试账号"),"err");return}const ke=B.current+1;B.current=ke;const le=Date.now(),de=te.map(Se=>({accountId:Se.id,label:L2(Se),position:d.get(Se.id)?.position||0,testId:RY(),startedAt:le,state:"running"}));H(new Set),_(de);for(const Se of de)K(Se,ke)}function Q(){F?X():_([])}const G=s.jsx("span",{className:"ml-2 font-mono text-[12px] font-normal text-subtle",children:e.id});if(!o)return s.jsx(Yt,{open:!0,onOpenChange:te=>{te||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("测试模型")})}),s.jsx(Lt,{children:s.jsx("p",{className:"text-sm leading-[1.7] text-subtle",children:r("这一行已不在当前清单里(模型被移除、或目录刷新后上游不再提供它)。关闭后刷新列表再试。")})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")})]})]})});const J=Fu(o).find(te=>te.isDefault)?.enabled===!1,Y=u0(o.id,o.id,a),re=Fu(o).filter(te=>!te.isDefault).map(te=>te.alias),M=ap(op().data,o).filter(te=>te!=="off"&&te!=="none"),U=J?r("跟随映射(该行未启用,本次不注入)"):Y?r("跟随映射(当前 {level})",{level:Y}):r("跟随映射(未绑定等级)"),Z=[r("以模型本名直发"),re.length?r("另有 {n} 条别名映射({aliases}),别名不参与本次",{n:re.length,aliases:re.join(r("、"))}):"",J?r("该行当前未启用:测试照常按本名直发(「先测通、再决定要不要启用」正是这颗按钮的用法),但本行的思考等级绑定不参与本次,生产路由也要等绑定打开后才会放行"):Y?r("映射上绑定的思考等级是 {level},「跟随映射」按它注入",{level:Y}):r("映射上未绑定思考等级,「跟随映射」等于这次不注入")].filter(Boolean).join(r(";"))+r("。"),ae=mp().wbProviders?.PROTOCOL_OPTIONS||kY,ce=ae.find(te=>te.value===y)?.label||y,W=[{value:"",label:r("跟随账号配置")},{value:TY,label:r("直连(不使用代理)")},...(S??[]).map(te=>({value:`${Qa}${te.id}`,label:du(te)}))];S===null?W.push({value:"__hint_pool__",label:r("正在读取代理列表…"),disabled:!0}):S.length||W.push({value:"__hint_pool__",label:r(k?"代理列表读取失败":"还没有代理(去「网络代理」页添加)"),disabled:!0});const ue=W.find(te=>te.value===j)?.label||r("跟随账号配置"),ve=c.map(te=>({value:te.id,label:`#${d.get(te.id)?.position||0} ${L2(te)}`+(Cf(te,e.id)?r(" · 限额中"):"")}));function ee(te){const ke=(Ae,oe)=>s.jsxs("div",{className:"flex items-center gap-2.5 border-b border-hairline px-3 py-2",children:[Ae,s.jsx("b",{className:"min-w-0 truncate text-[12.5px] text-foreground",title:te.label,children:te.label}),te.position?s.jsxs("span",{className:"flex-none text-xs text-subtle",children:["#",te.position]}):null,s.jsx("span",{className:"ml-auto flex-none font-mono text-[11.5px] tabular-nums text-subtle",children:oe})]},"head");if(te.state==="running"){const Ae=($-te.startedAt)/1e3;return s.jsxs("div",{className:"flex items-center gap-2.5 rounded-md border border-border bg-surface-2 px-3 py-2.5 text-xs text-subtle",children:[s.jsx(of,{className:"flex-none"}),s.jsxs("span",{className:"min-w-0 truncate",children:[r("账号 "),s.jsx("b",{className:"text-foreground",children:te.label}),r(" 已发出,等待上游首帧…")]}),s.jsx("span",{className:"ml-auto flex-none font-mono tabular-nums",children:r("已等待 {seconds}s",{seconds:Ae.toFixed(1)})})]},te.testId)}const le=te.result;if(!B2(te)){const Ae=Number(le?.status)||0,oe=AY.find(me=>me.test(Ae))?.hint??(te.transport?r("确认桌面端还在运行,再重试一次。"):"");return s.jsxs("div",{className:"rounded-md border border-border bg-surface-2",children:[ke(s.jsx(ze,{shape:"tag",variant:"destructive",className:"flex-none",children:Ae||r("失败")}),r("用时 {time}",{time:d0(le?.duration_ms)})),s.jsxs("div",{className:"flex flex-col gap-1.5 px-3 py-2.5",children:[s.jsxs("div",{className:"text-[12.5px] leading-[1.7]",children:[te.transport?s.jsxs(s.Fragment,{children:[s.jsx("b",{className:"text-destructive",children:r("本机网关没有返回结论")}),r(":"),te.transport]}):s.jsxs(s.Fragment,{children:[s.jsx("b",{className:"text-destructive",children:r("测试未通过")}),r(":"),le?.error||r("上游没有给出可读的错误说明")]}),Number(le?.attempts)>1?r("(中间共尝试 {n} 次)",{n:Number(le?.attempts)}):""]}),oe?s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:oe}):null]})]},te.testId)}const de=String(le?.reply??""),Se=String(le?.reasoning??""),Te=`think-${te.testId}`,_e=[le?.upstream_model&&le.upstream_model!==e.id?r("上游 {model}",{model:le.upstream_model}):"",le?.upstream_reasoning?r("思考等级 {level}",{level:le.upstream_reasoning}):"",le?.protocol&&le.protocol!=="chat_completions"?CY[le.protocol]||le.protocol:"",le?.proxy?r("节点 {proxy}",{proxy:le.proxy}):"",Number(le?.attempts)>1?r("尝试 {n} 次",{n:Number(le?.attempts)}):""].filter(Boolean).join(" · ");return s.jsxs("div",{className:"rounded-md border border-border bg-surface-2",children:[ke(s.jsx(ze,{shape:"tag",variant:"success",className:"flex-none",children:Number(le?.status)||200}),r("用时 {time} · 首字 {ttfb}",{time:d0(le?.duration_ms),ttfb:d0(le?.ttfb_ms)})),s.jsxs("div",{className:"flex flex-col gap-2 px-3 py-2.5",children:[s.jsxs("div",{className:"flex items-center gap-2 text-[11.5px] text-subtle",children:[s.jsx("span",{className:"flex-none",children:r("回复")}),_e?s.jsx("span",{className:"min-w-0 truncate",title:_e,children:_e}):null,s.jsx(ne,{variant:"ghost",size:"2xs",className:"ml-auto flex-none","data-copy":de,children:r("复制")})]}),s.jsx("div",{className:"max-h-[220px] overflow-y-auto whitespace-pre-wrap rounded-sm border border-border bg-surface px-3 py-2 text-[12.5px] leading-[1.7]",children:de||s.jsx("span",{className:"text-subtle",children:r("(上游这一次返回了空正文)")})}),Se?s.jsx(MY,{open:z.has(Te),label:r("思考过程({n} 字)",{n:Se.length}),text:Se,onToggle:()=>H(Ae=>{const oe=new Set(Ae);return oe.has(Te)?oe.delete(Te):oe.add(Te),oe})}):null]})]},te.testId)}function he(){if(F){const ke=O.length-O.filter(le=>le.state==="running").length;return s.jsxs(s.Fragment,{children:[O.length>1?s.jsxs("p",{className:"text-xs text-subtle",children:[r("正在测 "),s.jsx("b",{className:"text-foreground",children:O.length}),r(" 个账号"),ke?s.jsxs(s.Fragment,{children:[r(",已完成 "),s.jsx("b",{className:"text-foreground",children:ke})]}):null,r("。")]}):null,O.map(le=>ee(le))]})}const te=O.filter(B2).length;return s.jsxs(s.Fragment,{children:[O.length>1?s.jsxs("p",{className:"text-xs text-subtle",children:[s.jsx("b",{className:te?"text-success":"text-foreground",children:te}),r(" 成功 ·"),s.jsxs("b",{className:O.length-te?"text-destructive":"text-foreground",children:[" ",O.length-te]}),r(" 失败")]}):null,O.map(ke=>ee(ke)),te===0?s.jsxs(z2,{children:[r("两边原因不一样时各自处理。如果"),s.jsx("b",{className:"text-foreground",children:r("同一条错误出现在所有账号上")}),r(",通常就不是账号问题了:先确认这个模型还在上游目录里(「获取模型」刷一次),再看默认绑定指向的上游模型对不对。")]}):null]})}return s.jsx(Yt,{open:!0,onOpenChange:te=>{te||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsxs(Ut,{children:[r("测试模型"),G]})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"flex items-center gap-2 rounded-md border border-border bg-surface-inset px-3 py-2.5",children:[s.jsx("span",{className:"min-w-0 flex-1 truncate font-mono text-[12.5px] font-semibold text-primary-fg",title:o.id,children:o.id}),s.jsx(ze,{shape:"tag",variant:"brand",children:c0(a)}),s.jsx(ze,{shape:"tag",variant:"outline",children:as(a)?r("自定义家"):EY[o.source]||r("来源未知")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("本次测试的发送口径")}),children:"?"}),s.jsx(Fi,{children:Z})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-system",children:r("系统提示词")}),s.jsx(Mi,{id:"model-test-system",rows:2,maxLength:I2,placeholder:r("留空则不携带;设置页的提示词模式照常生效"),value:f,onChange:te=>p(te.currentTarget.value)})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-prompt",children:r("用户提示词")}),s.jsx(Mi,{id:"model-test-prompt",rows:2,maxLength:I2,placeholder:r("留空用默认问候「你好」"),value:h,onChange:te=>b(te.currentTarget.value)})]}),s.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-protocol",children:r("对话协议")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("对话协议的说明")}),children:"?"}),s.jsx(Fi,{children:r("按所选网关对话协议组装请求并校验响应转换(Chat Completions / Responses / Anthropic Messages)。")})]})]}),s.jsxs(ut,{value:y,onValueChange:te=>v(String(te)),children:[s.jsx(ft,{id:"model-test-protocol",className:"w-full",children:s.jsx(dt,{className:"min-w-0 truncate",children:ce})}),s.jsx(pt,{children:ae.map(te=>s.jsx($e,{value:te.value,children:te.label},te.value))})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-proxy",children:r("测试节点")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("测试节点的说明")}),children:"?"}),s.jsx(Fi,{children:r("仅本次测试临时生效,不修改账号保存的代理配置。可选「网络代理」页里的节点或强制直连。")})]})]}),s.jsxs(ut,{value:j,onValueChange:te=>w(String(te)),children:[s.jsx(ft,{id:"model-test-proxy",className:"w-full",children:s.jsx(dt,{className:"min-w-0 truncate",children:ue})}),s.jsx(pt,{children:W.map(te=>s.jsx($e,{value:te.value,disabled:te.disabled,children:te.label},te.value))})]})]})]}),s.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-reasoning",children:r("思考等级")}),s.jsxs(ut,{value:P,onValueChange:te=>R(String(te)),children:[s.jsx(ft,{id:"model-test-reasoning",className:"w-full",children:s.jsx(dt,{children:P?r("{level}(本次指定)",{level:P}):U})}),s.jsxs(pt,{children:[s.jsx($e,{value:"",children:U}),M.map(te=>s.jsx($e,{value:te,children:r("{level}(本次指定)",{level:te})},te))]})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-stream",children:r("流式请求")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("流式请求的说明")}),children:"?"}),s.jsx(Fi,{children:r("默认开,与真实请求一致:可同时验证 SSE 链路与首字延迟。")})]})]}),s.jsx(ns,{id:"model-test-stream",checked:C,onCheckedChange:te=>E(!!te)})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(Je,{htmlFor:"model-test-accounts",children:r("测试账号")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("测试账号的说明")}),children:"?"}),s.jsx(Fi,{children:r("勾几个就并行测几次;默认选队列里最靠前的一个。")})]}),s.jsx(ne,{variant:"ghost",size:"xs",className:"ml-auto",disabled:!c.length||D.length===c.length,onClick:()=>I(c.map(te=>te.id)),children:r("全选({n})",{n:c.length})})]}),s.jsx(Gh,{id:"model-test-accounts",value:D,onValueChange:I,options:ve,placeholder:r("选一个账号(至少一个)"),searchPlaceholder:r("搜索账号…"),emptyHint:r("这家没有可用账号(要在账号页启用一个、且凭证完整)")})]}),s.jsx(z2,{plain:!0,children:r("真实链路 · 消耗少量额度 · 日志带「测试」标记,不计报表")})]}),s.jsxs(tn,{className:"justify-end",children:[s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")}),s.jsx(ne,{variant:"default",disabled:!D.length||!c.length,onClick:q,children:r("开始测试")})]}),s.jsx(Yt,{open:O.length>0,onOpenChange:te=>{te||Q()},children:s.jsxs(Xt,{overlayForceRender:!0,className:"w-[min(680px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsxs(Ut,{children:[r(F?"测试中…":"测试结果"),G]})}),s.jsx(Lt,{children:he()}),s.jsx(tn,{className:"justify-end",children:F?s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"mr-auto text-xs text-subtle",children:r("关闭即中止")}),s.jsx(ne,{variant:"outline",onClick:()=>X(),children:r("中止测试")}),s.jsx(ne,{variant:"default",disabled:!0,children:r("测试中…")})]}):s.jsxs(s.Fragment,{children:[s.jsx(ne,{variant:"outline",onClick:Q,children:r("关闭")}),s.jsx(ne,{variant:"default",onClick:q,children:r("再测一次")})]})})]})})]})})}const H2=[{value:"enable",label:r("启用")},{value:"disable",label:r("禁用")},{value:"reasoning",label:r("设置思考等级")},{value:"delete",label:r("删除")}];function U2(e){return e.source==="manual"||as(e.provider)}function PY(e){return(e.name&&e.name!==e.id?r("{name}({id})",{name:e.name,id:e.id}):e.id)||e.id}function _Y({models:e,onClose:t,onDone:a}){const[o,c]=x.useState("enable"),d=VK(op().data,e),[f,p]=x.useState(()=>({select:d[0]||"",custom:""})),[h,b]=x.useState(!1),[y,v]=x.useState(""),j=f.select===fa?f.custom.trim():f.select,w=e.filter(U2).length,S=H2.find(A=>A.value===o)?.label||r("操作");async function N(A){return Promise.resolve(Wt().wbConfirm?.ask?.({title:r("删除选中的模型"),html:r("确定删除选中的 {count} 个模型登记?删除后 /v1/models 不再广告它们、请求也会被拒。",{count:A})+(e.length>A?"
    "+r("另有 {n} 个非手动登记的模型将被跳过。",{n:e.length-A}):""),okText:r("删除"),okClass:"danger"})??!1)}async function k(){if(h)return;if(!e.length){Nr(r("没有选中的模型"),"err");return}if(o==="reasoning"&&f.select===fa&&!j){v(s.jsx("span",{className:"text-destructive",children:r("请填写自定义思考等级,或改选候选档 / 「清除」")}));return}if(o==="delete"){if(w===0){v(s.jsx("span",{className:"text-destructive",children:r("选中的模型都不是手动登记,无法删除(开关映射才是它们的手段)")}));return}if(!await N(w))return}b(!0),v("");let A=0,P=0,R=0,C="";for(const E of e){const D=E.provider||"";try{if(o==="delete"){if(!U2(E)){P+=1;continue}tc(await E2(D,E.id))}else if(o==="enable"||o==="disable"){const I=o==="enable";for(const O of Fu(E))tc(await rx(D,O.alias,E.id,{enabled:I}))}else for(const I of Fu(E))tc(await rx(D,I.alias,E.id,{reasoning:j}));A+=1}catch(I){R+=1,C||(C=Lo(I)),v(s.jsx("span",{className:"text-destructive",children:r("失败 {n} 个 · 首个失败:{error}",{n:R,error:C})}))}}R===0?(Nr(P?r("✅ 批量{action}完成:共 {n} 个模型(跳过不可删除的 {skipped} 个)",{action:S,n:A,skipped:P}):r("✅ 批量{action}完成:共 {n} 个模型",{action:S,n:A})),a()):(Nr(r("批量{action}完成:成功 {ok} 个,失败 {failed} 个",{action:S,ok:A,failed:R}),"err"),v(s.jsxs("span",{className:"text-destructive",children:[r("成功 {ok} 个,失败 {failed} 个",{ok:A,failed:R}),P?r(",跳过 {n} 个",{n:P}):"",C?r(";首个失败:{error}",{error:C}):""]}))),b(!1)}return s.jsx(Yt,{open:!0,onOpenChange:A=>{A||h||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("批量操作 · 已选 {n} 个模型",{n:e.length})})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("将作用于以下模型")}),s.jsx("p",{style:{maxHeight:84,overflowY:"auto"},children:e.map(PY).join(r("、"))})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("操作")}),s.jsx(Ph,{value:o,onValueChange:A=>c(A),className:"flex-row flex-wrap items-center gap-5","aria-label":r("批量动作"),children:H2.map(A=>s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(yo,{value:A.value}),A.label]},A.value))}),o==="reasoning"?s.jsxs("div",{className:"mt-2.5",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"batch-model-reasoning",children:r("思考等级")}),s.jsxs(ut,{value:f.select,onValueChange:A=>p(P=>({...P,select:String(A)})),children:[s.jsx(ft,{id:"batch-model-reasoning",className:"min-w-[220px]",children:s.jsx(dt,{children:f.select===fa?r("自定义等级…"):f.select||r("清除(不覆盖)")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"",children:r("清除(不覆盖)")}),d.map(A=>s.jsx($e,{value:A,children:A},A)),s.jsx($e,{value:fa,children:r("自定义等级…")})]})]})]}),f.select===fa?s.jsxs("div",{className:"field-row mt-2",children:[s.jsx("label",{htmlFor:"batch-model-reasoning-custom",children:r("自定义等级")}),s.jsx(Fe,{id:"batch-model-reasoning-custom",maxLength:32,value:f.custom,onChange:A=>p(P=>({...P,custom:A.currentTarget.value}))})]}):null,s.jsxs("p",{className:"detail mt-1.5",children:[r("设置 / 清除会应用到选中模型的"),s.jsx("b",{children:r("全部映射")}),r("(默认绑定与别名 chips);「清除」= 不给这些映射指定等级(选「不覆盖」的口径与映射弹窗一致)")]})]}):null,o==="delete"?s.jsx("p",{className:"detail mt-2",children:w===0?r("选中的都不是手动登记的模型,删除不可用(上游目录带回来的行由清单决定存在性)"):r("可删除 {n} 个(手动登记 / 自定义家);",{n:w})+(e.length>w?r("其余 {n} 个会被跳过。",{n:e.length-w}):"")}):null]}),s.jsx("div",{className:"detail",style:{minHeight:18},children:y})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:h,onClick:t,children:r("关闭")}),s.jsx(ne,{variant:o==="delete"?"destructive":"default",disabled:h,onClick:()=>{k()},children:h?r("执行中…"):r("执行{action}",{action:S})})]})]})})}function rr(){return window}const V2={intl:"fm-table-intl",custom:"fm-table-custom"},F2={intl:"fetch-models",custom:"fetch-models-custom"},f0=["provider","source","state","count","note","updated","op"],p0=["pick","model","state"],LY={provider:"w-[13%]",source:"w-[21%]",state:"w-[9%]",count:"w-[6%]",note:"w-[20%]",updated:"w-[16%]",op:"w-[15%]"},zY={pick:"w-[8%]",model:"w-[74%]",state:"w-[18%]"},BY={pick:"",provider:r("提供商"),source:r("模型来源"),state:r("状态"),count:r("模型数"),note:r("说明"),updated:r("更新日期"),model:r("上游模型"),op:r("操作")},HY={refreshed:{variant:"brand",label:r("已刷新")},failed:{variant:"destructive",label:r("失败")},skipped:{variant:"outline",label:r("跳过")}},$2=new Set(["cline-free","cline-pass"]),q2="workbuddy-desktop-fetch-model-source";function hp(e){return String(e??"").trim().toLowerCase()}function m0(e,t){rr().wbApp?.toast?.(e,t)}function h0(e){return e instanceof Error?e.message:String(e)}function G2(e){const t=rr().formatTime??rr().wbApp?.formatTime;return String(t?.(e)??"")}function K2(){return rr().wbApp?.getState?.()?.accounts?.accounts||[]}function UY(e){const a=(rr().wbProviders?.customList?.()||[]).find(o=>o.id===e)?.models;return new Set((Array.isArray(a)?a:[]).map(o=>hp(o?.id)).filter(Boolean))}function Y2(e){if(e?.nameCustom===!0&&e?.name)return e.name;const t=String(e?.email||"").trim();return rr().wbAccountsModel?.providerFeatures?.(e?.provider)?.emailAsName&&t?t:String(e?.nickname||e?.name||t||e?.id||"").trim()||r("未命名账号")}function VY(e){if($2.has(e))return[];const t=rr().wbAccountsModel?.byPriorityOrder,a=K2().filter(o=>(o?.provider||"workbuddy")===e&&o?.available!==!1&&o?.enabled!==!1);return t?a.sort(t):a}function X2(){const e=new Set(rr().wbModelsPanel?.builtinProviders?.()||[]);for(const t of K2())t?.available===!1||t?.enabled===!1||e.add(t?.provider||"workbuddy");return[...e]}function FY(){const e=new Set(X2());return(rr().wbProviders?.all?.()||[]).filter(t=>e.has(t?.id??""))}function $Y(e){return G2(Number(e.refreshedAt)||0)||"—"}function qY(e){return HY[String(e.status)]??{variant:"outline",label:String(e.status||r("未知"))}}function GY(){try{const e=JSON.parse(localStorage.getItem(q2)||"{}");if(!e||typeof e!="object")return{};const t={};for(const[a,o]of Object.entries(e))typeof o=="string"&&o&&(t[a]=o);return t}catch{return{}}}function KY(e){rr().wbFilterMemory?.save?.(q2,e)}function YY({options:e,onClose:t}){const a=e.providerId,o=!!e.custom,c=e.name||a,{onDone:d,onRefreshed:f}=e,[p,h]=x.useState("idle"),[b,y]=x.useState(""),[v,j]=x.useState(""),[w,S]=x.useState(null),[N,k]=x.useState(""),A=w!==null,[P,R]=x.useState(!1),[C,E]=x.useState([]),[D,I]=x.useState(()=>new Set),[O,_]=x.useState(()=>new Set),[z,H]=x.useState([]),[B,L]=x.useState(""),[F,$]=x.useState(GY);x.useEffect(()=>{rr().wbTableColumns?.repaint?.(o?F2.custom:F2.intl)},[o]);const X=o?[]:FY(),K=o?[]:J(),q=B.trim().toLowerCase(),Q=C.filter(oe=>!q||oe.toLowerCase().includes(q)),G=o?P?r("已选 {picked} 个 · 上游共 {upstream} 个 · 清单已有 {managed} 个",{picked:O.size,upstream:C.length,managed:D.size}):r("尚未获取"):Y(K);function J(){const oe=new Map(z.map(Ce=>[String(Ce.provider||""),Ce])),me=X.map(Ce=>{const Ne=String(Ce.id||"");return{provider:Ne,label:String(Ce.label||Ne),item:oe.get(Ne)}}),pe=new Set(me.map(Ce=>Ce.provider));for(const Ce of z){const Ne=String(Ce.provider||"");pe.has(Ne)||me.push({provider:Ne,label:String(Ce.providerLabel||Ne),item:Ce})}return me}function Y(oe){if(p==="loading")return r("正在刷新…");if(p==="error")return"";const me=oe.map(Ne=>Ne.item).filter(Ne=>!!Ne);if(!me.length)return P?r("刷新完成,但没有得到任何结果"):oe.length?r("共 {n} 家 · 点「获取模型」开始",{n:oe.length}):r("0 家");const pe=me.filter(Ne=>Ne.status==="refreshed").length,Ce=me.filter(Ne=>Ne.status==="failed").length;return Ce?r("{total} 家 · 成功 {done} · 失败 {failed}",{total:oe.length,done:pe,failed:Ce}):r("{total} 家 · 成功 {done}",{total:oe.length,done:pe})}function re(oe,me){const pe=VY(oe);if(!pe.length)return{list:pe,selected:""};const Ce=String(F[oe]||""),Ne=String(me||""),be=De=>pe.some(Ge=>String(Ge.id)===De);return{list:pe,selected:be(Ce)?Ce:be(Ne)?Ne:String(pe[0].id)}}function M(oe){const me={};for(const[pe,Ce]of Object.entries(F))Ce&&(me[pe]=Ce);for(const pe of oe){const{selected:Ce}=re(pe.provider,pe.reported);Ce&&(me[pe.provider]=Ce)}return me}const U=K.map(oe=>({provider:oe.provider,reported:oe.item?.accountId}));function Z(oe,me){$(pe=>({...pe,[oe]:me})),KY({[oe]:me})}async function ae(){if(!A){S("load"),j(""),y(""),h("loading");try{if(o){const me=await rr().wbProviders?.customRequest?.("POST","/api/custom-providers/fetch-models",{providerId:a}),pe=new Set,Ce=(Array.isArray(me?.models)?me.models:[]).map(be=>String(be??"").trim()).filter(be=>{const De=hp(be);return!be||pe.has(De)?!1:(pe.add(De),!0)}),Ne=UY(a);E(Ce),I(Ne),_(new Set(Ce.filter(be=>!Ne.has(hp(be))))),R(!0),h("ready");return}const oe=await rr().workbuddyDesktop?.refreshModels({accounts:M(U),providers:X2()});H(Array.isArray(oe?.results)?oe.results:[]),R(!0),h("ready"),Number(oe?.refreshed)>0&&f?.()}catch(oe){const me=h0(oe);y(me),h("error"),j(me)}finally{S(null)}}}async function ce(oe){if(!(A||!oe.provider)){S("row"),k(oe.provider),j("");try{const me=await rr().workbuddyDesktop?.refreshModels({accounts:M([{provider:oe.provider,reported:oe.item?.accountId}]),providers:[oe.provider]});H(pe=>W(pe,Array.isArray(me?.results)?me.results:[])),R(!0),h("ready"),Number(me?.refreshed)>0&&f?.()}catch(me){const pe=h0(me);j(pe),m0(r("获取失败:{message}",{message:pe}),"err")}finally{S(null),k("")}}}function W(oe,me){const pe=new Map(me.map(be=>[String(be.provider||""),be])),Ce=oe.map(be=>pe.get(String(be.provider||""))??be),Ne=new Set(Ce.map(be=>String(be.provider||"")));for(const be of me)Ne.has(String(be.provider||""))||Ce.push(be);return Ce}async function ue(){if(!o||A||!O.size)return;const oe=[...O];S("import"),j("");try{const me=Number(await rr().wbModelsCustom?.addModels?.(a,oe))||0;m0(r("✅ 已导入 {added} 个模型({skipped} 个已存在,跳过)",{added:me,skipped:oe.length-me})),S(null),t(),d?.()}catch(me){const pe=h0(me);m0(r("导入失败:{message}",{message:pe}),"err"),j(pe),S(null)}}function ve(){A||t()}function ee(){const oe=new Set(O);for(const me of C)D.has(hp(me))||oe.add(me);_(oe)}function he(oe){return s.jsx(Cl,{children:s.jsx(Tn,{colSpan:o?p0.length:f0.length,className:"py-[26px] text-center text-muted-foreground",children:oe})})}function te(oe){return s.jsx("span",{className:"font-mono text-[11.5px] tabular-nums text-muted-foreground",children:oe})}function ke(oe){return s.jsx("div",{className:"truncate font-mono text-[12px] font-semibold",children:oe})}function le(oe,me){const{list:pe,selected:Ce}=re(oe,me);if(!pe.length){const be=$2.has(oe)?r("这家的模型清单是全局的,不跟账号走"):r("这家还没有可用账号,刷新会使用默认登录态");return s.jsx("span",{className:"text-[11.5px] text-muted-foreground",title:be,children:"—"})}const Ne=pe.find(be=>String(be.id)===Ce);return s.jsxs(ut,{value:Ce,onValueChange:be=>Z(oe,String(be)),children:[s.jsx(ft,{className:"w-full",title:r("用哪个账号去拉这家的模型清单"),"aria-label":r("模型来源"),children:s.jsx(dt,{children:Ne?Y2(Ne):"—"})}),s.jsx(pt,{children:pe.map(be=>s.jsx($e,{value:String(be.id),children:Y2(be)},String(be.id)))})]})}function de(oe,me){_(pe=>{const Ce=new Set(pe);return me?Ce.add(oe):Ce.delete(oe),Ce})}function Se(oe,me,pe){if(pe||oe.target?.closest('[data-slot="checkbox"], input[type="checkbox"]'))return;const Ne=window.getSelection();Ne&&!Ne.isCollapsed&&oe.currentTarget.contains(Ne.anchorNode)||de(me,!O.has(me))}function Te(){return p==="idle"?he(r("点右侧「获取模型」从上游拉取这家的模型清单")):p==="loading"?he(r("正在获取…")):p==="error"?he(r("获取失败:{message}",{message:b})):Q.length?Q.map(oe=>{const me=D.has(hp(oe));return s.jsxs(Cl,{className:me?"opacity-50":"cursor-pointer",onClick:pe=>Se(pe,oe,me),children:[s.jsx(Tn,{children:s.jsx(Pr,{checked:O.has(oe),disabled:me,"aria-label":oe,onCheckedChange:pe=>de(oe,!!pe)})}),s.jsx(Tn,{children:ke(oe)}),s.jsx(Tn,{children:me?s.jsx(ze,{variant:"brand",title:r("这个模型已经在这家的清单里,不重复导入"),children:r("已添加")}):s.jsx(ze,{variant:"outline",title:r("勾上它,导入后即进入这家的清单"),children:r("未添加")})})]},oe)}):he(C.length?r("没有匹配「{keyword}」的模型",{keyword:q}):r("上游没有返回任何模型"))}function _e(oe){const me=w==="row"&&N===oe.provider;return s.jsx(ne,{variant:"outline",size:"sm",className:"w-full",disabled:A,title:r("只刷新这一家的模型清单"),onClick:()=>{ce(oe)},children:me?r("获取中…"):oe.item?r("重新获取"):r("获取")})}function Ae(){return p==="loading"?he(r("正在获取…")):p==="error"?he(r("获取失败:{message}",{message:b})):K.length?K.map(oe=>{const me=oe.item;if(!me){const be=G2(Number(rr().wbModelsPanel?.providerRefreshedAt?.(oe.provider))||0);return s.jsxs(Cl,{children:[s.jsx(Tn,{children:ke(oe.label)}),s.jsx(Tn,{children:le(oe.provider)}),s.jsx(Tn,{children:s.jsx(ze,{variant:"outline",children:r("待获取")})}),s.jsx(Tn,{children:te("—")}),s.jsx(Tn,{children:te("—")}),s.jsx(Tn,{children:te(be||"—")}),s.jsx(Tn,{children:_e(oe)})]},oe.provider)}const pe=qY(me),Ce=Number(me.count),Ne=me.status==="refreshed"?r("远程目录已更新,「来源」列会显示为「远程」"):me.message||(me.fixed?r("这家用固定模型清单,无可刷新"):r("本次没有取到新内容"));return s.jsxs(Cl,{children:[s.jsx(Tn,{children:ke(oe.label)}),s.jsx(Tn,{children:le(oe.provider,me.accountId)}),s.jsx(Tn,{children:s.jsx(ze,{variant:pe.variant,children:pe.label})}),s.jsx(Tn,{children:te(Ce?r("{n} 个",{n:Ce}):"—")}),s.jsx(Tn,{children:s.jsx("span",{className:"text-[11.5px] leading-[1.5] text-muted-foreground",children:Ne})}),s.jsx(Tn,{children:te($Y(me))}),s.jsx(Tn,{children:_e(oe)})]},oe.provider)}):he(r("还没有可刷新的提供商:先在账号页添加一个账号"))}return s.jsx(Yt,{open:!0,onOpenChange:(oe,me)=>{if(!oe){if(A){me.cancel();return}t()}},children:s.jsxs(Xt,{className:o?"w-[min(607px,calc(100vw-48px))]":"w-[min(1012px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("获取模型 — {name}",{name:c})})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx("span",{className:"text-[11.5px] text-muted-foreground",children:G}),o&&s.jsxs(Di,{className:"w-[240px] flex-none",children:[s.jsx(Pi,{type:"search",placeholder:r("搜索模型 ID…"),autoComplete:"off",value:B,onChange:oe=>L(oe.currentTarget.value)}),s.jsx(Ii,{"aria-hidden":"true",children:"⌕"})]}),s.jsx("div",{className:"mr-auto"}),o&&s.jsxs(s.Fragment,{children:[s.jsx(ne,{variant:"ghost",size:"sm",onClick:ee,children:r("全选未添加")}),s.jsx(ne,{variant:"ghost",size:"sm",onClick:()=>_(new Set),children:r("清空")})]}),s.jsx(ne,{variant:"outline",size:"sm",title:r("刷新全部家(逐家打上游)"),disabled:A,onClick:()=>{ae()},children:r(w==="load"?"获取中…":P?"重新获取":"获取模型")})]}),s.jsxs(Zy,{id:o?V2.custom:V2.intl,className:"table-fixed",containerClassName:"max-h-[min(48vh,460px)]",children:[s.jsx("colgroup",{children:(o?p0:f0).map(oe=>s.jsx("col",{"data-col":oe,className:o?zY[oe]:LY[oe]},oe))}),s.jsx(AE,{children:s.jsx(Cl,{children:(o?p0:f0).map(oe=>s.jsx(RE,{"data-col":oe,children:BY[oe]},oe))})}),s.jsx(Wy,{className:"[&_tr:last-child>td]:border-b-0",children:o?Te():Ae()})]})]}),s.jsxs(tn,{children:[s.jsx("span",{className:"min-w-0 text-[11.5px] text-muted-foreground",children:v}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:ve,children:r(o?"取消":"完成")}),o&&s.jsx(ne,{variant:"default",disabled:!O.size||A,onClick:()=>{ue()},children:w==="import"?r("导入中…"):O.size?r("导入选中的 {n} 个模型",{n:O.size}):r("导入")})]})]})})}let gp=null,$u=null;function Q2(){gp&&(gp.unmount(),gp=null),$u&&($u.remove(),$u=null)}function XY(e){e?.providerId&&(Q2(),$u=document.createElement("div"),document.body.append($u),gp=jn.createRoot($u),gp.render(s.jsx(YY,{options:e,onClose:Q2})))}window.wbModelsFetchModal={open:XY};const Bo=(e,t)=>t?`${e} ta-${t}`:e;function Z2(e,t){const a=(t||"").trim();if(a)return up().find(o=>zo(o.provider,e)&&zo(o.id,a))}const QY="[.pv-row:hover_&_[data-slot=nav-item-count]]:invisible";function ZY(e){const t=/x\s*([\d.]+)/i.exec(String(e||""));return t?`${t[1]}x`:String(e||"")}function W2(e){const t=/x\s*([\d.]+)/i.exec(String(e||""));if(!t)return null;const a=Number(t[1]);return Number.isFinite(a)?a:null}const WY={workbuddy:250,"workbuddy-intl":295,raccoon:60,catpaw:85,autoclaw:250,"autoclaw-intl":295,qoder:330,"qoder-intl":350,"cline-free":200,"cline-pass":200,codearts:210,loomy:155,kuku:15,accio:320,"accio-intl":335,trae:170,zcode:285};function JY(e){const t=WY[e];if(t!==void 0)return t;let a=0;for(let o=0;o>>0;return a%360}function eX(e){const t=String(e||"").trim();if(!t)return"?";const a=t.match(/[A-Za-z]/);return(a?a[0]:t[t.length-1]).toUpperCase()}const tX=e=>({"--av-h":String(JY(e))}),g0=s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3.5",y:"3.5",width:"7",height:"7",rx:"1.5"}),s.jsx("rect",{x:"13.5",y:"3.5",width:"7",height:"7",rx:"1.5"}),s.jsx("rect",{x:"13.5",y:"13.5",width:"7",height:"7",rx:"1.5"}),s.jsx("rect",{x:"3.5",y:"13.5",width:"7",height:"7",rx:"1.5"})]})});function nX(e){if(!e)return"";const t=Wt().wbPresetProviders?.list;if(!Array.isArray(t))return"";const a=t.find(o=>o.name===e);return a&&Wt().wbPresetProviders?.iconOf?.(String(a.key||""))||""}function sX(e,t){return as(e)?nX(t):kg[e==="workbuddy-intl"?"workbuddy":e]||""}function qu(e,t,a){const o=a?"":sX(e,t),c=e==="all"||e==="custom-all";return s.jsx("span",{className:Ue("pv-ico",c&&"mute",o&&"img"),style:o?void 0:tX(e),"aria-hidden":"true",children:o?s.jsx("img",{src:o,alt:""}):a??eX(t)})}const rX={supportsToolCall:s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsx("path",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"})}),supportsImages:s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2.5"}),s.jsx("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),s.jsx("path",{d:"M21 15l-5-5L5 21"})]})}),supportsVideo:s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"9"}),s.jsx("path",{d:"M10 8.5l6 3.5-6 3.5z"})]})}),supportsReasoning:s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"}),s.jsx("path",{d:"M9 18h6M10 22h4"})]})})};function aX(e,t,a,o){return o==="enabled"&&!fp(e)||o==="disabled"&&fp(e)||o==="mapped"&&!(e.aliases||[]).length||a!=="all"&&(e.provider||"")!==a?!1:t?[e.id,e.name,...e.aliases||[]].join(" ").toLowerCase().includes(t):!0}function lX(){const e=x.useSyncExternalStore(XK,op),t=ex(e),a=as(t)||t==="custom-all",[o,c]=x.useState(null),[d,f]=x.useState(!1),[p,h]=x.useState(new Set),b=a&&!Vu()&&e0()&&!_o(t);x.useEffect(()=>{nY(),tx(),j2(),Wt().wbApp?.currentPage==="gateway"&&T2().then(()=>Wt().wbProviders?.refreshCustom?.()).then(()=>{ec()})},[]),x.useEffect(()=>{bY()});const y=n0(),v=Array.isArray(y.models)?y.models:[],j=e.search.trim().toLowerCase(),w=v.filter(J=>aX(J,j,t,e.stateFilter)),S=e.sort,N=C2(),k=N.length,A=t==="all"?r("全部"):t==="custom-all"?r("自定义 · 全部"):a?String(_o(t)?.name||t):s0().get(t)?.label||c0(t),P=v.filter(fp).length,R=v.filter(J=>(J.aliases||[]).length>0).length,C=hg(w.length,"models"),E=v.filter(J=>p.has(nc(J))),D=(J,Y)=>{const re=new Set(p);Y?re.add(J):re.delete(J),h(re)},I=w.map(nc),O=I.length>0&&I.every(J=>p.has(J)),_=I.some(J=>p.has(J)),z=s.jsx(Pr,{checked:O,indeterminate:!O&&_,disabled:!I.length,"aria-label":r("全选当前筛选结果"),title:r("全选当前筛选出的模型(跨分页);再点取消"),onCheckedChange:J=>{const Y=new Set(p);for(const re of I)J===!0?Y.add(re):Y.delete(re);h(Y)}});function H(){const J=s0(),Y=Wi(),re=WK(),M=[...J.values()].reduce((ce,W)=>ce+W.n,0),U=r("全部({n} 家)",{n:J.size}),Z=[...re.values()].reduce((ce,W)=>ce+W.n,0),ae=r("全部({n} 家)",{n:[...re.values()].filter(ce=>ce.n>0).length});return s.jsxs("aside",{className:"prov-rail",id:"prov-rail","aria-label":r("按提供商选择"),children:[s.jsxs("div",{className:"rail-scroll",children:[s.jsx("div",{className:"rail-label",children:r("内置提供商")}),s.jsx(uu,{active:t==="all","data-provider":"all",title:U,count:M,icon:qu("all","",g0),className:"shadow-none",onClick:()=>pp("all"),children:U}),[...J].map(([ce,W])=>s.jsx(uu,{active:t===ce,"data-provider":ce,title:W.label,count:W.n,icon:qu(ce,W.label),className:"shadow-none",onClick:()=>pp(ce),children:W.label},ce)),s.jsx("div",{className:"rail-label",children:r("自定义提供商")}),Y.length?[...Z>0?[s.jsx(uu,{active:Vu(),"data-provider":"custom-all",title:ae,count:Z,icon:qu("custom-all","",g0),className:"shadow-none",onClick:()=>pp("custom-all"),children:ae},"custom-all")]:[],...Y.map(ce=>{const W=String(ce.id||""),ue=String(ce.name||W);return s.jsxs("div",{className:"pv-row",children:[s.jsx(uu,{active:t===W,"data-provider":W,title:ue,count:re.get(W)?.n??0,icon:qu(W,ue),className:Ue("shadow-none",QY),onClick:()=>pp(W),children:ue}),s.jsx("button",{type:"button",className:"pv-del","aria-label":r("删除自定义提供商"),title:r("删除这个自定义提供商(连同名下账号)"),onClick:()=>{dY(W)},children:"×"})]},W)})]:s.jsx("div",{className:"rail-empty",children:r("还没有自定义提供商")})]}),s.jsx("div",{className:"rail-foot",children:s.jsx(uu,{variant:"add",id:"rail-add-custom",title:r("新建一个自定义提供商(同时创建它的第一个账号)"),onClick:()=>fY(),children:r("+ 新建自定义提供商")})})]})}function B(J,Y,re,M){const U=u0(J,Y,re);return s.jsx(ne,{variant:U?"secondary":"dashed",size:"2xs",disabled:M,className:"font-mono font-bold shadow-none",title:U?r("思考等级 {level}(点击修改)",{level:U}):r("设置思考等级(当前未绑定)"),onClick:()=>A2({alias:J,target:Y,provider:re}),children:U||r("+等级")})}function L(J){const Y=J.provider||"",re=Fu(J),[M,...U]=re;async function Z(ce){await Wt().wbConfirm?.ask?.({title:r("删除映射"),html:r("确定删除映射「{alias} → {target}」?",{alias:Yw(ce),target:Yw(J.id)}),okText:r("删除"),okClass:"danger"})&&o0(i0(ce,J.id,Y),()=>sY(Y,ce,J.id),r("映射已删除"))}const ae=ce=>{const W=ce.alias,ue=ce.enabled!==!1,ve=e.pending.has(i0(W,J.id,Y));return s.jsxs("span",{className:Ue("alias",!ue&&"map-off"),children:[s.jsx(ns,{size:"sm",checked:ue,disabled:ve,title:r(ue?"映射已启用,点击关闭":"映射已关闭,点击启用"),"aria-label":r("{action}映射 {alias}",{action:r(ue?"关闭":"启用"),alias:W}),onCheckedChange:ee=>{o0(i0(W,J.id,Y),()=>rx(Y,W,J.id,{enabled:ee}),r(ee?"映射已启用":"映射已关闭"))}}),s.jsx("span",{className:"t","data-copy":W,title:r("点击复制:{name}",{name:W}),children:W}),ce.isDefault?s.jsx("span",{className:"binding-default",children:r("默认")}):null,B(W,J.id,Y,ve),ce.isDefault?null:s.jsx(ne,{variant:"ghost",size:"icon-2xs",className:"text-[12px] leading-none",disabled:ve,title:r("删除映射 {alias}",{alias:W}),onClick:()=>{Z(W)},children:"×"})]},`${W}${ce.isDefault?"d":"m"}`)};return s.jsxs("div",{className:"aliases",children:[s.jsxs("div",{className:"alias-row",children:[M?ae(M):null,s.jsx(ne,{variant:"dashed",size:"xs",onClick:()=>A2({target:J.id,provider:Y}),children:r("+ 映射")})]}),U.map(ae)]})}function F(J){if(J.source==="manual")return s.jsxs("span",{className:"src manual",title:r("手动登记的上游模型;移除它会直接删掉这条登记"),children:[s.jsx("i",{"aria-hidden":"true"}),r("手动")]});if(!J.source&&as(J.provider))return s.jsxs("span",{className:"src manual",title:r("用户登记的自定义模型;整份清单只属于这一家"),children:[s.jsx("i",{"aria-hidden":"true"}),r("自定义")]});if(J.source!=="remote"&&J.source!=="builtin")return s.jsx("span",{className:"rate",children:"—"});const Y=J.source==="remote",re=$K(Number(J.refreshedAt)||0),M=Y?re?r("来自上游目录接口,清单拉取于 {at};刷新失败时保留上一份成功结果",{at:re}):r("来自上游目录接口;刷新失败时保留上一份成功结果"):r("上游目录尚未拉到,用的是内置静态清单;点「刷新模型清单」可重试");return s.jsxs("span",{className:Ue("src",Y?"remote":"builtin"),title:M,children:[s.jsx("i",{"aria-hidden":"true"}),r(Y?"远程":"内置")]})}function $(J){const Y=Gw(J),re=qw(J.capOverrides),M=typeof Y.maxInputTokens=="number"?Y.maxInputTokens:null,U=typeof Y.maxOutputTokens=="number"?Y.maxOutputTokens:null,Z=r("上下文窗口 {input} / 最大输出 Token {output} —— 点击修改模型能力",{input:sp(M),output:sp(U)})+X(J);return s.jsxs("button",{type:"button",className:"caps-open",title:Z,onClick:()=>R2(J.provider||"",J.id),children:[s.jsxs("span",{className:Ue("cap-num",M===null&&"unset",Hu(J,"maxInputTokens")==="modelsdev"&&"filled"),children:[n2(M),re.includes("maxInputTokens")?s.jsx("i",{className:"cap-mark",title:r("已覆盖上游值")}):null]}),s.jsx("span",{className:"cap-sep",children:"/"}),s.jsxs("span",{className:Ue("cap-num",U===null&&"unset",Hu(J,"maxOutputTokens")==="modelsdev"&&"filled"),children:[n2(U),re.includes("maxOutputTokens")?s.jsx("i",{className:"cap-mark",title:r("已覆盖上游值")}):null]})]})}function X(J){const Y=["maxInputTokens","maxOutputTokens"].filter(re=>Hu(J,re)==="modelsdev").map(re=>Bu[re]);return Y.length?r(";其中 {keys} 由 models.dev 补齐",{keys:Y.join(r("、"))}):""}function K(J){const Y=Gw(J),re=qw(J.capOverrides);return s.jsx("button",{type:"button",className:"caps-open caps-badges",title:r("对下游声明的能力(工具调用 / 图片识别 / 视频识别 / 支持思考)—— 点击修改"),onClick:()=>R2(J.provider||"",J.id),children:e2.map(M=>{const U=Y[M]??null,Z=Kw(U),ae=re.includes(M),ce=Hu(J,M);return s.jsxs("span",{className:Ue("cap-dot",Z,ce==="modelsdev"&&"filled",ae&&"marked"),title:PK(M,U,ae,ce),children:[rX[M],ae?s.jsx("i",{className:"cap-mark"}):null]},M)})})}function q(J,Y,re){async function M(){await Wt().wbConfirm?.ask?.({title:r("移除自定义模型"),html:r("确定移除自定义模型「{id}」?这条登记会被直接移除,之后 /v1/models 不再广告它、请求它也会被拒。",{id:Yw(Y.id)}),okText:r("移除"),okClass:"danger"})&&o0(nc(Y),()=>E2(Y.provider||"",Y.id),as(Y.provider||"")?r("模型已移除"):r("自定义模型已移除"))}switch(J.key){case"check":return s.jsx("td",{className:Bo("cell-check",J.align),children:s.jsx(Pr,{checked:p.has(nc(Y)),title:r("勾选后可批量操作"),"aria-label":r("勾选后可批量操作"),onCheckedChange:U=>D(nc(Y),U===!0)})});case"model":return s.jsxs("td",{className:Bo("cell-model",J.align),children:[s.jsx("div",{className:"mid",children:s.jsx("span",{className:"t","data-copy":Y.id,title:r("点击复制:{name}",{name:Y.id}),children:Y.id})}),Y.name&&Y.name!==Y.id?s.jsx("div",{className:"mname",children:Y.name}):null]});case"rate":return s.jsx("td",{className:Bo("cell-rate",J.align),children:s.jsx("span",{className:"rate",children:Y.credits?ZY(Y.credits):"—"})});case"source":return s.jsx("td",{className:Bo("cell-source",J.align),children:F(Y)});case"budget":return s.jsx("td",{className:Bo("cell-budget",J.align),children:$(Y)});case"caps":return s.jsx("td",{className:Bo("cell-caps",J.align),children:K(Y)});case"alias":return s.jsx("td",{className:Bo("cell-alias",J.align),children:L(Y)});case"act":{const U=OY(Y.provider||""),Z=Y.source==="manual"||as(Y.provider||"");return s.jsx("td",{className:Bo("cell-act r",J.align),children:s.jsxs("div",{className:"row-actions",children:[s.jsx(ne,{variant:"ghost",size:"sm",disabled:!!U,title:U||r("以这个上游模型发一次最小请求,走真实转发链路"),onClick:()=>c({provider:Y.provider||"",id:Y.id}),children:r("测试")}),Z?s.jsx(ne,{variant:"ghost",size:"sm",className:"text-destructive",disabled:re,onClick:()=>{M()},children:r("移除")}):null]})})}default:return null}}function Q(J){const Y=e.pending.has(nc(J)),re=p.has(nc(J));return s.jsx("tr",{className:Ue(re&&"sel"),children:N.map(M=>s.jsx(x.Fragment,{children:q(M,J,Y)},M.key))},`${J.provider||""}${J.id}`)}function G(){if(!v.length){const Z=a?e0()?Vu()?r("自定义提供商还没有模型:先在左栏选一家,点「添加模型」登记,或「获取上游模型」从上游拉取"):r(b?"该提供商已不存在(可能已被删除),请刷新列表":"这家还没有模型:点「添加模型」登记,或「获取上游模型」从上游拉取"):r("加载中…"):e.data?r("暂无模型(请先添加账号)"):r("加载中…");return s.jsx("tr",{children:s.jsx("td",{colSpan:k,className:"empty",children:Z})})}if(!w.length)return s.jsx("tr",{children:s.jsx("td",{colSpan:k,className:"empty",children:j?r("没有匹配「{keyword}」的模型",{keyword:j}):r("没有匹配当前筛选的模型")})});const J=t==="all"||Vu(),Y=J&&!j&&e.stateFilter==="all"&&!C.paged,re=new Map;for(const Z of w){const ae=Z.provider||"";re.has(ae)||re.set(ae,{label:Z.providerLabel||ae||r("未知"),items:[]}),re.get(ae)?.items.push(Z)}const M=[];let U=0;for(const[Z,ae]of re){ae.items.sort((te,ke)=>{const le=+!fp(te)-+!fp(ke);if(le!==0||S==="default")return le;const de=W2(te.credits),Se=W2(ke.credits);return de===null||Se===null?de===Se?0:de===null?1:-1:S==="rate-asc"?de-Se:Se-de});const ce=e.expanded.has(Z)||!Y,W=ce?ae.items:ae.items.slice(0,h2),ue=ae.items.length-W.length,ve=C.paged?Math.max(0,C.rangeStart-1-U):0,ee=C.paged?Math.min(W.length,C.rangeEnd-U):W.length,he=ve0?r("(续)"):"",r("{n} 个模型",{n:ae.items.length})]})},`group:${Z}`));for(const te of he)M.push(Q(te));U+=W.length,ue>0?M.push(s.jsx("tr",{className:"tr-more",children:s.jsx("td",{colSpan:k,children:s.jsx(ne,{variant:"ghost",size:"sm",onClick:()=>lY(Z),children:r("展开其余 {n} 个模型 ▾",{n:ue})})})},`more:${Z}`)):ce&&Y&&ae.items.length>h2&&M.push(s.jsx("tr",{className:"tr-more",children:s.jsx("td",{colSpan:k,children:s.jsx(ne,{variant:"ghost",size:"sm",onClick:()=>oY(Z),children:r("收起 ▴")})})},`collapse:${Z}`))}return M}return s.jsxs(s.Fragment,{children:[s.jsx("section",{className:"panel",children:s.jsxs("div",{className:"mm",children:[H(),s.jsxs("div",{className:"mm-main",children:[s.jsxs("div",{className:"panel-head",children:[s.jsxs("div",{className:"mm-titlebar",children:[s.jsxs("div",{className:"mm-title",children:[t==="all"||t==="custom-all"?qu(t,"",g0):qu(t,A),s.jsx("h2",{children:A}),s.jsxs("span",{className:"mm-meta",children:[s.jsx("b",{children:v.length}),r(" 个模型 · 已启用 "),s.jsx("b",{children:P}),r(" · 有映射 "),s.jsx("b",{children:R})]})]}),s.jsxs("div",{className:"head-actions",children:[s.jsx(ne,{id:"btn-refresh-models",title:as(t)?r("从这一家的上游拉一份模型清单,勾选要哪些再导入(已添加的不会重复导入)"):r("刷新模型管理页里各提供商的远程模型目录,逐家结果列在弹窗里"),onClick:()=>M2(),children:r("获取模型")}),s.jsx(ne,{id:"btn-add-custom-model",variant:"outline",size:"sm",onClick:()=>mY(),children:r("+ 添加模型")})]})]}),s.jsxs("div",{className:"mm-filters",children:[s.jsx(En,{options:GK,value:e.stateFilter,onValueChange:iY,"aria-label":r("按状态筛选"),className:"shrink-0"}),s.jsx(En,{options:YK,value:e.sort,onValueChange:cY,"aria-label":r("按倍率排序"),className:"shrink-0"}),s.jsxs(Di,{className:"w-full min-[768px]:w-[240px] flex-none min-[768px]:flex-none",id:"models-search",children:[s.jsx(Pi,{type:"search",placeholder:r("搜索模型 ID / 名称 / 映射名…"),"aria-label":r("搜索模型"),autoComplete:"off",value:e.search,onChange:J=>uY(J.currentTarget.value)}),s.jsx(Ii,{"aria-hidden":"true",children:"⌕"})]}),E.length>0?s.jsxs("span",{className:"batch-chip",children:[r("已选 "),s.jsx("b",{children:E.length}),r(" 个"),s.jsx(ne,{id:"btn-batch-models",variant:"outline",size:"xs",title:r("对选中的 {n} 个模型执行批量操作",{n:E.length}),onClick:()=>f(!0),children:r("批量操作")})]}):null]})]}),s.jsx("div",{className:"models-table-wrap",children:s.jsxs("table",{className:"models-table",ref:J=>xY(J),children:[s.jsxs("colgroup",{children:[s.jsx("col",{className:"c-check","data-col":"check"}),s.jsx("col",{className:"c-model","data-col":"model"}),s.jsx("col",{className:"c-rate","data-col":"rate"}),s.jsx("col",{className:"c-source","data-col":"source"}),s.jsx("col",{className:"c-budget","data-col":"budget"}),s.jsx("col",{className:"c-caps","data-col":"caps"}),s.jsx("col",{className:"c-alias","data-col":"alias"}),s.jsx("col",{className:"c-act","data-col":"act"})]}),s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{"data-col":"check",children:z}),s.jsx("th",{"data-col":"model",children:r("上游模型")}),s.jsx("th",{"data-col":"rate",children:r("倍率")}),s.jsx("th",{"data-col":"source",children:r("来源")}),s.jsxs("th",{"data-col":"budget",children:[r("上下文 / 输出"),s.jsx("span",{className:"th-help","aria-hidden":"true",title:r("数字带虚线底 = 由 models.dev 补齐;右上角小点 = 你手动覆盖过;— = 未声明。点任意一格可改。"),children:s.jsx("svg",{viewBox:"0 0 24 24",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"9"}),s.jsx("path",{d:"M12 16v-4"}),s.jsx("path",{d:"M12 8h.01"})]})})})]}),s.jsxs("th",{"data-col":"caps",children:[r("能力"),s.jsx("span",{className:"th-help","aria-hidden":"true",title:r("圆点带内侧描边 = 由 models.dev 补齐;右上角小点 = 你手动覆盖过;虚线圈 = 未声明。悬停某一枚可看逐项出处。"),children:s.jsx("svg",{viewBox:"0 0 24 24",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"9"}),s.jsx("path",{d:"M12 16v-4"}),s.jsx("path",{d:"M12 8h.01"})]})})})]}),s.jsxs("th",{"data-col":"alias",children:[r("模型映射"),s.jsx("span",{className:"th-help","aria-hidden":"true",title:r("每条映射 = 对外名 → 上游模型;原始 ID 与别名有独立开关,默认绑定永远存在(没有映射时是合成的那条)。"),children:s.jsx("svg",{viewBox:"0 0 24 24",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"9"}),s.jsx("path",{d:"M12 16v-4"}),s.jsx("path",{d:"M12 8h.01"})]})})})]}),s.jsx("th",{className:"r","data-col":"act",children:r("操作")})]})}),s.jsx("tbody",{id:"models",children:G()})]})}),s.jsx($i,{className:"models-panel-foot",leading:Vu()?s.jsxs(s.Fragment,{children:[r("这里是"),s.jsx("b",{children:r("全部自定义提供商")}),r("的模型合集:每家的清单互相独立,别名也只在自己那家内生效;要改名称 / 协议 / Base URL,到账号页该家账号的「设置」→ 提供商一栏。")]}):a?s.jsxs(s.Fragment,{children:[r("自定义提供商的清单"),s.jsx("b",{children:r("只属于这一家")}),r(":这里的模型不会出现在其他家,别名也只在这一家内生效。改名称 / 协议 / Base URL 在账号页该家账号的「设置」→ 提供商一栏;整家不要了,鼠标移到左栏这家上点 × 删除(连同名下账号)。")]}):void 0,total:w.length,range:C.paged?{start:C.rangeStart,end:C.rangeEnd}:null,page:C.page,pageCount:C.pageCount,size:C.size,onSizeChange:C.setSize,onPageChange:C.goto})]})]})}),e.mapping?s.jsx(iX,{context:e.mapping,onClose:pY}):null,e.customModel?s.jsx(cX,{initial:e.customModel,onClose:hY}):null,e.capability?s.jsx(SY,{context:e.capability,onClose:gY}):null,o?s.jsx(IY,{target:o,onClose:()=>c(null)}):null,d?s.jsx(_Y,{models:E,onClose:()=>f(!1),onDone:()=>{h(new Set),f(!1)}}):null]})}const oX=r("绑定在「对外名 → 上游模型」这一条映射上的思考等级(列表照抄 OmniProxy 的手动绑定),选「不覆盖」表示不给这条映射指定等级。它会跟着这条映射注入转发,由承载的那家翻译成自己的档位字段(CatPaw 归并成 low/high/max,Qoder 按模型声明的档位归一)。以下几种情况故意不注入:① off / none(关闭思考)—— 本项目没有安全的表达方式;② 表外的自定义等级(各家能力范围不同,无法判断上游收不收);③ 客户端请求体里已经自己指定了档位(那是更明确的意图,绑定不覆盖);④ 这家上游不认识档位字段(如 WorkBuddy / 小浣熊 / AutoClaw / Cline)。注入与跳过都会写进详细日志。");function J2(e,t,a){const o=k2(e),c=(t||"").trim(),d=o.find(f=>f.id.toLowerCase()===c.toLowerCase());return d?d.id:c||o[0]?.id||""}function iX({context:e,onClose:t}){const a=!!e.alias,[o,c]=x.useState(()=>e.provider||r0()[0]?.id||""),[d,f]=x.useState(e.alias||""),[p,h]=x.useState(()=>J2(o,e.target)),[b,y]=x.useState(""),[v,j]=x.useState(!1),[w,S]=x.useState(()=>{const _=ap(op().data,Z2(o,p)),z=a?u0(e.alias,e.target,e.provider):"";return z&&_.includes(z)?{select:z,custom:""}:{select:z?fa:"",custom:z}}),N=ap(op().data,Z2(o,p)),k=(()=>{const _=r0();for(const z of[e.provider,o])z&&!_.some(H=>H.id===z)&&_.push({id:z,label:r(Wt().wbProviders?.labelOf?.(z)||z)});return _})(),A=(()=>{const _=k2(o),z=(p||"").trim();return z&&!_.some(H=>H.id.toLowerCase()===z.toLowerCase())&&_.unshift({id:z,label:r("{name}(不在该家当前清单里)",{name:z}),off:!0}),_})(),P=k.find(_=>_.id===o)?.label||o||r("(全局)"),R=w.select&&w.select!==fa&&!N.includes(w.select)?{select:fa,custom:w.custom||w.select}:w,C=R.select===fa?R.custom.trim():R.select,E=R.select===fa;function D(_){c(_),h(J2(_,p))}async function I(){if(v)return;const _=a?e.alias||"":d.trim(),z=p;if(!_){y(r("请填写对外映射名"));return}if(!z){y(r("该提供商当前没有可选的上游模型"));return}if(!o){y(r("请选择提供商"));return}if(!a&&zo(_,z)&&up().some(H=>zo(H.id,z)&&zo(H.provider,o))){y(r("原始 ID 已作为默认绑定,请直接使用该绑定的开关或等级按钮"));return}j(!0),y(r("保存中…"));try{tc(await rx(o,_,z,{reasoning:C})),j(!1),t();const H=C?r(" · 思考等级 {level}",{level:C}):"",B=r(Wt().wbProviders?.labelOf?.(o)||o);Nr(a?r("✅ 已更新 {name} 的思考等级",{name:_}):r("✅ 已添加映射 {name} → {target}({label}){suffix}",{name:_,target:z,label:B,suffix:H}))}catch(H){y(r("保存失败:{message}",{message:Lo(H)})),j(!1)}}const O=_=>{_.key==="Enter"&&(_.preventDefault(),I())};return s.jsx(Yt,{open:!0,onOpenChange:(_,z)=>{if(!_){if(v){z.cancel();return}t()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r(a?"设置思考等级":"添加模型映射")})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"mapping-provider",children:r("提供商")}),s.jsxs(ut,{value:o,disabled:!0,onValueChange:_=>D(String(_)),children:[s.jsx(ft,{id:"mapping-provider",className:"w-full",children:s.jsx(dt,{children:k.find(_=>_.id===o)?.label||o})}),s.jsx(pt,{children:k.map(_=>s.jsx($e,{value:_.id,children:_.label},_.id))})]})]}),s.jsxs("div",{className:"grid grid-cols-[1fr_24px_1fr] items-end gap-2.5",children:[s.jsxs("div",{className:"flex min-w-0 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"mapping-alias",children:r("对外映射名(下游请求时用)")}),s.jsx(Fe,{id:"mapping-alias",maxLength:128,placeholder:r("例如 gpt-4o"),autoComplete:"off",autoFocus:!a,value:d,disabled:a,onChange:_=>f(_.currentTarget.value),onKeyDown:O})]}),s.jsx("div",{className:"pb-2 text-center text-muted-foreground",children:"→"}),s.jsxs("div",{className:"flex min-w-0 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"mapping-upstream",children:r("转发到上游模型")}),s.jsxs(ut,{value:p,disabled:!0,onValueChange:_=>h(String(_)),children:[s.jsx(ft,{id:"mapping-upstream",className:"w-full",children:s.jsx(dt,{children:A.find(_=>_.id===p)?.label||p})}),s.jsx(pt,{children:A.map(_=>s.jsxs($e,{value:_.id,children:[_.label,_.off?r("(已禁用)"):""]},_.id))})]})]})]}),s.jsxs("div",{className:"rounded-md border border-border bg-surface-inset px-3 py-2.5 font-mono text-[12px] text-subtle",children:[r("下游请求 "),s.jsx("b",{className:"text-primary-fg",children:d.trim()||r("<对外名>")}),r(" → 转发")," ",s.jsx("b",{className:"text-primary-fg",children:p||r("<上游模型>")}),r("({label})",{label:P}),C?s.jsxs(s.Fragment,{children:[r(" · 思考等级 "),s.jsx("b",{className:"text-primary-fg",children:C})]}):null]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-[7px]",children:[s.jsx(Je,{htmlFor:"mapping-reasoning",children:r("思考等级")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("思考等级的注入规则")}),children:"?"}),s.jsx(Fi,{children:oX})]})]}),s.jsxs(ut,{value:R.select,onValueChange:_=>{const z=String(_);S(H=>({...H,select:z}))},children:[s.jsx(ft,{id:"mapping-reasoning",className:"w-full",autoFocus:a,children:s.jsx(dt,{children:R.select===fa?r("自定义等级…"):R.select||r("不覆盖")})}),s.jsxs(pt,{children:[s.jsx($e,{value:"",children:r("不覆盖")}),N.map(_=>s.jsx($e,{value:_,children:_},_)),s.jsx($e,{value:fa,children:r("自定义等级…")})]})]}),E?s.jsx(Fe,{id:"mapping-reasoning-custom",maxLength:32,autoFocus:!0,placeholder:r("自定义等级(例如 custom-high)"),autoComplete:"off",disabled:v,value:R.custom,onChange:_=>S(z=>({...z,custom:_.currentTarget.value})),onKeyDown:O}):null]}),s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("对外名可自由命名,允许与上游模型 ID 同名(同名时该上游的原生路由优先,映射作兜底); 支持字母、数字与 "),s.jsx("code",{children:"- _ . / :"}),r("。同一对外名可在多个提供商各添加一条: 下游用同一个名字请求,网关按账号优先级主备切换,失败自动落到下一个提供商。")]}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:b})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:v,onClick:()=>{I()},children:r(a?"保存等级":"保存映射")})]})]})})}function cX({initial:e,onClose:t}){const[a,o]=x.useState(e.provider),[c,d]=x.useState(""),[f,p]=x.useState(""),[h,b]=x.useState(!1),y=(()=>{const N=tY();return a&&!N.some(k=>k.id===a)&&N.push({id:a,label:r(Wt().wbProviders?.labelOf?.(a)||a)}),N})(),v=y.some(N=>N.id===a)?a:y[0]?.id||"",j=y.find(N=>N.id===v)?.label||v||r("(未选)");async function w(){if(h)return;const N=c.trim();if(!v){p(r("请选择提供商"));return}if(!N){p(r("请填写上游模型 ID"));return}b(!0),p(r("保存中…"));try{const k=await rY(v,N);tc(k),b(!1),t();const A=y.find(P=>P.id===v)?.label||v;if(as(Uu()))Nr(r("✅ 已登记模型 {name}({label})",{name:N,label:A}));else{const P=k;Array.isArray(P?.models)&&P.models.some(C=>C.id===N&&(C.provider||"")===v)?Nr(r("✅ 已登记自定义模型 {name}({label})",{name:N,label:A})):Nr(r("✅ 已登记 {name}({label}),但该提供商还没有可用账号,这一行要加上账号后才会显示",{name:N,label:A}),"err")}}catch(k){p(r("保存失败:{message}",{message:Lo(k)})),b(!1)}}const S=N=>{N.key==="Enter"&&(N.preventDefault(),w())};return s.jsx(Yt,{open:!0,onOpenChange:(N,k)=>{if(!N){if(h){k.cancel();return}t()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("添加自定义模型")})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"custom-model-provider",children:r("提供商")}),s.jsxs(ut,{value:v,disabled:e.locked,onValueChange:N=>o(String(N)),children:[s.jsx(ft,{id:"custom-model-provider",className:"w-full",children:s.jsx(dt,{children:j})}),s.jsx(pt,{children:y.map(N=>s.jsx($e,{value:N.id,children:N.label},N.id))})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"custom-model-id",children:r("上游模型 ID")}),s.jsx(Fe,{id:"custom-model-id",maxLength:128,placeholder:r("例如 gpt-5.5-preview"),autoComplete:"off",spellCheck:!1,autoFocus:!0,value:c,onChange:N=>d(N.currentTarget.value),onKeyDown:S})]}),s.jsxs("div",{className:"rounded-md border border-border bg-surface-inset px-3 py-2.5 font-mono text-[12px] text-subtle",children:[r("在 "),s.jsx("b",{className:"text-primary-fg",children:j}),r(" 上登记上游模型")," ",s.jsx("b",{className:"text-primary-fg",children:c.trim()||r("<上游模型 ID>")}),r("(登记后即可用这个名字请求)")]}),s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("填上游真正认识的那个模型 ID(不是给下游用的名字)。登记后它会进入该家的模型清单: 表格里出现这一行、"),s.jsx("code",{children:"/v1/models"}),r(" 会广告它、请求它也会被转发到这家。 支持字母、数字与 "),s.jsx("code",{children:"- _ . / :"}),r("。")]}),s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("「来源」列会标成"),s.jsx("b",{children:r("手动")}),r(",与远程目录 / 内置清单区分开。删除自定义模型是"),s.jsx("b",{children:r("直接移除")}),r("这条登记(不像内置模型那样只是隐藏),因为它的存在完全由这次登记决定。")]}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:f})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:h,onClick:()=>{w()},children:r("保存")})]})]})})}const eD='.page[data-page="gateway"]';let x0=null;function tD(){if(x0)return;const e=document.querySelector(eD);e&&(e.replaceChildren(),x0=jn.createRoot(e),x0.render(s.jsx(lX,{})))}document.querySelector(eD)?tD():document.addEventListener("DOMContentLoaded",tD,{once:!0});const nD=3065;function uX(){if(nl().workbuddyDesktop?.platform!=="web")return null;const e=typeof window>"u"?"":window.location?.origin;return e&&e!=="null"?e:null}function sD(e,t){return uX()??(e?`http://127.0.0.1:${e}`:t)}function nl(){return window}function ax(e){return e instanceof Error?e.message:String(e)}function Gu(e,t){nl().wbApp?.toast?.(e,t)}let xp={backend:null,gatewayBase:sD(0,`http://127.0.0.1:${nD}`)};const b0=new Set;function v0(){return xp}function dX(e){return b0.add(e),()=>{b0.delete(e)}}function fX(e){xp=e;for(const t of b0)t()}function rD(){return xp.gatewayBase.replace(/^https?:\/\//,"")}function pX(){return xp.backend?.ready===!0}function aD(e){const t=(a,o)=>{const c=document.getElementById(a);c&&(c.textContent=o)};t("api-base",`${e}/v1`),t("api-chat",`POST ${e}/v1/chat/completions`),t("api-responses",`POST ${e}/v1/responses`),t("api-messages",`POST ${e}/v1/messages`),t("api-models",`GET ${e}/v1/models`)}let y0=!1;async function Ku(){if(!y0){y0=!0;try{const e=nl().workbuddyDesktop;if(!e)throw new Error("后端桥不可用");const t=await e.getBackendStatus(),a=Number(t?.port)||0,o=v0(),c={backend:t??null,gatewayBase:sD(a,o.gatewayBase)};c.gatewayBase!==o.gatewayBase&&aD(c.gatewayBase),fX(c),nl().wbApp?.renderTopbarStatus?.()}catch(e){console.warn("读取后端状态失败:",ax(e))}finally{y0=!1}}}function mX(){aD(xp.gatewayBase),Ku()}async function lD(e){Gu(e||r("正在重启…"));try{await nl().workbuddyDesktop?.restartApp()}catch(t){Gu(r("重启失败:{reason}",{reason:ax(t)}),"err")}}const hX={idle:r("结束占用进程"),querying:r("查询中…"),ending:r("结束中…")};function gX({container:e}){const{backend:t,gatewayBase:a}=x.useSyncExternalStore(dX,v0),[o,c]=x.useState("idle"),d=t?.failure||null,f=rD(),p=t?.ready;let h="live off",b=r("正在检查… · {port}",{port:f});p===!0?(h="live pulse",b=r("网关运行中 · {port}",{port:f})):d?(h="live bad",b=r("{label} · {port}",{label:d.label||r("网关启动失败"),port:f})):p===!1&&(b=r("网关启动中… · {port}",{port:f}));const y=d?d.message??"":p===!0?r("本地网关正在监听 {url},可直接调用 OpenAI 兼容接口",{url:a}):r("正在确认网关是否已就绪");x.useEffect(()=>{Ku()},[]),x.useEffect(()=>{const j=nl().workbuddyDesktop?.onBackendError?.(()=>{Ku()});return typeof j=="function"?j:void 0},[]),x.useEffect(()=>{e.title=y},[e,y]);async function v(){if(o!=="idle")return;const j=nl().workbuddyDesktop;if(j){c("querying");try{const w=await j.getPortOccupant(),S=w?.occupant;if(!S){Gu(r("端口 {port} 上没有查到监听进程,请改用「更换端口」",{port:w?.port??""}),"err");return}const N=[r("即将结束以下进程:"),"",r("进程名:{name}",{name:String(S.name)}),r("PID:{pid}",{pid:String(S.pid)}),r("路径:{path}",{path:S.path||r("(未知)")}),"",r("结束它会强制退出该程序未保存的数据。确认继续?")],k=nl().wbConfirm?.ask;if(!k||!await k({title:r("结束占用端口的进程"),text:N.join(` -`),okText:r("结束进程"),okClass:"danger"}))return;c("ending"),(await j.endPortOccupant())?.released?(Gu(r("已结束进程 {name}(PID {pid}),端口已释放",{name:String(S.name),pid:String(S.pid)})),await k({title:r("重启程序"),text:r("端口已释放。现在重启程序让网关用这个端口启动?"),okText:r("重启")})?await lD(r("重启中…")):await Ku()):(Gu(r("进程已结束,但端口仍被占用,建议改用「更换端口」"),"err"),await Ku())}catch(w){Gu(r("结束失败:{reason}",{reason:ax(w)}),"err")}finally{c("idle")}}}return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"status-line",children:[s.jsx("span",{className:h}),s.jsx("span",{className:"txt",children:b})]}),d?.conflict?s.jsxs("div",{className:"status-actions",children:[d.canEndOccupant===!0?s.jsx(ne,{size:"sm",disabled:o!=="idle",onClick:()=>{v()},children:hX[o]}):null,s.jsx(ne,{size:"sm",onClick:()=>{vX()},children:r("更换端口")})]}):null]})}let j0=null;function oD(){if(j0)return;const e=document.getElementById("sidebar-status");e&&(e.replaceChildren(),j0=jn.createRoot(e),j0.render(s.jsx(gX,{container:e})))}const xX={idle:r("保存并重启"),checking:r("校验中…"),saving:r("保存中…")};function bX({status:e,onClose:t}){const a=Number(e?.port)||nD,[o,c]=x.useState(()=>a<65535?String(a+1):String(a-1)),[d,f]=x.useState("idle"),[p,h]=x.useState(""),[b,y]=x.useState(""),v=x.useRef(!0),j=Number(o)||0,w=e?.failure?.message||r("当前端口 {port},网关运行正常。",{port:a});async function S(){if(d!=="idle")return;const N=nl().workbuddyDesktop;if(!N)return;const k=Number(o)||0;if(!k||k<1024||k>65535){y(r("端口需在 1024-65535 之间"));return}f("checking"),y(""),h("");try{const A=await N.checkPort(k);if(!A?.ok){h(A?.message||r("该端口不可用"));return}if(A.same){h(A.message??"");return}if(f("saving"),(await N.changePort(k))?.changed===!1){h(r("与当前端口相同,无需重启"));return}t(),await lD(r("端口已改为 {port},正在重启…",{port:k}))}catch(A){y(ax(A))}finally{f("idle")}}return s.jsx(Yt,{open:!0,onOpenChange:N=>{N||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("更换网关端口")})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("当前状态")}),s.jsx("p",{children:w})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("新端口")}),s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{htmlFor:"port-input",className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("端口号")}),s.jsx(Fe,{id:"port-input",type:"number",min:1024,max:65535,step:1,placeholder:r("例如 3066"),autoComplete:"off",className:"max-w-[130px]",value:o,onChange:N=>{c(N.currentTarget.value)},onKeyDown:N=>{N.key==="Enter"&&S()},autoFocus:!0,onFocus:N=>{v.current&&(v.current=!1,N.currentTarget.select())}})]}),p?s.jsx("p",{children:p}):null,s.jsx("p",{children:r("端口需在 1024-65535 之间。1023 及以下是系统保留范围,普通程序无法监听。")})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("换端口后要改的地方")}),s.jsxs("p",{children:[r("网关地址会变成 "),s.jsx("code",{children:`http://127.0.0.1:${j||"—"}`}),r("。已经把这个地址填进其它工具(Claude Code、Cherry Studio 等)的,需要一并改成新地址,否则那些工具会连不上。")]})]}),s.jsx("p",{className:"min-h-[18px] text-[11.5px] text-muted-foreground",children:b})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:d!=="idle",onClick:()=>{S()},children:xX[d]})]})]})})}let bp=null,Yu=null;function iD(){bp&&(bp.unmount(),bp=null),Yu&&(Yu.remove(),Yu=null)}async function vX(){let e=v0().backend;e||(e=await nl().workbuddyDesktop?.getBackendStatus().catch(()=>null)??null),iD(),Yu=document.createElement("div"),document.body.append(Yu),bp=jn.createRoot(Yu),bp.render(s.jsx(bX,{status:e,onClose:iD}))}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",oD,{once:!0}):oD(),window.wbPortPanel={render:mX,sync:Ku,portLabel:rD,isReady:pX};function nn(){return window}function Es(e,t){nn().wbApp?.toast?.(e,t)}function pr(e){return e instanceof Error?e.message:String(e)}function cD(e){const t=String(e||"").trim();return/^https?:\/\//i.test(t)?t:""}async function uD(e){const t=cD(e);if(!t){Es(r("链接地址不受支持"),"err");return}try{await nn().workbuddyDesktop?.openReleasePage(t)}catch(a){Es(r("打开链接失败:{error}",{error:pr(a)}),"err")}}const lx="1127656296",yX=`assets/qq-group/${lx}.jpg`;function dD(e){return nn().wbMarkdown?.render?.(e)||""}function Xu(e){const a=e.target?.closest?.("[data-external]");a&&(e.preventDefault(),uD(a.dataset.external||""))}async function jX(){try{const e=await nn().workbuddyDesktop?.getUpdateStatus?.();e&&e.checked!==!1&&nn().wbApp?.updateUpdateBadge?.(e)}catch(e){console.warn("读取版本检查结果失败:",pr(e))}}const vp="__proxy_other__",fD={proxyChoice:null,pool:null,poolError:""};async function wX(){const e=nn().workbuddyDesktop,t={...fD};if(!e?.getUpdateProxy)return t;try{t.proxyChoice=(await e.getUpdateProxy())?.proxy??null}catch{}try{if(typeof e.getProxyPool!="function")throw new Error("桥未提供代理池方法");const a=(await e.getProxyPool())?.items;if(!Array.isArray(a))throw new Error("代理池响应异常");t.pool=a}catch(a){t.pool=[],t.poolError=pr(a)}return t}async function SX(e){if(e===vp)return null;const t=nn().workbuddyDesktop;if(!t?.setUpdateProxy)return null;const a=e===""?null:{source:"pool",proxyId:e.slice(Qa.length)};try{const o=await t.setUpdateProxy({proxy:a}),c=o?.proxy??null,d=o?.saved!==!1;return d?Es(c?r("✅ 更新出网已切换为 {label}",{label:c.label||r("指定代理")}):r("✅ 更新出网已切换为直连")):Es(r("出网线路已切换,但写入磁盘失败(重启后会恢复原线路)"),"err"),{choice:c,saved:d}}catch(o){return Es(r("保存失败:{error}",{error:pr(o)}),"err"),null}}function pD(e){const t=e.proxyChoice,a=t?.config?.source||t?.source,o=t?.label||r(a==="custom"?"自定义代理":"已设置"),c=!!t?.error,d=Array.isArray(e.pool)?e.pool:[];let f="";a==="pool"&&t?.config?.proxyId?f=`${Qa}${t.config.proxyId}`:t&&(f=vp);const p=[{value:"",label:r("直连")}];for(const h of d)p.push({value:`${Qa}${h.id}`,label:du(h)});if(e.pool===null?p.push({value:"__hint_pool__",label:r("正在读取代理列表…"),disabled:!0}):d.length||p.push({value:"__hint_pool__",label:e.poolError?r("代理列表读取失败"):r("还没有代理(去「网络代理」页添加)"),disabled:!0}),f===vp){const h=a==="clash"?r("Clash 出口:"):a==="custom"?r("自定义:"):"";p.push({value:vp,label:`${h}${o}${c?r("(不可用)"):""}`})}else a==="pool"&&!d.some(h=>`${Qa}${h.id}`===f)&&p.push({value:f,label:`${o}${c?r("(不可用)"):""}`});return{current:f,items:p,selected:p.find(h=>h.value===f),broken:c,title:c?r("当前线路不可用:{error};请重新选择代理或切回直连",{error:String(t?.error||"")}):r("检查更新与下载安装包走哪条线路(当前:{current});选择即保存。选项来自「网络代理」页;直连失败时会自动借 Clash 混合端口重试一次,选定指定代理后只走它",{current:t?o:r("直连")})}}const Ho="https://proxylane.dev/zh-cn/isp-proxies?utm_source=agent2api&utm_medium=partnership&utm_campaign=agent2api_202610&utm_content=client",NX="assets/proxylane-logo-for-light-bg.png",kX="assets/proxylane-logo-for-dark-bg.png";function mD({children:e}){return s.jsx("a",{className:"font-semibold text-primary-fg no-underline hover:underline",href:Ho,"data-external":Ho,onClick:Xu,children:e})}function CX({item:e,onClose:t}){const a=e!==null,[o,c]=x.useState(e?.name||""),[d,f]=x.useState(e?.protocol==="socks5"?"socks5":"http"),[p,h]=x.useState(e?.host||""),[b,y]=x.useState(e?.port?String(e.port):""),[v,j]=x.useState(e?.username||""),[w,S]=x.useState(e?.password||""),[N,k]=x.useState(e?e.enabled:!0),[A,P]=x.useState(!1),[R,C]=x.useState(!1),[E,D]=x.useState(null);function I(){const z=o.trim();if(!z)return{error:r("请填写代理名称")};const H=p.trim();if(!H)return{error:r("请填写代理主机地址")};const B=Number(b);return!Number.isInteger(B)||B<1||B>65535?{error:r("代理端口必须是 1-65535 的整数")}:{payload:{name:z,source:"manual",protocol:d,host:H,port:B,username:v.trim(),password:w,enabled:N}}}async function O(){if(R)return;const z=I();if("error"in z){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",z.error]}));return}const H=z.payload,B={source:"custom",protocol:H.protocol,host:H.host,port:H.port,username:H.username,password:H.password};C(!0),D(r("正在连接上游…"));try{const L=await tr().workbuddyDesktop?.testProxy?.({proxy:B});if(L?.success){const F=Uj(L.durationMs);D(s.jsxs("span",{className:"text-success",children:[r("✅ 出口可用"),L.ip?r(" 出口 IP {ip}",{ip:L.ip}):"",F?` ${F}`:""]}))}else D(s.jsxs("span",{className:"text-destructive",children:["❌ ",L?.error||r("连接失败")]}))}catch(L){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",Ra(L)]}))}finally{C(!1)}}async function _(){if(A)return;const z=I();if("error"in z){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",z.error]}));return}P(!0),D(null);try{await Mq(e,z.payload),qn(a?r("已保存「{name}」",{name:o.trim()}):r("已新增「{name}」",{name:o.trim()})),t()}catch(H){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",Ra(H)]})),P(!1)}}return s.jsx(Yt,{open:!0,onOpenChange:z=>{!z&&!A&&t()},children:s.jsxs(Xt,{className:"max-w-[560px]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r(a?"编辑代理":"新增代理")})}),s.jsxs(Lt,{className:"flex flex-col gap-3.5",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-name",children:r("名称")}),s.jsx(Fe,{id:"proxy-name",maxLength:60,autoComplete:"off",spellCheck:!1,placeholder:r("例如:香港 HTTP 出口"),value:o,onChange:z=>c(z.currentTarget.value)})]}),s.jsxs("div",{className:"flex flex-row items-end gap-2.5",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-protocol",children:r("协议")}),s.jsxs(ut,{value:d,onValueChange:z=>f(z),children:[s.jsx(ft,{id:"proxy-protocol",className:"min-w-[110px]",children:s.jsx(dt,{children:d==="socks5"?"SOCKS5":"HTTP"})}),s.jsxs(pt,{children:[s.jsx($e,{value:"http",children:"HTTP"}),s.jsx($e,{value:"socks5",children:"SOCKS5"})]})]})]}),s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-host",children:r("主机")}),s.jsx(Fe,{id:"proxy-host",placeholder:"127.0.0.1",autoComplete:"off",spellCheck:!1,value:p,onChange:z=>h(z.currentTarget.value)})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-port",children:r("端口")}),s.jsx(Fe,{id:"proxy-port",type:"number",min:1,max:65535,className:"max-w-[110px]",placeholder:"7890",value:b,onChange:z=>y(z.currentTarget.value)})]})]}),s.jsxs("div",{className:"flex flex-row items-end gap-2.5",children:[s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-user",children:r("用户名")}),s.jsx(Fe,{id:"proxy-user",placeholder:r("可选"),autoComplete:"off",value:v,onChange:z=>j(z.currentTarget.value)})]}),s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-pass",children:r("密码")}),s.jsx(Fe,{id:"proxy-pass",placeholder:r("可选"),autoComplete:"off",value:w,onChange:z=>S(z.currentTarget.value)})]})]}),s.jsxs("div",{className:"flex flex-row items-center gap-2.5",children:[s.jsx(ns,{checked:N,onCheckedChange:k,"aria-label":r("启用这条代理")}),s.jsx("span",{className:"text-[12.5px]",children:r("启用(禁用的条目不会被账号使用,被引用时账号回退直连;仍可测试)")})]}),s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("需要干净的出口?"),s.jsx(mD,{children:"ProxyLane"}),r(" AI 账号专用静态住宅 IP:Scamalytics 低欺诈评分,不限流量,首单 75 折(AGENT2API25)")," ",s.jsx(mD,{children:r("去获取")})]}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:E})]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",disabled:R||A,onClick:()=>{O()},children:r(R?"测试中…":"测试出口")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:A,onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:A,onClick:()=>{_()},children:r(A?"保存中…":"保存")})]})]})})}function TX({onClose:e}){const[t,a]=x.useState(!0),[o,c]=x.useState(!1),[d,f]=x.useState(""),[p,h]=x.useState(""),[b,y]=x.useState(""),[v,j]=x.useState({}),[w,S]=x.useState(""),[N,k]=x.useState(!1);x.useEffect(()=>{let C=!0;return(async()=>{try{const E=await fO();if(!C||E===null)return;f(String(E.listenerPortBase??"")),h(String(E.listenerPortEnd??"")),y(String(E.testUrl??"")),j(E.defaults??{}),a(!1)}catch(E){if(!C)return;S(Ra(E)),a(!1)}})(),()=>{C=!1}},[]);function A(){const C=Number(d),E=Number(p);if(!Number.isInteger(C)||C<1||C>65535||!Number.isInteger(E)||E<1||E>65535)return S(r("端口范围必须是 1-65535 的整数")),null;if(C>E)return S(r("起始端口不能大于结束端口")),null;const D=b.trim();return D&&!D.startsWith("http://")&&!D.startsWith("https://")?(S(r("测试网址要以 http:// 或 https:// 开头")),null):(S(""),{listenerPortBase:C,listenerPortEnd:E,testUrl:D})}async function P(){if(o||t)return;const C=A();if(C){c(!0);try{await Dq(C),k(!0)}catch(E){S(Ra(E))}finally{c(!1)}}}function R(){f(String(v.listenerPortBase??"")),h(String(v.listenerPortEnd??"")),y(String(v.testUrl??"")),k(!1),S("")}return s.jsx(Yt,{open:!0,onOpenChange:C=>{!C&&!o&&e()},children:s.jsxs(Xt,{className:"max-w-[560px]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("代理设置")})}),s.jsx(Lt,{className:"flex flex-col gap-3.5",children:t?s.jsx("p",{className:"text-xs text-subtle",children:r("加载中…")}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"flex flex-row items-end gap-2.5",children:[s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-settings-base",children:r("节点端口范围(起始)")}),s.jsx(Fe,{id:"proxy-settings-base",type:"number",min:1,max:65535,placeholder:String(v.listenerPortBase??""),autoComplete:"off",value:d,onChange:C=>{f(C.currentTarget.value),k(!1)}})]}),s.jsx("span",{"aria-hidden":"true",className:"flex-none pb-[7px] text-subtle",children:"—"}),s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-settings-end",children:r("节点端口范围(结束)")}),s.jsx(Fe,{id:"proxy-settings-end",type:"number",min:1,max:65535,placeholder:String(v.listenerPortEnd??""),autoComplete:"off",value:p,onChange:C=>{h(C.currentTarget.value),k(!1)}})]})]}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r("订阅节点会在本机各占一个监听端口,从该范围里挑空闲的分配;节点多的大订阅把默认范围({base}-{end})用尽时会报「没有可用的节点端口」,这时把范围调大再重启内核。已分配出去的端口不会因改范围而失效。",{base:v.listenerPortBase??"",end:v.listenerPortEnd??""})}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-settings-url",children:r("出口测试网址")}),s.jsx(Fe,{id:"proxy-settings-url",placeholder:v.testUrl||"",autoComplete:"off",spellCheck:!1,className:"font-mono text-[12px]",value:b,onChange:C=>{y(C.currentTarget.value),k(!1)}})]}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r("「测试」与「批量测试」访问的目标;留空用默认(打 WorkBuddy 上游)。判据是能否拿到 HTTP 响应,不用考虑该网址返回什么内容。")}),s.jsxs("div",{className:"min-h-[18px] text-xs",children:[w?s.jsxs("span",{className:"text-destructive",children:["❌ ",w]}):null,!w&&N?s.jsxs("span",{className:"text-success",children:["✅ ",r("已保存。重启内核后,新分配的节点端口才会按新范围来。")]}):null]})]})}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"ghost",disabled:t||o,onClick:R,children:r("恢复默认")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:o,onClick:e,children:r("关闭")}),s.jsx(ne,{variant:"default",disabled:t||o,onClick:()=>{P()},children:r(o?"保存中…":"保存")})]})]})})}function hD(e){return(Math.max(0,Number(e)||0)/1024/1024).toFixed(1)}function EX(e){return/^[A-Za-z]:[\\/]/.test(e)||e.startsWith("\\\\")||e.startsWith("/")}function AX({onClose:e}){const t=x.useSyncExternalStore(yg,jg),a=Su(),o=a?.download,c=o?.state==="downloading",d=c&&o&&o.total>0?Math.round(o.received/o.total*100):null,[f,p]=x.useState(null),[h,b]=x.useState(""),[y,v]=x.useState(null),[j,w]=x.useState(a?.kernelDir||""),[S,N]=x.useState(!1),[k,A]=x.useState(!1),[P,R]=x.useState("");x.useEffect(()=>{let H=!0;return(async()=>{try{const B=(await nr().workbuddyDesktop?.getProxyPool?.())?.items;if(!Array.isArray(B))throw new Error(r("代理池响应异常"));H&&p(B)}catch(B){if(!H)return;p([]),b(wr(B))}})(),()=>{H=!1}},[]),x.useEffect(()=>{a?.installed&&e()},[a?.installed]);const C=pD({proxyChoice:a?.downloadProxy??null,pool:f,poolError:h}),E=y??C.current,D=C.items.find(H=>H.value===E)??C.selected,I=a?.kernelDirDefault||"";async function O(){if(S)return;const H=j.trim();if(H&&!EX(H)){R(r("存放位置要填绝对路径,例如 D:\\proxy-kernel"));return}R(""),N(!0);try{const B={dir:H};E!==vp&&(B.proxy=E===""?null:{source:"pool",proxyId:E.slice(Qa.length)}),Hq(B)}finally{N(!1)}}async function _(){if(!k){A(!0);try{const H=await Uq();H==="done"?an(r("下载已经完成,停止没赶上(内核已安装)")):H==="none"?an(r("当前没有正在进行的下载"),"err"):H==="stalled"&&an(r("停止请求已发出,但下载还没收手,稍后再看一次进度"),"err")}finally{A(!1)}}}async function z(){const H=nr().workbuddyDesktop;if(typeof H?.pickFolder!="function"){an(r("当前环境不支持选择文件夹,直接填写绝对路径即可"),"err");return}try{const B=await H.pickFolder(j.trim()||I||null);if(B?.unsupported){an(r("当前环境不支持选择文件夹,直接填写绝对路径即可"),"err");return}if(B?.canceled||!B?.path)return;w(B.path)}catch(B){an(r("打开文件夹选择框失败:{reason}",{reason:wr(B)}),"err")}}return s.jsx(Yt,{open:!0,onOpenChange:H=>{H||e()},children:s.jsxs(Xt,{className:"w-[min(520px,calc(100vw-48px))]",children:[s.jsxs(Vt,{children:[s.jsx(Ut,{children:r(c?"正在下载内核":"下载内核")}),s.jsx("span",{className:"text-[11.5px] text-subtle",children:r("内核 {version}({asset})",{version:a?.version||"—",asset:a?.asset||"—"})})]}),c?s.jsxs(Lt,{className:"flex flex-col gap-3",children:[s.jsx(cf,{value:d??null}),s.jsxs("div",{className:"flex items-center justify-between text-[12px]",children:[s.jsx("span",{className:"text-text-2",children:d!==null?r("{percent}%({received} / {total} MB)",{percent:d,received:hD(o?.received),total:hD(o?.total)}):r("正在连接 GitHub…")}),s.jsx("span",{className:"text-subtle",children:r("存放位置 {dir}",{dir:a?.kernelDir||"—"})})]}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r("关掉这个窗口不会中断下载(它在后台继续跑)—— 要停下就点下面的「停止下载」,未下载完的临时文件会被删除。")})]}):s.jsxs(Lt,{className:"flex flex-col gap-3.5",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"kernel-proxy",children:r("下载线路")}),s.jsxs(ut,{value:E,onValueChange:H=>v(String(H)),children:[s.jsx(ft,{id:"kernel-proxy",className:Ue("w-full",C.broken&&"border-destructive-bd"),children:s.jsx(dt,{className:"min-w-0 truncate",children:D?.label||r("直连")})}),s.jsx(pt,{children:C.items.map(H=>s.jsx($e,{value:H.value,disabled:H.disabled,children:H.label},H.value))})]}),s.jsx("div",{className:"text-[12px] text-subtle",children:C.broken?r("当前线路不可用:{error};重新选一条或切回直连",{error:String(a?.downloadProxy?.error||"")}):r("选项来自「网络代理」页(Clash Verge 同步的出口在这里可用;订阅节点要等内核起来才有端口)。选「直连」时连不上会自动借 Clash 混合端口重试一次;选定某条线路后只走它。")})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"kernel-dir",children:r("存放位置")}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(Fe,{id:"kernel-dir",className:"min-w-0 flex-1 font-mono text-[12px]",autoComplete:"off",spellCheck:!1,value:j,placeholder:I,onChange:H=>w(H.currentTarget.value)}),s.jsx(ne,{variant:"outline",size:"sm",className:"flex-none",onClick:()=>{z()},children:r("选择目录…")}),I&&j.trim()!==I?s.jsx(ne,{variant:"ghost",size:"sm",className:"flex-none",title:I,onClick:()=>w(I),children:r("恢复默认")}):null]}),s.jsx("div",{className:"text-[12px] text-subtle",children:r("内核二进制 / 配置 / 端口映射都会放在这里,默认 {dir};目录不存在会在下载开始时自动创建。",{dir:I||"—"})})]}),o?.state==="error"&&o.error?s.jsx("span",{className:"text-[12px] text-destructive",children:r("上次下载失败:{reason}",{reason:o.error})}):null,o?.state==="canceled"?s.jsx("span",{className:"text-[12px] text-subtle",children:r("上次下载已停止,未下载完的临时文件已删除")}):null,P?s.jsx("span",{className:"text-[12px] text-destructive",children:P}):null]}),s.jsx(tn,{children:c?s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:e,children:r("后台继续")}),s.jsx(ne,{variant:"destructive",disabled:k,onClick:()=>{_()},children:r(k?"正在停止…":"停止下载")})]}):s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:e,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:S||t.pending,onClick:()=>{O()},children:r(S?"正在开始…":"下载")})]})})]})})}function gD({showPortRange:e=!1}){const t=x.useSyncExternalStore(yg,jg),a=Su(),[o,c]=x.useState(null),[d,f]=x.useState(!1);x.useEffect(()=>{let b=!0;return(async()=>{try{const y=await fO();if(!b||!y)return;const v=Number(y.listenerPortBase),j=Number(y.listenerPortEnd);Number.isFinite(v)&&Number.isFinite(j)&&v>0&&j>0&&c({base:v,end:j})}catch{}})(),()=>{b=!1}},[]);const p=a?.download.state==="downloading",h=p&&a.download.total>0?Math.round(a.download.received/a.download.total*100):null;return s.jsxs("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-surface-2 px-3 py-2",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[s.jsx(ze,{variant:a?.running?"default":"secondary",children:a?.running?r("内核运行中"):a?.installed?a.halted?r("内核已手动关闭"):r("内核已停止"):r("内核未安装")}),s.jsxs("span",{className:"text-[12.5px] text-text-2",children:[a?.installed?r("内核 {version}",{version:a.version})+" · ":"",a?.running?r("控制端口 {port} · {n} 个节点监听器",{port:a?.controllerPort??"—",n:a?.listenerCount??0}):a?.installed?a.halted?r("内核已手动关闭(点「启动内核」拉起)"):r("内核已停止,点「启动内核」拉起"):r("按需下载(约 20-40MB)")]}),e&&o?s.jsx("span",{className:"text-[11.5px] text-subtle",children:r("节点端口范围 {base}–{end}",{base:o.base,end:o.end})}):null,s.jsx("div",{className:"ml-auto flex items-center gap-2",children:a?.installed?s.jsxs(s.Fragment,{children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:t.pending||p,onClick:()=>{Vq()},children:a?.running?r("重启内核"):r("启动内核")}),a?.running?s.jsx(ne,{size:"sm",variant:"outline",disabled:t.pending||p,onClick:()=>{Fq()},children:r("关闭内核")}):null,s.jsx(ne,{size:"sm",variant:"destructive",disabled:t.pending||p,onClick:()=>{$q()},children:r("删除内核")})]}):s.jsx(ne,{size:"sm",variant:"outline",disabled:t.pending&&!p,onClick:()=>f(!0),children:r(p?"下载中…":"下载内核")})})]}),p?s.jsxs("div",{className:"flex items-center gap-3",children:[s.jsx(cf,{className:"min-w-[200px] flex-1",value:h??null}),s.jsx("span",{className:"text-[11px] text-subtle",children:h!==null?r("{percent}%({received} / {total} MB)",{percent:h,received:xD(a.download.received),total:xD(a.download.total)}):r("下载中…")})]}):null,a?.lastError?s.jsx("span",{className:"text-[12px] text-destructive",children:a.lastError}):null,d?s.jsx(AX,{onClose:()=>f(!1)}):null]})}function RX({onClose:e}){const t=x.useSyncExternalStore(yg,jg),a=x.useSyncExternalStore(cO,uO),o=Iq(),c=t.data!==null,[d,f]=x.useState(null);return x.useEffect(()=>{Ml()},[]),s.jsxs(Yt,{open:!0,onOpenChange:p=>{p||e()},children:[s.jsxs(Xt,{className:"w-[min(880px,calc(100vw-48px))]",children:[s.jsxs(Vt,{children:[s.jsx(Ut,{children:r("订阅管理")}),s.jsxs("span",{className:"text-[11.5px] text-subtle",children:[c?r("{n} 条订阅",{n:o.length}):r("加载中…")," · ",r("节点由内核起成本地监听器,镜像进代理池")]})]}),s.jsxs(Lt,{className:"flex flex-col gap-3",children:[s.jsx(gD,{}),s.jsx("div",{className:"models-table-wrap",children:s.jsxs("table",{className:"models-table",children:[s.jsxs("colgroup",{children:[s.jsx("col",{className:"w-[18%]"}),s.jsx("col",{className:"w-[31%]"}),s.jsx("col",{className:"w-[9%]"}),s.jsx("col",{className:"w-[14%]"}),s.jsx("col",{className:"w-[8%]"}),s.jsx("col",{className:"w-[20%]"})]}),s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{children:r("名称")}),s.jsx("th",{children:r("订阅来源")}),s.jsx("th",{className:"ta-center",children:r("节点")}),s.jsx("th",{children:r("上次同步")}),s.jsx("th",{className:"ta-center",children:r("启用")}),s.jsx("th",{className:"ta-right",children:r("操作")})]})}),s.jsx("tbody",{children:o.length?o.map(p=>{const h=Su()?.providerSync?.[p.id];return s.jsxs("tr",{className:p.enabled?"":"off",children:[s.jsx("td",{children:s.jsx("b",{children:p.name||r("未命名")})}),s.jsx("td",{className:"group",children:s.jsx("div",{className:"flex min-w-0 items-center gap-1",children:p.kind==="local"?s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"min-w-0 truncate font-mono text-[12px] text-text-2",title:p.fileName,children:p.fileName||r("本地 YAML 文件")}),s.jsx(ze,{variant:"secondary",children:r("本地文件")})]}):s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"min-w-0 truncate font-mono text-[12px] text-text-2",title:p.url,children:OX(p.url)}),s.jsx(ne,{variant:"ghost",size:"icon-xs",className:"copy-btn size-[21px] rounded-[var(--r-xs)] opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100","data-copy":p.url,title:r("复制订阅链接"),children:"⧉"})]})})}),s.jsx("td",{className:"ta-center",children:bD(h,p)>0?s.jsx(ze,{variant:"secondary",children:r("{n} 个",{n:bD(h,p)})}):s.jsx("span",{className:"text-subtle",children:r("—")})}),s.jsx("td",{children:h?.at?s.jsx("span",{className:"text-[12px] text-text-2",children:sO(h.at)}):s.jsx("span",{className:"text-subtle",children:r("未同步")})}),s.jsx("td",{className:"ta-center",children:s.jsx(ns,{checked:p.enabled,disabled:t.pending,"aria-label":r("启用订阅「{name}」",{name:p.name||r("未命名")}),onCheckedChange:b=>{Lq(p,b)}})}),s.jsx("td",{children:s.jsxs("div",{className:"row-actions",children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:t.pending||t.refreshing!==null||p.kind==="local",title:p.kind==="local"?r("本地文件订阅无需更新(要换内容请编辑后重新选择文件)"):void 0,onClick:()=>{zq(p)},children:t.refreshing===p.id?r("更新中…"):r("立即更新")}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:t.pending,onClick:()=>f({item:p}),children:r("编辑")}),s.jsx(ne,{size:"sm",variant:"destructive",disabled:t.pending,onClick:()=>{Bq(p)},children:r("删除")})]})})]},p.id)}):s.jsx("tr",{children:s.jsx("td",{colSpan:6,className:"empty",children:c?s.jsxs("div",{className:"flex flex-col items-center gap-2 py-3",children:[s.jsx("span",{children:r("还没有订阅:粘贴订阅链接、导入本地 YAML 文件,或从图片识别二维码。")}),s.jsx(ne,{size:"sm",variant:"outline",disabled:t.pending,onClick:()=>f({item:null}),children:r("+ 新增订阅")}),s.jsx("span",{className:"text-[11px] text-subtle",children:r("订阅里的节点会自动同步进代理池,账号即可引用。")})]}):r("加载中…")})})})]})}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r("订阅里的节点会被内核起成本地监听器,镜像到代理池(账号按 id 引用,与本页其它出口同一用法)。内核只在用到订阅时按需下载(约 20-40MB),不随安装包分发。")}),t.error?s.jsx("span",{className:"text-destructive",children:r("读取失败:{reason}",{reason:t.error})}):null]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"default",disabled:t.pending,onClick:()=>f({item:null}),children:r("+ 新增订阅")}),s.jsx(ne,{variant:"outline",disabled:a.syncing||a.batchBusy,onClick:()=>{Cq()},children:a.syncing?r("同步中…"):r("同步 Clash Verge")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:e,children:r("完成")})]})]}),d?s.jsx(DX,{item:d.item,onClose:()=>f(null)}):null]})}function xD(e){return!Number.isFinite(e)||e<=0?"—":(e/1e3/1e3).toFixed(1)}function OX(e){try{const t=new URL(e);return t.host+(t.pathname!=="/"?"/…":"")}catch{return e.slice(0,60)}}function bD(e,t){return e?.count??t.nodeCount}function MX(){return s.jsxs("div",{className:"flex flex-col gap-2.5 rounded-lg border border-border bg-surface-2 px-3.5 py-3",children:[s.jsxs("a",{href:Ho,"data-external":Ho,onClick:Xu,className:"inline-flex w-fit items-center no-underline",children:[s.jsx("img",{src:NX,alt:"ProxyLane",className:"h-[24px] w-auto dark:hidden"}),s.jsx("img",{src:kX,alt:"ProxyLane",className:"hidden h-[24px] w-auto dark:block"})]}),s.jsxs("p",{className:"text-xs leading-[1.7] text-text-2",children:[s.jsx("a",{className:"font-semibold text-primary-fg no-underline hover:underline",href:Ho,"data-external":Ho,onClick:Xu,children:"ProxyLane"}),r(" 提供 AI 账号专用的原生静态住宅 IP(Static Residential ISP):IP 来自真实家庭宽带运营商,Scamalytics 低欺诈评分,每个 IP 独享,不限流量,$3.90 起。")]}),s.jsx("p",{className:"text-xs leading-[1.7] text-text-2",children:r("首次购买使用优惠码 AGENT2API25 享 75 折。")}),s.jsx("div",{children:s.jsx(ne,{size:"sm",render:s.jsx("a",{href:Ho,"data-external":Ho,onClick:Xu}),children:r("去获取")})})]})}function DX({item:e,onClose:t}){const a=e!==null,[o,c]=x.useState(e?.kind==="local"?"local":"url"),[d,f]=x.useState(e?.name||""),[p,h]=x.useState(e?.url||""),[b,y]=x.useState(e?.fileName||""),[v,j]=x.useState(""),[w,S]=x.useState(e?e.enabled:!0),[N,k]=x.useState(!1),[A,P]=x.useState(!1),[R,C]=x.useState(!1),[E,D]=x.useState(null),I=x.useRef(null);async function O(){if(N)return;const L=d.trim();if(!L){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",r("请填写订阅名称")]}));return}const F=p.trim();if(o==="url"&&!(F.startsWith("http://")||F.startsWith("https://"))){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",r("订阅链接必须是 http:// 或 https:// 开头")]}));return}if(!a&&o==="local"&&!v){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",r("请选择要导入的 YAML 文件")]}));return}k(!0);try{a&&o==="local"?await mO(e,{name:L,enabled:w,kind:"local",fileName:b||void 0,...v?{contentB64:v}:{}}):a?await mO(e,{name:L,url:F,enabled:w,kind:"url"}):o==="local"?await pO({name:L,kind:"local",fileName:b||void 0,contentB64:v}):await pO({name:L,kind:"url",url:F}),t()}catch($){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",wr($)]})),k(!1)}}async function _(L){if(!A){P(!0),D(r("正在识别二维码…"));try{const F=await qq(L);h(F),D(s.jsxs("span",{className:"text-success",children:["✅ ",r("已识别订阅链接")]}))}catch(F){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",wr(F)]}))}finally{P(!1)}}}async function z(L){if(!R){C(!0),D(null);try{const F=await hO(L);j(F),y(L.name),D(s.jsxs("span",{className:"text-success",children:["✅ ",r("已选择「{name}」,保存后导入",{name:L.name})]}))}catch(F){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",wr(F)]}))}finally{C(!1)}}}function H(L){if(o!=="url")return;const $=Array.from(L.clipboardData?.files||[]).find(X=>X.type.startsWith("image/"));$&&(L.preventDefault(),_($))}function B(L){L!==o&&(c(L),D(null))}return s.jsx(Yt,{open:!0,onOpenChange:L=>{!L&&!N&&t()},children:s.jsxs(Xt,{className:"max-w-[560px]",overlayForceRender:!0,onPaste:H,children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r(a?"编辑订阅":"新增订阅")})}),s.jsxs(Lt,{className:"flex flex-col gap-3.5",children:[o==="residential"?null:s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"sub-name",children:r("名称")}),s.jsx(Fe,{id:"sub-name",maxLength:60,autoComplete:"off",spellCheck:!1,placeholder:r("例如:我的机场"),value:d,onChange:L=>f(L.currentTarget.value)})]}),a?null:s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{children:r("订阅来源")}),s.jsx(En,{options:[{value:"url",label:r("订阅链接")},{value:"local",label:r("本地 YAML 文件")},{value:"residential",label:r("家庭宽带")}],value:o,onValueChange:B,"aria-label":r("订阅来源")})]}),o==="residential"?s.jsx(MX,{}):o==="url"?s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"sub-url",children:r("订阅链接")}),s.jsx(Fe,{id:"sub-url",autoComplete:"off",spellCheck:!1,placeholder:"https://…",value:p,onChange:L=>h(L.currentTarget.value)}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:A,onClick:()=>I.current?.click(),children:r(A?"识别中…":"从图片识别二维码")}),s.jsx("span",{className:"text-[11px] text-subtle",children:r("也可以把二维码截图直接粘贴到弹窗里(Ctrl+V)")}),s.jsx("input",{ref:I,type:"file",accept:"image/*",className:"hidden",onChange:L=>{const F=L.currentTarget.files?.[0];F&&_(F),L.currentTarget.value=""}})]})]}):s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"sub-file",children:r("YAML 文件")}),s.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:R,className:"shrink-0",onClick:()=>I.current?.click(),children:r(R?"读取中…":a?"重新选择文件…":"选择 YAML 文件…")}),s.jsx("span",{className:"min-w-0 truncate font-mono text-[12px] text-text-2",title:b||void 0,children:b||r(a?"保持原文件":"未选择文件")})]}),a?s.jsx("span",{className:"text-[11px] text-subtle",children:r("本地文件不会自动更新:要更新节点,重新选择文件后保存;不重选则内容保持不变。")}):null,s.jsx("input",{ref:I,type:"file",accept:".yaml,.yml,text/yaml,application/yaml,text/plain",className:"hidden",onChange:L=>{const F=L.currentTarget.files?.[0];F&&z(F),L.currentTarget.value=""}})]}),o==="residential"?null:s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"flex flex-row items-center gap-2.5",children:[s.jsx(ns,{checked:w,onCheckedChange:S,"aria-label":r("启用这条订阅")}),s.jsx("span",{className:"text-[12.5px]",children:r("启用(禁用的订阅不参与内核同步,它的节点会从代理池移除)")})]}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r(o==="url"?"订阅内容由内核定时刷新(每 24 小时);节点数与同步状态在保存后由轮询刷新,稍等几秒。":"本地文件订阅的内容在导入时固定:节点会由内核起成本地监听器并镜像进代理池,节点数稍等几秒由轮询刷新。")}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:E})]})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:N,onClick:t,children:r("取消")}),o==="residential"?null:s.jsx(ne,{variant:"default",disabled:N||A||R,onClick:()=>{O()},children:r(N?"保存中…":"保存")})]})]})})}const w0=[{key:"pick",label:r("选择"),align:"center"},{key:"name",label:r("节点")},{key:"addr",label:r("地址")},{key:"state",label:r("启用"),align:"center"},{key:"test",label:r("连通性")},{key:"act",label:r("操作"),align:"right"}],IX={pick:"p-pick",name:"",addr:"p-addr",state:"p-state",test:"p-test",act:"p-act"},vD="proxies";function S0(){return window}let ox=null,yD=null;function jD(){return ox?ox.apply([...w0]):w0.map(e=>({...e,align:e.align??"left"}))}function PX(){S0().wbTableColumns?.repaint?.(vD)}function _X(e){if(yD=e,ox)return!0;const t=S0().wbColSettings;return t?.register?(ox=t.register({id:vD,label:r("代理池表"),columns:w0.map(a=>({key:a.key,label:a.label,align:a.align??"left"})),mount:()=>document.querySelector('.page[data-page="proxies"] .panel-head .head-actions'),onChange:()=>yD?.()}),!0):!1}function LX(){S0().wbColSettings?.close?.()}function zX(){const e=x.useSyncExternalStore(cO,uO),t=x.useSyncExternalStore(yg,jg).data?.items??[],[a,o]=x.useState(null),[c,d]=x.useState(!1),[f,p]=x.useState(!1),[h,b]=x.useState(""),[y,v]=x.useState("all"),[j,w]=x.useState("all"),[S,N]=x.useState("all"),[k,A]=x.useState(0),[,P]=x.useReducer(W=>W+1,0),R=vg(),C=e.data!==null,E=e.selected.size,D=R.filter(W=>e.selected.has(W.id)&&xg(W)).length,I=e.batchProgress;x.useEffect(()=>{Ml()},[]),x.useLayoutEffect(()=>{if(!_X(()=>P())){const W=window.setTimeout(()=>A(ue=>ue+1),50);return()=>window.clearTimeout(W)}P()},[k]),x.useLayoutEffect(()=>{PX()}),x.useEffect(()=>()=>{LX()},[]);const O=h.trim().toLowerCase(),_=UX(R,t);function z(W){return j==="all"?!0:j==="manual"||j==="clash"||j==="subscription"?sl(W)===j:j===ND?!!W.orphan:W.source==="subscription"&&!W.orphan&&W.providerId===j}function H(W){return!(y!=="all"&&sl(W)!==y||!z(W)||S!=="all"&&SD(W)!==S||O&&![W.name,Yh(W),W.host,W.protocol,String(W.port??"")].join(" ").toLowerCase().includes(O))}function B(W){const ue=W??"all";w(ue),v(ue==="all"?"all":ue==="manual"||ue==="clash"?ue:"subscription")}function L(W){v(W),w("all")}const F=R.filter(H),$=F.map(W=>W.id),X=$.length>0&&$.every(W=>e.selected.has(W)),K=$.some(W=>e.selected.has(W))&&!X,q=jD(),Q=[];for(const W of wD())Q.push(...F.filter(ue=>sl(ue)===W.key));const G=hg(F.length,"proxies"),J=G.paged?G.slice(Q):Q,Y=new Map;for(const W of F)Y.set(sl(W),(Y.get(sl(W))??0)+1);x.useEffect(()=>{G.goto(1)},[O,y,j,S]);function re(W){const ue=W.lastTest;if(!ue||!ue.at)return s.jsx("span",{className:"text-subtle",children:r("未测试")});const ve=Uj(ue.durationMs);return s.jsxs("div",{className:"flex flex-col gap-0.5 leading-[1.5] min-w-0",children:[s.jsxs("span",{className:ue.success?"text-success":"text-destructive",children:[ue.success?r("✅ {ip}",{ip:ue.ip||r("连接成功")}):r("❌ 连接失败"),ve?` ${ve}`:"",s.jsxs("span",{className:"text-[11px] text-subtle",children:[" ",sO(ue.at)]})]}),ue.success?null:s.jsx("span",{className:"overflow-hidden text-ellipsis whitespace-nowrap text-[11px] text-subtle",title:String(ue.error||r("连接失败")),children:String(ue.error||r("连接失败"))})]})}function M(W){const ue=W.usedBy||[],ve=[];return W.protocol&&ve.push(W.protocol),ue.length&&ve.push(s.jsx("span",{className:"text-warn",title:ue.map(ee=>String(ee.name||ee.id||"")).join(r("、")),children:r("{n} 个账号在用",{n:ue.length})})),ve.length?s.jsx("span",{className:"text-[11px] text-subtle",children:ve.map((ee,he)=>s.jsxs(x.Fragment,{children:[he?" · ":"",ee]},he))}):null}function U(W){if(mq(W)&&(W.port===null||W.port===void 0))return s.jsx("span",{className:"text-subtle",children:r("已禁用(未开监听端口)")});if(W.resolveError){const ve=W.source==="subscription"&&(W.port===null||W.port===void 0);return s.jsx("span",{className:ve?"text-subtle":"text-destructive",title:W.resolveError,children:r(ve?"未分配端口":"解析失败")})}if(fq(W)){const ve=Su()?.installed===!1;return s.jsx("span",{className:"text-subtle",title:r(ve?"代理内核未安装(在「订阅管理」里下载内核后,节点会自动分配监听端口)":"还没有监听端口(还没有账号引用它 —— 在账号里选它并保存后,内核会自动开端口)"),children:Yh(W)||r("未分配端口")})}const ue=Yh(W);return s.jsxs("div",{className:"flex min-w-0 items-center gap-1",children:[s.jsx("span",{className:"min-w-0 flex-1 font-mono text-[12px] leading-[1.45] text-text-2 break-all",title:ue||void 0,children:ue||"—"}),ue?s.jsx(ne,{variant:"ghost",size:"icon-xs",className:"copy-btn flex-none","data-copy":ue,title:r("复制地址"),children:"⧉"}):null]})}function Z(W,ue,ve,ee){const he=ve||e.batchBusy;switch(W){case"pick":return s.jsx(Pr,{checked:ee,title:r("勾选后可批量操作"),"aria-label":r("勾选「{name}」",{name:ue.name||r("未命名")}),onCheckedChange:te=>Sq(ue.id,te)});case"name":return s.jsxs("div",{className:"flex flex-col gap-0.5 leading-[1.5] min-w-0",children:[s.jsx("b",{children:ue.name||r("未命名")}),M(ue)]});case"addr":return U(ue);case"state":{const te=aO(ue);return s.jsx(ns,{checked:ue.enabled!==!1,disabled:he||te,"aria-label":r("启用「{name}」",{name:ue.name||r("未命名")}),title:jq(ue),onCheckedChange:ke=>{Eq(ue,ke)}})}case"test":return re(ue);case"act":{const te=bg(ue);xg(ue);const ke=iO(ue),le=e.testing===ue.id;return s.jsxs("div",{className:"row-actions",children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:he||e.testing!==null,onClick:()=>{Tq(ue)},children:r(le?"测试中…":"测试")}),ue.source!=="clash"&&ue.source!=="subscription"?s.jsxs(s.Fragment,{children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:he,onClick:()=>o({item:ue}),children:r("编辑")}),s.jsx(ne,{size:"sm",variant:"destructive",disabled:he,onClick:()=>{dO(ue)},children:r("删除")})]}):null,te?s.jsx(ne,{size:"sm",variant:"destructive",disabled:he,title:ke,onClick:()=>{dO(ue)},children:r("删除")}):null]})}default:return null}}function ae(W){const ue=e.pending.has(W.id),ve=wq(W.id);return s.jsx("tr",{className:Ue(W.enabled?"":"off",ve&&"bg-primary-soft"),"data-id":W.id,children:q.map(ee=>s.jsx("td",{className:`ta-${ee.align}`,children:Z(ee.key,W,ue,ve)},ee.key))},W.id)}function ce(){if(!R.length)return s.jsx("tr",{children:s.jsx("td",{colSpan:q.length,className:"empty",children:r(C?"还没有代理。点右上角「+ 新增代理」手填一个,或在「订阅管理」里导入订阅节点、同步 Clash Verge 的出口。":"加载中…")})});if(!F.length)return s.jsx("tr",{children:s.jsx("td",{colSpan:q.length,className:"empty",children:O?r("没有匹配「{kw}」的出口",{kw:h.trim()}):r("没有匹配当前筛选的出口")})});const W=[];let ue="";for(const ve of J){const ee=sl(ve);if(ee!==ue){ue=ee;const he=wD().find(te=>te.key===ee);W.push(s.jsx("tr",{className:"tr-group",children:s.jsxs("td",{colSpan:q.length,children:[s.jsx("span",{className:"prov-tag",children:he?.label??ee}),r("{n} 个",{n:Y.get(ee)??0}),he?.note?s.jsxs("span",{className:"font-normal",children:[" · ",he.note]}):null]})},`group:${ee}:${W.length}`))}W.push(ae(ve))}return s.jsx(s.Fragment,{children:W})}return s.jsx(s.Fragment,{children:s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("代理池")}),s.jsx("span",{className:"panel-sub",children:C?r("{n} 个出口",{n:R.length}):r("加载中…")}),s.jsx("span",{className:"text-[11px] text-subtle",children:r("订阅与 Clash 的出口自动镜像进来")}),s.jsxs("div",{className:"head-actions",children:[s.jsx(ne,{variant:"outline",disabled:e.batchBusy,onClick:()=>d(!0),children:r("设置")}),s.jsx(ne,{variant:"outline",disabled:e.batchBusy,onClick:()=>p(!0),children:t.length?r("订阅管理({n})",{n:t.length}):r("订阅管理")}),s.jsx(ne,{variant:"outline",disabled:e.loading||e.batchBusy,onClick:()=>{Lf(),Ml()},children:e.loading?r("刷新中…"):r("刷新")}),s.jsx(ne,{variant:"default",disabled:e.batchBusy,onClick:()=>o({item:null}),children:r("+ 新增代理")})]})]}),s.jsx("div",{className:"px-3 pt-3",children:s.jsx(gD,{showPortRange:!0})}),E>0?s.jsxs("div",{className:"batch-bar active",children:[s.jsxs("span",{className:"batch-count",children:[r("已选")," ",s.jsx("b",{children:E})," ",r("个 · 共")," ",s.jsx("b",{children:F.length})," ",r("个")]}),D?s.jsx("span",{className:"batch-hidden",children:r("其中 {n} 条是同步来的只读条目(Clash / 订阅):可参与批量测试,删除会跳过",{n:D})}):null,s.jsxs("div",{className:"batch-actions",children:[s.jsx(ne,{variant:"outline",disabled:e.batchBusy,onClick:()=>{Rq()},children:I?r("测试中 {done}/{total}",{done:I.done,total:I.total}):r("批量测试")}),s.jsx(ne,{variant:"destructive",disabled:e.batchBusy,onClick:()=>{Oq()},children:r("批量删除")}),s.jsx(ne,{variant:"outline",disabled:e.batchBusy,onClick:()=>kq(),children:r("取消选择")})]})]}):s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5 border-b border-border px-4 py-[10px]",children:[s.jsxs(Di,{className:"w-[clamp(150px,22vw,220px)]",children:[s.jsx(Pi,{type:"search",value:h,"aria-label":r("搜索节点"),placeholder:r("搜索名称 / 地址 / 端口"),onChange:W=>b(W.currentTarget.value)}),s.jsx(Ii,{align:"inline-start","aria-hidden":"true",children:s.jsx(VX,{})})]}),s.jsxs(ut,{value:j,onValueChange:B,children:[s.jsx(ft,{className:"w-[clamp(150px,18vw,210px)]","aria-label":r("按提供方筛选"),children:s.jsx(dt,{children:_.find(W=>W.value===j)?.label??r("全部提供方")})}),s.jsx(pt,{children:_.map(W=>s.jsx($e,{value:W.value,children:s.jsxs("span",{className:"flex w-full items-center gap-2",children:[s.jsx("span",{className:"min-w-0 flex-1 truncate"+(W.count?"":" text-subtle"),children:W.label}),s.jsx("span",{className:"flex-none text-[11px] text-subtle",children:W.count})]})},W.value))})]}),s.jsx(En,{options:BX(R),value:y,onValueChange:L,"aria-label":r("按来源筛选")}),s.jsx(En,{options:HX(R),value:S,onValueChange:N,"aria-label":r("按状态筛选")}),s.jsx("span",{className:"ml-auto text-[11px] text-subtle",children:r("显示 {n} / 共 {total} 个出口",{n:F.length,total:R.length})})]}),s.jsx("div",{className:"models-table-wrap",children:s.jsxs("table",{className:"models-table proxies-table",children:[s.jsx("colgroup",{children:q.map(W=>s.jsx("col",{"data-col":W.key,className:IX[W.key]||void 0},W.key))}),s.jsx("thead",{children:s.jsx("tr",{children:q.map(W=>s.jsx("th",{"data-col":W.key,className:`ta-${W.align}`,children:W.key==="pick"?s.jsx(Pr,{checked:X,indeterminate:K,disabled:!$.length,title:r("全选当前筛选出的出口"),"aria-label":r("全选当前筛选出的出口"),onCheckedChange:ue=>Nq($,ue)}):W.label},W.key))})}),s.jsx("tbody",{children:ce()})]})}),s.jsx($i,{leading:s.jsxs(s.Fragment,{children:[e.data?.clash&&e.data.clash.available===!1?s.jsx("span",{className:"text-subtle",children:e.data.clash.error?r("未检测到 Clash Verge:{reason}",{reason:e.data.clash.error}):r("未检测到 Clash Verge")}):null,e.error?s.jsx("span",{className:"text-destructive",children:r("读取失败:{reason}",{reason:e.error})}):null]}),total:F.length,page:G.page,pageCount:G.pageCount,size:G.size,onSizeChange:G.setSize,onPageChange:G.goto,range:G.paged?{start:G.rangeStart,end:G.rangeEnd}:null}),a?s.jsx(CX,{item:a.item,onClose:()=>o(null)}):null,c?s.jsx(TX,{onClose:()=>d(!1)}):null,f?s.jsx(RX,{onClose:()=>p(!1)}):null]})})}function sl(e){return e.source==="clash"?"clash":e.source==="subscription"?"subscription":"manual"}function wD(){return[{key:"manual",label:r("手动"),note:r("本页可编辑、可删除")},{key:"clash",label:"Clash Verge",note:r("名字与端口在 Clash Verge 里改;启用可在本页关闭")},{key:"subscription",label:r("订阅"),note:r("名字与端口跟随订阅与内核;启用可在本页关闭")}]}function BX(e){const t=a=>e.filter(o=>sl(o)===a).length;return[{value:"all",label:r("全部"),count:e.length},{value:"manual",label:r("手动"),count:t("manual")},{value:"clash",label:"Clash",count:t("clash")},{value:"subscription",label:r("订阅"),count:t("subscription")}]}function SD(e){return e.enabled===!1?"off":e.port===null||e.port===void 0?"wait":e.lastTest?.at?e.lastTest.success?"ok":"fail":"none"}function HX(e){const t=a=>e.filter(o=>SD(o)===a).length;return[{value:"all",label:r("全部状态"),count:e.length},{value:"ok",label:r("可用"),count:t("ok")},{value:"fail",label:r("失败"),count:t("fail")},{value:"wait",label:r("未就绪"),count:t("wait")},{value:"off",label:r("已禁用"),count:t("off")}]}const ND="__orphan";function UX(e,t){const a=e.filter(d=>sl(d)==="subscription"),o=t.map(d=>({value:d.id,label:d.name||d.id,count:a.filter(f=>!f.orphan&&f.providerId===d.id).length})).sort((d,f)=>f.count-d.count||d.label.localeCompare(f.label)),c=a.filter(d=>d.orphan).length;return[{value:"all",label:r("全部提供方"),count:e.length},{value:"manual",label:r("手动"),count:e.filter(d=>sl(d)==="manual").length},{value:"clash",label:"Clash Verge",count:e.filter(d=>sl(d)==="clash").length},{value:"subscription",label:r("全部订阅"),count:a.length},...o,...c?[{value:ND,label:r("已移除的订阅"),count:c}]:[]]}function VX(){return s.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[s.jsx("circle",{cx:"11",cy:"11",r:"8"}),s.jsx("path",{d:"m21 21-4.3-4.3"})]})}window.wbProxiesPanel={load:async()=>{await Lf(),await Ml()},visibleColumns:()=>jD().map(e=>({key:e.key}))};const kD='.page[data-page="proxies"]';function CD(){const e=document.querySelector(kD);!e||e.dataset.mounted==="1"||(e.dataset.mounted="1",e.replaceChildren(),jn.createRoot(e).render(s.jsx(zX,{})),tr().wbApp?.currentPage==="proxies"&&(Lf(),Ml()))}document.querySelector(kD)?CD():document.addEventListener("DOMContentLoaded",CD,{once:!0});const ix=["today","7","30","month","all","custom"],N0="7",k0="custom",TD="workbuddy-desktop-report-range",ED="workbuddy-desktop-report-custom-range",AD={today:r("今天"),7:r("近 7 天"),30:r("近 30 天"),month:r("本月"),all:r("全部"),custom:r("自定义区间")},FX={today:r("今天"),7:r("7 天"),30:r("30 天"),month:r("本月"),all:r("全部"),custom:r("自定义")};function $X(){try{const e=localStorage.getItem(TD);return e!==null&&ix.includes(e)?e:N0}catch{return N0}}function C0(e){const t=a=>String(a).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function qX(){const e=new Date;return{start:C0(new Date(e.getFullYear(),e.getMonth(),e.getDate()-6)),end:C0(e)}}const cx=/^\d{4}-\d{2}-\d{2}$/;function GX(){try{const e=localStorage.getItem(ED);if(e){const t=JSON.parse(e),a=typeof t?.start=="string"?t.start:"",o=typeof t?.end=="string"?t.end:"";if(cx.test(a)&&cx.test(o)&&a<=o)return{start:a,end:o}}}catch{}return qX()}function KX(e){try{localStorage.setItem(ED,JSON.stringify(e))}catch{}}const YX=[[0,r("一")],[2,r("三")],[4,r("五")]],RD=400;function sc(e){const t=T0();return t.formatInt?t.formatInt(e):(Number(e)||0).toLocaleString("zh-CN")}function T0(){return window.wbUnits||{}}function os(e){const t=T0();return t.formatTokens?t.formatTokens(e):String(Number(e)||0)}function OD(e,t){const a=T0();return a.formatAxis?a.formatAxis(e,t):String(e)}function rc(e){return`${((Number(e)||0)*100).toFixed(1)}%`}function zt(e){return Math.round(e*10)/10}function ux(e){return[...e].reduce((t,a)=>t+(/[\u2e80-\u9fff]/.test(a)?9.7:5.4),0)}function dx(e){const[t,a,o]=String(e||"").split("-").map(Number);return new Date(t||1970,(a||1)-1,o||1)}const XX=[r("日"),r("一"),r("二"),r("三"),r("四"),r("五"),r("六")];function fx(e){const t=dx(e);return r("{m}月{d}日 周{wd}",{m:t.getMonth()+1,d:t.getDate(),wd:XX[t.getDay()]})}function MD(e){const t=String(e||"").slice(11,13);return t?`${t}:00`:"—"}const QX=8;function DD(e,t){const a=(Array.isArray(e)?e:[]).map(d=>({name:String(d?.label??d?.model??"").trim()||r("未知模型"),tokens:Number(d?.tokens)||0})).filter(d=>d.tokens>0);if(!a.length)return[];const o=a.slice(0,QX),c=o.map(d=>`${t?`[${t(d.name)}]`:""}${r("{model}:{tokens} tokens",{model:d.name,tokens:os(d.tokens)})}`);return a.length>o.length&&c.push(r("…还有 {n} 个模型",{n:a.length-o.length})),c}function ID(e,t){return[fx(e.date),r("总 Token:{tokens}({n} 次请求)",{tokens:os(e.tokens),n:sc(e.requests)}),...DD(e.models,t)].join(` -`)}function ZX(e,t){return[`${fx(String(e.hour).slice(0,10))} ${MD(e.hour)}`,r("命中率 {rate}(命中 {hit} / 输入 {input})",{rate:rc(e.rate),hit:os(e.hitTokens),input:os(e.inputTokens)}),r("总 Token:{tokens}",{tokens:os(e.totalTokens)}),...DD(e.models,t)].join(` -`)}const WX=[1,1.5,2,2.5,3,4,5,6,8,10];function JX(e){if(!(e>0))return 1;const t=10**Math.floor(Math.log10(e)),a=e/t;return(WX.find(c=>c>=a-1e-9)??10)*t}function E0(e){return JX(e/4)*4}function eQ(e,t,a){const o=e||{},c=o.topModel,d=Number(o.requests)||0,f=Number(o.successful)||0,p=d?`${(f/d*100).toFixed(1)}%`:"—",h=[{key:"requests",label:r("总请求数"),value:sc(d),sub:AD[t]||"",mono:!1},{key:"successful",label:r("成功请求数"),value:sc(f),sub:r("成功率 {rate}",{rate:p}),mono:!1},{key:"tokens",label:r("总 Token"),value:os(o.tokens),sub:r("输入 + 输出"),mono:!1},{key:"activeDays",label:r("活跃天数"),value:sc(o.activeDays),sub:r("区间共 {n} 天",{n:a}),mono:!1},{key:"streak",label:r("当前连续天数"),value:sc(o.streak),sub:r("含今天在内往前数"),mono:!1}];return h.push(c?{key:"topModel",label:r("Top 模型"),value:String(c.model??""),sub:r("{tokens} tokens · 占 {pct}",{tokens:os(c.tokens),pct:rc(c.percentage)}),mono:!0}:{key:"topModel",label:r("Top 模型"),value:"—",sub:r("所选范围内还没有模型用量"),mono:!1}),h}function PD(e){if(!Array.isArray(e))return null;const t=e.map(c=>({id:String(c?.id??"").trim(),label:String(c?.label??"").trim(),tokens:Number(c?.totalTokens??c?.tokens)||0})).filter(c=>c.tokens>0);if(!t.length)return[];const a=t.reduce((c,d)=>c+d.tokens,0),o=c=>a?c/a*100:0;return[...t].sort((c,d)=>d.tokens-c.tokens).map((c,d)=>{const f=o(c.tokens),p=os(c.tokens),h=c.label||c.id||r("未知"),b=c.id?r("{name}({id})",{name:h,id:c.id}):h;return{key:`${d}-${c.id||h}`,id:c.id,name:h,full:b,tip:r("{name}:{tokens} tokens · 占 {pct}%",{name:b,tokens:p,pct:f.toFixed(1)}),tokensText:p,percentText:`${f.toFixed(1)}%`,barWidth:`${f.toFixed(1)}%`}})}function _D(e){return`${os(e.reduce((t,a)=>t+(Number(a?.totalTokens??a?.tokens)||0),0))} tokens`}const px=["#f73b00","#f7bb07","#4aaa4d","#1872cb","#3444a3","#13c2c2","#722ed1","#eb2f96","#a0d911","#34d399","#d946ef","#ff85c0","#b37feb","#9d174d","#ffa39e","#69b1ff"],tQ={size:220,inner:.62,outer:.88,padAngle:2};function nQ(e,t,a,o,c,d){const f=P=>(P-90)*Math.PI/180,p=(P,R)=>[zt(e+P*Math.cos(f(R))),zt(t+P*Math.sin(f(R)))],h=d-c;if(h>=359.999){const[P,R]=p(a,0),[C,E]=p(a,180),[D,I]=p(o,0),[O,_]=p(o,180);return`M ${P} ${R} A ${a} ${a} 0 1 1 ${C} ${E} A ${a} ${a} 0 1 1 ${P} ${R} Z M ${D} ${I} A ${o} ${o} 0 1 0 ${O} ${_} A ${o} ${o} 0 1 0 ${D} ${I} Z`}const[b,y]=p(a,c),[v,j]=p(a,d),[w,S]=p(o,d),[N,k]=p(o,c),A=h>180?1:0;return`M ${b} ${y} A ${a} ${a} 0 ${A} 1 ${v} ${j} L ${w} ${S} A ${o} ${o} 0 ${A} 0 ${N} ${k} Z`}const sQ="#9aa0a6";function LD(e){const t=new Map;for(const a of Array.isArray(e)?e:[]){const o=String(a?.label??a?.model??a?.id??"").trim();!o||t.has(o)||(Number(a?.totalTokens??a?.tokens)||0)>0&&t.set(o,px[t.size%px.length])}return t}function zD(e,t){const a=(Array.isArray(e)?e:[]).map(k=>({label:String(k?.label??k?.model??k?.id??"").trim()||t,tokens:Number(k?.totalTokens??k?.tokens)||0,requests:Number(k?.requests)||0})).filter(k=>k.tokens>0);if(!a.length)return null;const o=a.reduce((k,A)=>k+A.tokens,0);if(!o)return null;const c=LD(e),{size:d,inner:f,outer:p,padAngle:h}=tQ,b=d/2,y=d/2,v=d/2*p,j=d/2*f;let w=0;const S=[],N=[];return a.forEach((k,A)=>{const P=k.tokens/o,R=P*360,C=a.length>1?Math.min(h/2,R/4):0,E=w+C,D=w+R-C;w+=R;const I=c.get(k.label)??px[A%px.length];let O=null;if(P>=.03){const _=(E+D)/2,z=j+(v-j)*.6,H=(_-90)*Math.PI/180;O={x:zt(b+z*Math.cos(H)),y:zt(y+z*Math.sin(H)),text:`${Math.round(P*100)}%`}}D>E&&S.push({key:`${A}-${k.label}`,d:nQ(b,y,v,j,E,D),fill:I,evenOdd:R>=359.999,label:O,tip:`${k.label} · ${os(k.tokens)} tokens · ${rc(P)}`}),N.push({key:`${A}-${k.label}`,fill:I,name:k.label,tokensText:os(k.tokens),percentText:rc(P),tip:r("{name} · {tokens} tokens · {n} 次请求 · {pct}",{name:k.label,tokens:os(k.tokens),n:sc(k.requests),pct:rc(P)})})}),{size:d,slices:S,legend:N,totalText:os(o)}}const rQ=[1,1.25,1.5,2,2.5,3,4,5,6,8,10];function aQ(e){if(!(e>0))return 1;const t=10**Math.floor(Math.log10(e)),a=e/t;let o=1;for(const c of rQ)c<=a+1e-9&&(o=c);return o*t}function lQ(e){const t=Number(e)||0;if(t<=0)return[0,1,2,3,1/0];const a=Math.max(1,aQ(t/4));return[0,a,a*2,a*3,1/0]}function oQ(e,t){if(e===0)return"0";const a=t[e-1],o=t[e];return Number.isFinite(o)?a===0?`≤${os(o)}`:`${os(a)}–${os(o)}`:`>${os(a)}`}function BD(e){const t=Array.isArray(e)?e:[];return lQ(t.reduce((a,o)=>Math.max(a,Number(o?.tokens)||0),0))}function iQ(e,t){const a=Array.isArray(e)?e:[];if(!a.length)return null;const o=(dx(a[0].date).getDay()+6)%7,c=new Array(o).fill(null).concat(a),d=Math.ceil(c.length/7),f=3,p=20,h=t-p,b=Math.floor((h-f*(d-1))/d),y=Math.max(7,Math.min(26,b)),v=y+3,j=y+f,w=p+d*j-f,S=Math.max(0,Math.round((t-w)/2)),N=v+7*j-f+2,k=Math.max(w,Math.round(t)),A=BD(a),P=O=>A.findIndex(_=>Number(O)<=_),R=[];for(let O=0;O({key:_,x:S+p-6,y:zt(v+O*j+y/2),text:_})),E=[];let D=-1,I=-9;for(let O=0;O({level:t,text:oQ(t,e)}))}function uQ(e){const t=e||{};return[["last10m",r("近 10 分钟")],["last1h",r("近 1 小时")],["last24h",r("近 24 小时")],["last7d",r("近 7 天")]].map(([o,c])=>{const d=t[o]||{},f=Number(d.inputTokens)||0;return{key:o,label:c,value:f?rc(d.rate):"—",sub:r("命中 {hit} / 输入 {input}",{hit:os(d.hitTokens),input:os(f)})}})}function dQ(e,t,a){const o=Array.isArray(e)?e:[];if(!o.length)return null;const c=230,d={left:44,right:56,top:26,bottom:24},f=Math.max(40,t-d.left-d.right),p=c-d.top-d.bottom,h=o.map(K=>Number(K.rate)||0),b=o.map(K=>Number(K.totalTokens)||0),y=Math.max(1,E0(Math.max(...h))),v=Math.max(...b),j=E0(v),w=v>0,S=K=>d.left+(o.length>1?f*K/(o.length-1):f/2),N=K=>d.top+p-p*K/y,k=K=>d.top+p-p*K/j,A=[],P=[],R=[];for(let K=0;K<=4;K+=1){const q=y*K/4,Q=zt(N(q)),G=q*100;A.push({key:`g${K}`,y:Q}),P.push({key:`r${K}`,x:d.left-8,y:Q,anchor:"end",text:`${Number.isInteger(G)?G:G.toFixed(1)}%`}),w&&R.push({key:`t${K}`,x:zt(d.left+f+8),y:Q,anchor:"start",text:OD(j*K/4,j)})}const C=o.length===1?4.5:2.5,E=(K,q)=>({points:K.map((Q,G)=>`${zt(S(G))},${zt(q(Q))}`).join(" "),dots:K.map((Q,G)=>({key:`d${G}`,cx:zt(S(G)),cy:zt(q(Q))}))}),D=[],I=(K,q,Q,G)=>{const J=ux(Q),Y=G==="middle"?K-J/2:G==="end"?K-J:K,re={left:Y,right:Y+J,top:q-8.5,bottom:q+2.5};return D.some(M=>re.leftM.left-2&&re.topM.top-1)?null:(D.push(re),{key:`${Q}-${K}-${q}`,x:zt(K),y:zt(q),text:Q,anchor:G})},O=(K,q)=>{const Q=ux(q)/2;return K-Qd.left+f+6?"end":"middle"},_=[];w&&o.forEach((K,q)=>{if(!(Number(K.totalTokens)>0))return;const Q=k(b[q]),G=Q-12>=d.top-10,J=os(b[q]),Y=I(S(q),G?Q-12:Q+13,J,O(S(q),J));Y&&_.push({...Y,key:`tl${q}`})});const z=[];o.forEach((K,q)=>{if(!((Number(K.inputTokens)||0)+(Number(K.hitTokens)||0)>0))return;const G=N(h[q]),J=G+15<=d.top+p+8,Y=rc(h[q]),re=I(S(q),J?G+13:G-7,Y,O(S(q),Y));re&&z.push({...re,key:`rl${q}`})});const H=o.length>1?f/(o.length-1):f,B=d.left,L=d.left+f,F=o.length<=RD?o.map((K,q)=>{const Q=Math.max(B,S(q)-H/2),G=Math.min(L,S(q)+H/2);return{key:`h${q}`,x:zt(Q),width:zt(G-Q),tip:ZX(K,a)}}):null,$=Math.max(1,Math.ceil(o.length/8)),X=[];for(let K=0;K=o.length;X.push({key:`x${K}`,x:zt(S(K)),y:c-8,anchor:K===0?"start":q?"end":"middle",text:MD(o[K].hour)})}return{width:t,height:c,plotLeft:B,plotW:f,plotH:p,plotTop:d.top,grid:A,rateTicks:P,tokenTicks:R,rateLine:E(h,N),tokenLine:w?E(b,k):null,dotR:C,rateLabels:z,tokenLabels:_,hourTicks:X,hits:F}}const fQ=13;function pQ(e,t,a){const o=Array.isArray(e)?e:[];if(!o.length)return null;const c=240,d={left:50,right:14,top:26,bottom:26},f=Math.max(40,t-d.left-d.right),p=f/o.length,h=o.map($=>Number($.tokens)>0?os($.tokens):""),b=Math.max(0,...h.map(ux)),y=h.every($=>!$)||b+4<=p,v=!y&&p>=fQ;v&&(d.top=10+Math.ceil(b*1.25));const j=c-d.top-d.bottom,w=o.map($=>Number($.tokens)||0),S=Math.max(...w),N=E0(S),k=Math.max(1,Math.min(28,p*.68)),A=d.top+j,P=$=>d.top+j-j*$/N,R=o.length<=RD,C=S<=0,E=[],D=[];if(!C)for(let $=0;$<=4;$+=1){const X=N*$/4,K=zt(P(X));E.push({key:`g${$}`,x1:d.left,y:K,x2:zt(d.left+f)}),D.push({key:`v${$}`,x:d.left-8,y:K,anchor:"end",text:OD(X,N)})}const I=[];o.forEach(($,X)=>{const K=Number($.tokens)||0;if(K<=0)return;const q=P(K);I.push({key:String($.date??X),x:zt(d.left+p*X+(p-k)/2),y:zt(q),width:zt(k),height:zt(Math.max(1,A-q)),rx:k>4?2:1,tip:ID($),nativeTip:!R})});const O=[],_=[],z=($,X)=>{const K=h[$],q=P(Number(o[$].tokens)||0),Q=zt(d.left+p*$+p/2);if(v)return{key:`b${$}`,x:Q,y:zt(q-6),anchor:"start",text:K,rotate:!0};const G=q-6,J=G-9M.leftU.left-2&&M.topU.top-1))return null;_.push(M)}return{key:`b${$}`,x:Q,y:Y,anchor:"middle",text:K}};if(y||v)h.forEach(($,X)=>{if(!$)return;const K=z(X,!1);K&&O.push(K)});else{const $=o.map((X,K)=>({index:K,value:Number(X.tokens)||0})).filter(X=>X.value>0).sort((X,K)=>K.value-X.value);for(const X of $){if(O.length>=8)break;const K=z(X.index,!0);K&&O.push(K)}}const H=R?o.map(($,X)=>({key:`h${X}`,x:zt(d.left+p*X),width:zt(p),tip:ID($,a)})):null,B=Math.max(1,Math.ceil(o.length/6)),L=[];for(let $=0;${const X=o.length===1,K=!X&&$===o.length-1,q=dx(o[$].date);return{key:`d${$}`,x:X?d.left+f/2:K?d.left+f:zt(d.left+p*$+p/2),y:c-8,anchor:X?"middle":K?"end":$===0?"start":"middle",text:`${q.getMonth()+1}/${q.getDate()}`}});return{width:t,height:c,plotLeft:d.left,plotW:f,plotH:j,plotTop:d.top,grid:E,valueTicks:D,bars:I,barLabels:O,dateTicks:F,hits:H,blank:C}}function ac(){return window}const HD=1e3,mQ=ix.map(e=>({value:e,label:FX[e]})),hQ=r("所选范围内每个账号各消耗了多少 Token,按 Token 用量从多到少排。账号是比提供商更细的一维:同一家可以挂多个账号,转发时按优先级在候选链上依次尝试,所以这里反映的是「具体哪个登录态在出力」。百分比按本区间的总 Token 数算(这一块只看用量,请求次数与成功率在概览卡片里)。「未知账号」是指那批请求没有账号身份:走默认登录态转发(未配置账号列表)时会这样;这一维上线前写出的旧聚合行也没有账号明细,但它们会在升级导入旧数据时按明细自动补算回来 —— 只有明细已被手动清理掉的那几天补不回来,仍留在「未知账号」里,那是确实无从恢复的部分。"),gQ=r("所选范围内每个提供商各消耗了多少 Token,按 Token 用量从多到少排。同一个模型名可能有多家都能提供,网关按设置页「转发路由」的优先级依次尝试,所以占比也反映了实际落到谁身上。百分比按本区间的总 Token 数算(这一块只看用量,请求次数与成功率在概览卡片里)。「未知」是指那批请求没记下承载它的提供商 —— 主要是记录提供商这个功能上线之前的旧明细,其次是请求在选定上游之前就失败了(请求体非法、模型不存在、没有可用账号)。这一维与账号那一维不同:旧明细里根本没有「哪家承载」的信息(早期版本只有单一上游,但那是配置事实而非逐条记录),所以无法回算,旧数据会一直留在「未知」里;此后新产生的请求都会记上具体的提供商。"),xQ=r("所选范围内每个模型各消耗了多少 Token,按用量从多到少排,扇区角度即占比。中心是这一维的合计(等于概览里的总 Token),右侧每行给出该模型的 Token 用量与百分比。扇区内的百分比只在 ≥3% 时标出,更小的会挤成一团 —— 完整读数在右侧列表与悬停气泡里。颜色按用量排名分配:最大的那段是红色,依次往后;同一份报表里换个维度看,配色口径不变。"),bQ=r("所选范围内每个提供商各消耗了多少 Token,按用量从多到少排,扇区角度即占比。同一个模型名可能有多家都能提供,网关按设置页「转发路由」的优先级依次尝试,所以占比也反映了实际落到谁身上。中心是这一维的合计(等于概览里的总 Token),右侧每行给出该提供商的 Token 用量与百分比。「未知」是指那批请求没记下承载它的提供商 —— 主要是记录提供商这个功能上线之前的旧明细,其次是请求在选定上游之前就失败了。"),vQ=r("命中率 = 缓存读取 Token / 输入 Token(promptTokens)。窗口越短越贴近「此刻」:上游把缓存读取与输入分开上报时,该比值合法地可能超过 100%,此处不夹取值、如实展示。"),yQ=r("每天的总 Token 用量(输入 + 输出)。柱顶标出当天的读数;区间很长、柱子挤到放不下时只标最高的那几天,其余悬停柱子即可读到。");let mx=HD,hx=!0,A0=!1,R0=!1,O0=0,Uo=null,lc=null,gx=null;function oc(e,t="empty"){return s.jsx("div",{className:t,style:{padding:"14px 0"},children:e})}function xx({text:e}){return s.jsx("span",{className:"tip-q","data-tip":e})}function jQ({accountId:e}){const t=(ac().wbApp?.getState?.()?.accounts?.accounts||[]).find(f=>f?.id===e),a=typeof t?.provider=="string"?t.provider:"";if(!a)return null;const o=ac().wbProviders?.labelOf?.(a)||a,c=t&&ac().wbAccountsModel?.editionSuffix?.(t)||"",d=c?`${o} ${c}`:o;return s.jsx("span",{className:`pbadge p-${a}`,title:r("提供商:{text}",{text:d}),children:d})}function wQ({summary:e,range:t}){const a=Array.isArray(e.dailyTrend)?e.dailyTrend:[];return s.jsx(s.Fragment,{children:eQ(e.overview,t,a.length).map(o=>s.jsxs("div",{className:"field",children:[s.jsx("div",{className:"label",children:o.label}),s.jsxs("div",{className:o.mono?"value mono":"value",children:[o.value,o.sub?s.jsx("div",{className:"sub",children:o.sub}):null]})]},o.key))})}function UD({panelId:e,listId:t,labelId:a,title:o,tip:c,rows:d,totalText:f,withBadge:p,emptyText:h}){return s.jsxs("section",{className:"panel",id:e,children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:o}),s.jsx(xx,{text:c}),s.jsx("span",{className:"panel-sub",id:a,children:f})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"rank-shares",id:t,children:d.length?d.map(b=>s.jsxs("div",{className:"rank-row","data-tip":b.tip,children:[s.jsxs("span",{className:"name",title:b.full,children:[p?s.jsx(jQ,{accountId:b.id}):null,b.name]}),s.jsx("span",{className:"track",children:s.jsx("span",{className:"bar",style:{width:b.barWidth}})}),s.jsx("span",{className:"num",title:`${b.tokensText} tokens`,children:b.tokensText}),s.jsx("span",{className:"pct",children:b.percentText})]},b.key)):oc(h)})})]})}function VD({panelId:e,listId:t,title:a,tip:o,ariaLabel:c,view:d,emptyText:f}){return s.jsxs("section",{className:"panel",id:e,children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:a}),s.jsx(xx,{text:o})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{id:t,children:d?s.jsxs("div",{className:"donut-layout",children:[s.jsxs("div",{className:"donut-wrap",children:[s.jsx("svg",{className:"donut-svg",width:d.size,height:d.size,viewBox:`0 0 ${d.size} ${d.size}`,role:"img","aria-label":c,children:d.slices.map(p=>s.jsxs(x.Fragment,{children:[s.jsx("path",{className:"donut-slice",d:p.d,fill:p.fill,fillRule:p.evenOdd?"evenodd":void 0,tabIndex:-1,"data-tip":p.tip}),p.label?s.jsx("text",{className:"donut-label",x:p.label.x,y:p.label.y,textAnchor:"middle",dominantBaseline:"central",children:p.label.text}):null]},p.key))}),s.jsxs("div",{className:"donut-center",children:[s.jsx("div",{className:"donut-center-value",children:d.totalText}),s.jsx("div",{className:"donut-center-label",children:r("总 Token")})]})]}),s.jsx("div",{className:"donut-legend",children:d.legend.map(p=>s.jsxs("div",{className:"donut-legend-row","data-tip":p.tip,children:[s.jsx("span",{className:"donut-dot",style:{background:p.fill}}),s.jsx("span",{className:"donut-legend-name",title:p.name,children:p.name}),s.jsx("span",{className:"donut-legend-tokens",children:p.tokensText}),s.jsx("span",{className:"donut-legend-percent",children:p.percentText})]},p.key))})]}):oc(f)})})]})}function SQ({view:e}){return s.jsxs("svg",{className:"report-svg",width:e.width,height:e.height,viewBox:`0 0 ${e.width} ${e.height}`,role:"img","aria-label":r("近 365 天活跃热力图"),children:[e.months.map(t=>s.jsx("text",{className:"hm-axis",x:t.x,y:10,children:t.text},t.key)),e.weekdays.map(t=>s.jsx("text",{className:"hm-axis",x:t.x,y:t.y,textAnchor:"end",dominantBaseline:"middle",children:t.text},t.key)),e.cells.map(t=>s.jsx("rect",{className:`hm-cell l${t.level}`,x:t.x,y:t.y,width:t.size,height:t.size,rx:2,tabIndex:-1,"data-tip":t.tip},t.key))]})}function FD({line:e,cls:t,radius:a}){return s.jsxs(s.Fragment,{children:[s.jsx("polyline",{className:`chart-line ${t}`,points:e.points}),e.dots.map(o=>s.jsx("circle",{className:`chart-dot ${t}`,cx:o.cx,cy:o.cy,r:a},o.key))]})}function M0({items:e,cls:t}){return s.jsx(s.Fragment,{children:e.map(a=>s.jsx("text",{className:`chart-label ${t}`,x:a.x,y:a.y,textAnchor:a.anchor,transform:a.rotate?`rotate(-90 ${a.x} ${a.y})`:void 0,dominantBaseline:a.rotate?"central":void 0,children:a.text},a.key))})}function NQ({view:e}){const{width:t,height:a,plotLeft:o,plotW:c,plotTop:d,plotH:f}=e;return s.jsxs(s.Fragment,{children:[s.jsxs("svg",{className:"report-svg",width:t,height:a,viewBox:`0 0 ${t} ${a}`,role:"img","aria-label":r("近 24 小时缓存命中率与总 Token 趋势"),children:[e.grid.map(p=>s.jsx("line",{className:"chart-grid",x1:o,y1:p.y,x2:zt(o+c),y2:p.y},p.key)),e.rateTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,dominantBaseline:"middle",children:p.text},p.key)),e.tokenTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,dominantBaseline:"middle",children:p.text},p.key)),e.tokenLine?s.jsx(FD,{line:e.tokenLine,cls:"tokens",radius:e.dotR}):null,s.jsx(FD,{line:e.rateLine,cls:"rate",radius:e.dotR}),s.jsx(M0,{items:e.tokenLabels,cls:"tokens"}),s.jsx(M0,{items:e.rateLabels,cls:"rate"}),e.hourTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,children:p.text},p.key))]}),e.hits?s.jsx("svg",{className:"report-svg chart-hit-layer",width:t,height:a,viewBox:`0 0 ${t} ${a}`,"aria-hidden":"true",children:e.hits.map(p=>s.jsx("rect",{className:"chart-hit",x:p.x,y:d,width:p.width,height:zt(f),tabIndex:-1,"data-tip":p.tip,"data-tip-variant":"plain"},p.key))}):null]})}function kQ({view:e}){const{width:t,height:a,plotLeft:o,plotW:c,plotTop:d,plotH:f}=e;return s.jsxs(s.Fragment,{children:[s.jsxs("svg",{className:"report-svg",width:t,height:a,viewBox:`0 0 ${t} ${a}`,role:"img","aria-label":r("按天 Token 趋势"),children:[e.grid.map(p=>s.jsx("line",{className:"chart-grid",x1:p.x1,y1:p.y,x2:p.x2,y2:p.y},p.key)),e.valueTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,dominantBaseline:"middle",children:p.text},p.key)),e.bars.map(p=>p.nativeTip?s.jsx("rect",{className:"bar",x:p.x,y:p.y,width:p.width,height:p.height,rx:p.rx,children:s.jsx("title",{children:p.tip})},p.key):s.jsx("rect",{className:"bar",x:p.x,y:p.y,width:p.width,height:p.height,rx:p.rx},p.key)),s.jsx(M0,{items:e.barLabels,cls:"tokens"}),e.dateTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,children:p.text},p.key)),e.blank?s.jsx("text",{className:"chart-empty",x:zt(o+c/2),y:zt(d+f/2),textAnchor:"middle",children:r("所选范围内暂无请求")}):null]}),e.hits?s.jsx("svg",{className:"report-svg chart-hit-layer",width:t,height:a,viewBox:`0 0 ${t} ${a}`,"aria-hidden":"true",children:e.hits.map(p=>s.jsx("rect",{className:"chart-hit",x:p.x,y:d,width:p.width,height:zt(f),tabIndex:-1,"data-tip":p.tip,"data-tip-variant":"plain"},p.key))}):null]})}const CQ=680;function D0(){const e=x.useRef(null),[t,a]=x.useState(0);return x.useLayoutEffect(()=>{const o=e.current;if(!o)return;let c=o.clientWidth;if(c&&a(c),typeof ResizeObserver!="function")return;const d=new ResizeObserver(()=>{const f=o.clientWidth;!f||f===c||(c=f,a(f))});return d.observe(o),()=>d.disconnect()},[]),[e,t||CQ]}async function $D(){if(!A0)try{const e=await ac().workbuddyDesktop?.getScheduledTasks(),t=(e?.tasks||[]).find(a=>a.id==="reportAutoRefresh");I0(t||null),A0=Array.isArray(e?.tasks)}catch(e){console.warn("读取报表自动刷新间隔失败,按默认 1 秒:",e instanceof Error?e.message:e),I0(null)}}function I0(e){A0=!0;const t=Number(e?.interval);!!e&&typeof e=="object"&&Number.isFinite(t)&&t>0&&(e.unit==="seconds"||e.unit==="minutes")?(hx=e.enabled!==!1,mx=e.unit==="minutes"?t*6e4:t*1e3):(hx=!0,mx=HD),lc?.applyAutoConfig(mx,hx)}const TQ={summary:null,error:null};function EQ(){const[e,t]=x.useState(TQ),[a,o]=x.useState($X),[c,d]=x.useState(GX),[f,p]=x.useState(()=>({ms:mx,enabled:hx})),[,h]=x.useState(0),b=x.useRef(a),y=x.useRef(c),v=x.useRef(""),j=x.useCallback((Y,re)=>{v.current=re,t(Y)},[]),w=x.useCallback(async(Y={})=>{$D();const re=++O0,M=b.current,U=M===k0?y.current:void 0;try{const Z=ac().workbuddyDesktop;if(!Z)throw new Error("后端桥不可用");const ae=await Z.getStatsSummary(M,U);if(re!==O0)return Uo;if(!ae||typeof ae!="object")throw new Error("后端未返回报表数据");Uo=ae;const ce=JSON.stringify(ae);return ce!==v.current&&j({summary:ae,error:null},ce),Uo}catch(Z){if(re!==O0)return Uo;const ae=Z instanceof Error?Z.message:"";return Uo=null,Y.silent||console.warn("读取报表数据失败:",ae),j({summary:null,error:ae||r("未知错误")},""),null}},[j]),S=x.useCallback(Y=>{Y!==void 0&&(Uo=Y||null,Y&&j({summary:Y,error:null},JSON.stringify(Y)))},[j]),N=x.useCallback(Y=>{const re=ix.includes(Y)?Y:N0;if(re!==b.current){b.current=re,o(re);try{localStorage.setItem(TD,re)}catch{}w()}},[w]),k=x.useCallback(Y=>{const re={...y.current,...Y};if(!cx.test(re.start)||!cx.test(re.end))return;const M=re.start<=re.end?re:Y.start?{start:re.start,end:re.start}:{start:re.end,end:re.end};y.current=M,d(M),KX(M),b.current===k0&&w()},[w]);x.useEffect(()=>{if(lc={load:w,render:S,applyAutoConfig:(Y,re)=>p({ms:Y,enabled:re})},gx){const Y=gx;gx=null,S(Y.data)}return ac().wbApp?.currentPage==="overview"&&w({silent:!0}),()=>{lc=null}},[w,S]),x.useEffect(()=>{if(!f.enabled||f.ms<=0)return;const Y=window.setInterval(()=>{document.hidden||ac().wbApp?.currentPage!=="overview"||R0||(R0=!0,w({silent:!0}).finally(()=>{R0=!1}))},f.ms);return()=>{window.clearInterval(Y)}},[f,w]),x.useEffect(()=>{const Y=()=>h(re=>re+1);return window.addEventListener("wb-units-changed",Y),()=>window.removeEventListener("wb-units-changed",Y)},[]);const A=D0(),P=D0(),R=D0(),{summary:C,error:E}=e,D=C&&ix.includes(C.range??"")?C.range:a,I=C&&Array.isArray(C.heatmap)?C.heatmap:[],O=C&&Array.isArray(C.cacheTrend24h)?C.cacheTrend24h:[],_=C&&Array.isArray(C.dailyTrend)?C.dailyTrend:[],z=C&&Array.isArray(C.providers)?C.providers:null,H=C&&Array.isArray(C.accounts)?C.accounts:null,B=C&&Array.isArray(C.models)?C.models:null,L=E?oc(r("读取报表失败:{error}",{error:E}),"empty report-error"):null,F=oc(r("正在加载…")),$=L??F,X=x.useMemo(()=>LD(B||[]),[B]),K=x.useCallback(Y=>X.get(Y)||sQ,[X]),q=C?iQ(I,A[1]):null,Q=C?dQ(O,P[1],K):null,G=C?pQ(_,R[1],K):null,J=C0(new Date);return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("统计概览")}),s.jsx("span",{className:"panel-sub",id:"report-range-label",children:AD[D]||""}),s.jsxs("div",{className:"head-actions",children:[s.jsx(En,{options:mQ,value:a,onValueChange:N,"aria-label":r("报表时间范围")}),a===k0?s.jsxs("span",{className:"report-date-range",children:[s.jsx(Fe,{type:"date",className:"report-date-input w-[132px]",value:c.start,max:c.end||J,"aria-label":r("开始日期"),title:r("起始日期(含当天)"),onChange:Y=>k({start:Y.target.value})}),s.jsx("span",{className:"report-date-sep","aria-hidden":"true",children:"~"}),s.jsx(Fe,{type:"date",className:"report-date-input w-[132px]",value:c.end,min:c.start||void 0,max:J,"aria-label":r("结束日期"),title:r("结束日期(含当天)"),onChange:Y=>k({end:Y.target.value})})]}):null]})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"field-grid",id:"report-overview",children:C?s.jsx(wQ,{summary:C,range:D}):$})})]}),s.jsxs("div",{className:"report-rank-grid",children:[H?s.jsx(UD,{panelId:"report-accounts-panel",listId:"report-accounts",labelId:"report-accounts-label",title:r("Top 账号"),tip:hQ,rows:PD(H)||[],totalText:_D(H),withBadge:!0,emptyText:r("所选范围内还没有账号用量")}):null,z?s.jsx(UD,{panelId:"report-providers-panel",listId:"report-providers",labelId:"report-providers-label",title:r("Top 提供商"),tip:gQ,rows:PD(z)||[],totalText:_D(z),withBadge:!1,emptyText:r("所选范围内还没有请求记录")}):null]}),s.jsxs("div",{className:"report-donut-grid",children:[B?s.jsx(VD,{panelId:"report-models-panel",listId:"report-models-donut",title:r("模型用量"),tip:xQ,ariaLabel:r("模型用量占比"),view:zD(B,r("未知模型")),emptyText:r("所选范围内还没有模型用量")}):null,z?s.jsx(VD,{panelId:"report-providers-pie-panel",listId:"report-providers-donut",title:r("提供商用"),tip:bQ,ariaLabel:r("提供商用占比"),view:zD(z,r("未知")),emptyText:r("所选范围内还没有提供商用量")}):null]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("活跃热力图")}),s.jsx("span",{className:"panel-sub",children:r("近 365 天,按天 Token 用量着色(档位按本窗口峰值自动定)")})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"heat-wrap",id:"report-heatmap",ref:A[0],children:C?q?s.jsx(SQ,{view:q}):oc(r("暂无热力图数据")):$})}),s.jsxs("div",{className:"panel-foot",children:[s.jsx("span",{className:"heat-scale-label",children:r("Token")}),s.jsx("span",{className:"heat-legend",id:"report-heat-legend",children:C?cQ(BD(I)).map(Y=>s.jsxs("span",{className:"heat-legend-item",children:[s.jsx("span",{className:`l${Y.level}`}),Y.text]},Y.level)):null}),s.jsx("div",{className:"spacer"}),s.jsx("span",{children:r("方格为本地自然日,无请求显示为空槽")})]})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("缓存命中率")}),s.jsx(xx,{text:vQ})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"field-grid",id:"report-cache-rates",children:C?uQ(C.cacheRates).map(Y=>s.jsxs("div",{className:"field rate",children:[s.jsx("div",{className:"label",children:Y.label}),s.jsxs("div",{className:"value big",children:[Y.value,s.jsx("div",{className:"sub",children:Y.sub})]})]},Y.key)):$})})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("近 24 小时缓存命中率趋势")}),s.jsx("span",{className:"panel-sub",children:r("按本地整点,无请求的整点不标注")})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"chart-wrap",id:"report-cache-trend",ref:P[0],children:C?Q?s.jsx(NQ,{view:Q}):oc(r("暂无缓存趋势数据")):$})}),s.jsxs("div",{className:"panel-foot",children:[s.jsxs("span",{className:"chart-legend",children:[s.jsx("span",{className:"swatch rate"}),r("缓存命中率"),s.jsx("span",{className:"axis-hint",children:r("左轴")})]}),s.jsxs("span",{className:"chart-legend",children:[s.jsx("span",{className:"swatch tokens"}),r("总 Token"),s.jsx("span",{className:"axis-hint",children:r("右轴")})]}),s.jsx("div",{className:"spacer"}),s.jsx("span",{children:r("无请求的整点按 0% 计,但不写读数")})]})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("按天 Token 趋势")}),s.jsx(xx,{text:yQ}),s.jsx("span",{className:"panel-sub",id:"report-trend-label",children:C?`${C.startDate||"—"} ~ ${C.endDate||"—"}`:"—"})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"chart-wrap tall",id:"report-daily-trend",ref:R[0],children:C?G?s.jsx(kQ,{view:G}):oc(r("暂无趋势数据")):$})})]})]})}async function AQ(e={}){return lc?lc.load(e):Uo}function RQ(e){if(e!==void 0){if(!lc){gx={data:e??null};return}lc.render(e)}}function OQ(){return Uo}window.wbReport={load:AQ,render:RQ,lastSummary:OQ,applyAutoRefresh:I0};const qD='.page[data-page="overview"]';let GD=!1;function KD(){if(GD)return;const e=document.querySelector(qD);e&&(GD=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(EQ,{})))}document.querySelector(qD)?KD():document.addEventListener("DOMContentLoaded",KD,{once:!0}),$D();const P0={all:{title:r("全部删除"),desc:r("删除日志记录本身。当前有筛选时只删命中的条目,按天聚合报表不受影响;无筛选时清空全部并重置报表。此方式无法恢复。")},raw:{title:r("仅清空报文原文"),desc:r("保留统计行与报表,只抹掉请求 / 响应正文。清理后详情弹窗的「预览对话」将无原文可看,统计数字分毫不动。")}},MQ=["all","raw"],DQ=3e3;function Pl(){return window}let yp=!1;function jp(e,t){Pl().wbApp?.toast?.(e,t)}function IQ(e){const t=Math.max(0,Number(e)||0);if(t<1024)return`${Math.round(t)} B`;const a=t/1024;if(a<1024)return`${a.toFixed(1)} KB`;const o=a/1024;return o<1024?`${o.toFixed(1)} MB`:`${(o/1024).toFixed(2)} GB`}function _0(){const e=Pl().wbRequestsPanel?.clearParams?.();return typeof e=="string"?e:""}function YD(e){return{all:Number(e?.all)||0,raw:Number(e?.raw)||0,dbBytes:Number(e?.dbBytes)||0,vacuumRunning:e?.vacuumRunning===!0}}function L0(e){return e instanceof Error?e.message:String(e)}function XD(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t]??t)}function PQ({onClose:e}){const[t,a]=x.useState("all"),[o,c]=x.useState({status:"loading"}),[d,f]=x.useState(""),[p,h]=x.useState(!1),[b,y]=x.useState(!1),v=x.useRef(!0),j=x.useRef(null),w=x.useCallback(D=>{yp=D,y(D)},[]),S=x.useCallback(()=>{j.current!==null&&(window.clearInterval(j.current),j.current=null)},[]),N=x.useCallback(D=>{c({status:"ready",all:D.all,raw:D.raw,dbBytes:D.dbBytes}),h(D.vacuumRunning)},[]),k=x.useCallback(async()=>{const D=Pl().workbuddyDesktop;if(!D)return;let I;try{I=await D.getStatsClearPreview(_0())}catch{return}if(!v.current)return;const O=YD(I);N(O),!O.vacuumRunning&&(S(),f(""),jp(r("✅ 压缩完成")),Pl().wbRequestsPanel?.load?.({silent:!0}))},[N,S]),A=x.useCallback(()=>{j.current===null&&(h(!0),j.current=window.setInterval(()=>{k()},DQ))},[k]);async function P(){c({status:"loading"});try{const D=Pl().workbuddyDesktop;if(!D)throw new Error(r("后端桥不可用"));const I=await D.getStatsClearPreview(_0());if(!v.current)return;const O=YD(I);N(O),O.vacuumRunning&&A()}catch(D){if(!v.current)return;c({status:"failed"}),f(r("预览读取失败:{error}",{error:L0(D)}))}}x.useEffect(()=>(v.current=!0,P(),()=>{v.current=!1,S(),yp=!1}),[]);async function R(){const D=Pl().workbuddyDesktop;if(D){h(!0);try{await D.compactStatsDb(),f(r("压缩已在后台开始,完成后会自动提示")),A()}catch(I){const O=L0(I);if(/409|正在进行/.test(O)){jp(r("压缩已在进行中")),f(r("压缩已在进行中,接上它的进度等待完成")),A();return}h(!1),f(r("压缩失败:{message}",{message:O})),jp(r("压缩失败:{message}",{message:O}),"err")}}}async function C(){if(yp)return;const D=Pl().workbuddyDesktop,I=Pl().wbConfirm?.ask;if(!D||!I)return;const O=P0[t].title,_=_0(),z=_.length>0,H=o.status==="ready"?t==="raw"?o.raw:o.all:0;if(await I({title:r("清理请求日志"),html:z?r("确定按当前筛选执行「{label}」?将处理 {count} 条,此操作无法恢复。",{label:XD(O),count:H}):r("确定对全部请求日志执行「{label}」?将处理 {count} 条,此操作无法恢复。",{label:XD(O),count:H}),okText:r(t==="raw"?"抹掉原文":"删除"),okClass:"danger"})){w(!0);try{const L=z?`mode=${t}&${_}`:`mode=${t}&all=1`,F=await D.clearStatsRequests(L),$=Number(F?.deleted)||0;jp(t==="raw"?r("已抹掉 {count} 条报文原文",{count:$}):r("已删除 {count} 条",{count:$})),w(!1),e(),Pl().wbRequestsPanel?.notifyCleared?.()}catch(L){const F=L0(L);f(r("清理失败:{message}",{message:F})),jp(r("清理失败:{message}",{message:F}),"err"),w(!1)}}}const E=o.status==="ready"?r("将删除 {count} 条日志 · 其中 {raw} 条仍带报文原文 · 数据库占用 {db}",{count:o.all,raw:o.raw,db:IQ(o.dbBytes)}):o.status==="failed"?r("预览读取失败"):r("正在统计…");return s.jsx(Yt,{open:!0,onOpenChange:(D,I)=>{if(!D){if(yp){I.cancel();return}e()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("清理请求日志")})}),s.jsxs(Lt,{children:[s.jsx(Ph,{"aria-label":r("清理方式"),value:t,onValueChange:D=>a(D==="raw"?"raw":"all"),children:MQ.map(D=>{const I=t===D;return s.jsxs("label",{"data-checked":I?"":void 0,className:"group/card grid cursor-pointer grid-cols-[auto_minmax(0,1fr)] items-center gap-x-2.5 gap-y-0.5 rounded-md border border-border px-3 py-2.5 transition-colors duration-150 ease-out hover:border-border-strong data-checked:border-primary data-checked:bg-primary-soft",children:[s.jsx(yo,{value:D,className:"row-span-2 self-center"}),s.jsx("span",{className:"text-[13px] font-semibold text-foreground group-data-checked/card:text-primary-fg",children:P0[D].title}),s.jsx("span",{className:"text-[11.5px] leading-[1.55] text-subtle",children:P0[D].desc})]},D)})}),s.jsx("p",{className:"text-[11.5px] text-muted-foreground",children:E})]}),s.jsxs(tn,{children:[s.jsx("span",{className:"min-w-0 text-[11.5px] text-muted-foreground",children:d}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>{R()},disabled:p,title:r(p?"压缩正在后台执行,完成后自动恢复":"回收已删除数据占用的磁盘空间(checkpoint + VACUUM,后台执行)"),children:r(p?"压缩中…":"压缩数据库")}),s.jsx(ne,{variant:"outline",onClick:e,disabled:b,children:r("取消")}),s.jsx(ne,{variant:"destructive",onClick:()=>{C()},disabled:b,children:r(b?"清理中…":"执行清理")})]})]})})}let wp=null,Qu=null;function QD(){wp&&(wp.unmount(),wp=null),Qu&&(Qu.remove(),Qu=null)}function _Q(){yp||QD()}function LQ(){QD(),Qu=document.createElement("div"),document.body.append(Qu),wp=jn.createRoot(Qu),wp.render(s.jsx(PQ,{onClose:_Q}))}window.wbRequestClearModal={open:LQ};const ZD=[{value:"detail",label:r("请求详情")},{value:"preview",label:r("预览对话")},{value:"raw",label:r("原始报文")}],zQ="detail",WD="border-b border-hairline px-2.5 py-[7px] align-top",Vo="border border-hairline px-2 py-1 align-top",BQ="border border-hairline bg-surface-2 px-2 py-1 text-[11.5px] tracking-normal",bx="hover:[&>td]:bg-transparent";function Zu(){return window}function z0(){const e=Zu().workbuddyDesktop;if(!e)throw new Error(r("后端桥不可用"));return e}let B0=0;function HQ(e){if(!e)return"—";const t=new Date(e),a=o=>String(o).padStart(2,"0");return`${t.getFullYear()}-${a(t.getMonth()+1)}-${a(t.getDate())} ${a(t.getHours())}:${a(t.getMinutes())}:${a(t.getSeconds())}`}function JD(e){const t=Math.round(Number(e)||0);if(t<1e3)return`${t}ms`;const a=Math.floor(t/1e3);if(a>=60)return r("{m}分{s}秒",{m:Math.floor(a/60),s:a%60});const o=t%1e3;return o>0?r("{s}秒{ms}ms",{s:a,ms:o}):r("{n}秒",{n:a})}function UQ(e){const t=Number(e);return!Number.isFinite(t)||t<=0?"-":JD(t)}const VQ=r("生成速度:输出 token ÷ 流式段用时(总用时 − 首响);流式段不足总用时一半时按总用时计");function FQ(e){const t=Number(e.completionTokens)||0,a=Number(e.durationMs)||0;if(t<=0||a<=0)return"";const o=Number(e.firstResponseMs),c=Number.isFinite(o)&&o>0&&o=500&&c*2>=a,f=t/((d?c:a)/1e3);return`${f>=100?Math.round(f):f.toFixed(1)} tok/s`}function vx(e){return Zu().wbUnits?.formatTokens?.(e)??(Number(e)||0).toLocaleString("zh-CN")}function $Q(e){const t=Math.max(0,Date.now()-(Number(e)||0));return r("{n}秒",{n:Math.max(1,Math.floor(t/1e3))})}function qQ(e){const t=Number(e.status)||0;return t>=200&&t<300&&!e.error}function yx(e){return(Number(e?.status)||0)===0&&!e?.error}function eI(e){const t=String(e.provider??"").trim();return String(e.providerLabel??"").trim()||(t?Zu().wbProviders?.labelOf?.(t)||t:"")}function Sp(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function H0(e){if(e==null)return"";if(typeof e=="string")return e;try{return JSON.stringify(e,null,2)}catch{return""}}function U0(e){return e instanceof Error?e.message:String(e)}const tI=[{label:r("请求头"),pick:e=>H0(e.requestHeaders)},{label:r("请求体"),pick:e=>H0(e.requestBody)},{label:r("响应头"),pick:e=>H0(e.responseHeaders)},{label:r("响应体"),pick:e=>e.responseBody?String(e.responseBody):""}];function jx({text:e,loading:t=!1}){return s.jsxs("div",{className:"flex items-center justify-center gap-2 py-6 text-center text-[12.5px] text-muted-foreground",children:[t?s.jsx(of,{className:"size-3.5"}):null,e]})}function pa({label:e,children:t}){return s.jsxs(Cl,{className:bx,children:[s.jsx("th",{scope:"row",className:`w-[76px] whitespace-nowrap text-left text-[12.5px] font-semibold text-muted-foreground ${WD}`,children:e}),s.jsx(Tn,{className:WD,children:t})]})}function GQ({row:e}){if(yx(e)){const c=Zu().wbRequestPhase;if(!c?.badgeHtml)return s.jsxs(ze,{variant:"info",shape:"tag",title:r("请求正在转发中,用时列显示的是已用时"),children:[s.jsx(my,{className:"req-live-dot"}),r("进行中")]});const d=c.elapsedLineHtml?.(e)??"";return s.jsxs("span",{className:"inline-flex flex-wrap items-center gap-1.5",children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:c.badgeHtml(e)}}),d?s.jsx("span",{className:"text-[11.5px] text-muted-foreground",dangerouslySetInnerHTML:{__html:d}}):null]})}const t=Number(e.status)||0,a=qQ(e),o=!a&&t>=200&&t<300?r("HTTP {status},但响应体阶段出错",{status:t}):"";return s.jsx(ze,{variant:a?"success":"destructive",shape:"tag",title:o||void 0,children:t||r("失败")})}function KQ({row:e}){const t=String(e.clientModel??"").trim(),a=String(e.upstreamModel??"").trim(),o=String(e.model??"").trim(),c=String(e.clientReasoning??"").trim(),d=String(e.upstreamReasoning??"").trim(),f=(b,y)=>y?`${b}(${y})`:b;if(!t||!a||a.toLowerCase()===t.toLowerCase())return s.jsx(s.Fragment,{children:f(o,d||c)||"—"});const p=f(a,d),h=f(t,c);return s.jsxs("span",{className:"flex flex-col gap-0.5",children:[s.jsxs("span",{title:r("转发到上游的模型:{model}",{model:p}),children:["⬆️ ",p]}),s.jsxs("span",{className:"text-muted-foreground",title:r("下游请求的模型:{model}",{model:h}),children:["⬇️ ",h]})]})}function YQ(e){const t=Number(e?.status),a=e?.status!==null&&e?.status!==void 0&&Number.isFinite(t),o=e?.error?String(e.error):"";if(o){const c=a?r("失败({status}):{error}",{status:String(t),error:o}):r("失败:{error}",{error:o});return s.jsx("span",{className:"break-words text-destructive",children:c})}return a?s.jsx("span",{className:"text-success",children:r("成功({status})",{status:String(t)})}):s.jsx("span",{className:"text-muted-foreground",children:r("无结果记录")})}function XQ({row:e}){const t=Array.isArray(e.attemptDetails)?e.attemptDetails:[];if(!t.length)return s.jsx(s.Fragment,{children:"-"});const a=Number(e.attempts)||1;return s.jsxs(Zy,{className:"text-[11.5px]",children:[s.jsx(AE,{children:s.jsx(Cl,{className:bx,children:[r("轮次"),r("提供商"),r("账号"),r("结果"),r("体积"),r("内部重试"),r("提示")].map(o=>s.jsx(RE,{className:BQ,children:o},o))})}),s.jsxs(Wy,{children:[t.map((o,c)=>{const d=Array.isArray(o?.retries)?o.retries:[],f=d.map(v=>{const j=Number(v?.delayMs),w=Number.isFinite(j)&&j>0?j>=1e3?r(",{n}秒后重试",{n:Math.round(j/1e3)}):r(",{n}毫秒后重试",{n:Math.round(j)}):"";return`${String(v?.reason||r("未知原因"))}${w}`}).join(` -`),p=String(o?.notice??"").trim(),h=Number(o?.bodyBytes),b=Number.isFinite(h)&&h>0?h>=1024*1024?`${(h/1024/1024).toFixed(1)} MB`:h>=1024?`${Math.round(h/1024)} KB`:`${h} B`:"—",y=Number.isFinite(h)&&h>0?r("实际发给上游 {bytes} 字节",{bytes:h.toLocaleString()}):void 0;return s.jsxs(Cl,{className:bx,children:[s.jsx(Tn,{className:Vo,children:c+1}),s.jsx(Tn,{className:Vo,children:eI(o)||(o?.provider?String(o.provider):r("未知"))}),s.jsx(Tn,{className:Vo,children:o?.account?String(o.account):"—"}),s.jsx(Tn,{className:Vo,children:YQ(o)}),s.jsx(Tn,{className:`${Vo} whitespace-nowrap`,title:y,children:b}),s.jsx(Tn,{className:`${Vo} whitespace-nowrap`,title:f||void 0,children:d.length?r("↻ {n} 次",{n:d.length}):"-"}),s.jsx(Tn,{className:Vo,children:p||"—"})]},c)}),t.lengths.jsxs("li",{className:"py-0.5",children:[s.jsxs("b",{children:[y+1,". ",String(b.name||b.id||"—")]}),s.jsxs("span",{className:"text-muted-foreground",children:[" ",String(b.reason||"")]})]},String(b.id??y)))}):null,p.length?s.jsxs("div",{className:"mt-1 text-muted-foreground",children:[r("被跳过:"),p.map(b=>String(b.name||b.id||"")).join("、")]}):null,h?s.jsx("div",{className:"mt-1",children:r("最终承载:{picked}",{picked:h})}):null]})}function ZQ({row:e}){if(!e)return s.jsx(jx,{text:r("列表数据已刷新,请重试(关闭后重新打开这条详情)")});const t=String(e.accountName??"").trim(),a=FQ(e);return s.jsx(Zy,{className:"text-[12.5px] text-subtle [&_tr:last-child>td]:border-b-0 [&_tr:last-child>th]:border-b-0",children:s.jsxs(Wy,{children:[s.jsx(pa,{label:r("时间"),children:HQ(e.ts)}),s.jsx(pa,{label:r("状态"),children:s.jsx(GQ,{row:e})}),s.jsx(pa,{label:r("耗时"),children:yx(e)?s.jsxs(s.Fragment,{children:[$Q(e.ts),s.jsx("span",{className:"text-[11.5px] text-muted-foreground",children:r("(请求仍在转发中)")})]}):r("{duration} / 首帧 {first}",{duration:JD(e.durationMs),first:UQ(e.firstResponseMs)})}),s.jsx(pa,{label:r("重试次数"),children:String(Number(e.attempts)||1)}),s.jsx(pa,{label:r("模型"),children:s.jsx(KQ,{row:e})}),s.jsxs(pa,{label:r("提供商"),children:[eI(e)||"—",t?s.jsx("span",{className:"text-[11.5px] text-muted-foreground",children:r("(账号:{account})",{account:t})}):null]}),s.jsxs(pa,{label:r("令牌"),children:[r("输入 {input} · 输出 {output} · 总计 {total} · 缓存读 {cache}",{input:vx(e.promptTokens),output:vx(e.completionTokens),total:vx(e.totalTokens),cache:vx(e.cacheReadTokens)}),a?s.jsxs("span",{title:VQ,children:[" · ",a]}):null]}),e.isTest?s.jsx(pa,{label:r("来源"),children:s.jsx(ze,{variant:"brand",shape:"tag",title:r("模型管理页操作列那颗「测试」发起的请求:与真实请求同一条转发链路,但不计入报表统计"),children:r("模型测试")})}):null,s.jsx(pa,{label:r("错误"),children:e.error?s.jsx("span",{className:"text-destructive",children:String(e.error)}):"—"}),s.jsx(pa,{label:r("尝试明细"),children:s.jsx(XQ,{row:e})}),e.route?s.jsx(pa,{label:r("路由回放"),children:s.jsx(QQ,{row:e})}):null,s.jsx(pa,{label:r("敏感词"),children:Array.isArray(e.sensitiveHits)&&e.sensitiveHits.length?s.jsx("span",{className:"inline-flex flex-wrap gap-1.5",children:e.sensitiveHits.map((o,c)=>s.jsxs(ze,{variant:"sensitive",shape:"tag",children:[String(o?.word??"")," × ",String(Number(o?.count)||0)]},c))}):"—"})]})})}function WQ({state:e}){if(!e)return s.jsx(jx,{text:r("正在读取…"),loading:!0});const t=e==="gone"?null:e.body,a=t&&Zu().wbConversationPreview?.render?.(t.requestBody,t.responseBody)||"";return a?s.jsxs("div",{children:[e!=="gone"&&e.truncated?s.jsx("div",{className:"mb-2 text-[11.5px] text-warning",children:r("正文超过单条上限,可能已被截断")}):null,s.jsx("div",{dangerouslySetInnerHTML:{__html:a}})]}):s.jsx(jx,{text:r("无报文原文(未开启「调试模式」,或已被清理)")})}function JQ({data:e}){const t=e.status===null||e.status===void 0?"-":String(e.status),a=[e.url?`URL: ${e.url}`:"",e.provider?r("提供商: {provider}",{provider:String(e.provider)}):"",r("上游状态码: {status}",{status:t})].filter(Boolean);return s.jsxs("div",{className:"flex flex-col gap-4",children:[a.length?s.jsx("div",{className:"border-b border-hairline pb-2.5 text-xs leading-[1.7] break-all text-subtle",children:a.map((o,c)=>s.jsx("div",{children:o},c))}):null,tI.map(o=>{const c=o.pick(e)||"";return s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx("h3",{className:"text-[11.5px] font-semibold tracking-[.02em] text-muted-foreground",children:o.label}),c?s.jsx("pre",{className:"max-h-80 overflow-auto rounded-md border border-border bg-surface-2 p-[10px_12px] font-mono text-[11.5px] leading-[1.6] break-words whitespace-pre-wrap text-subtle",children:c}):s.jsx(jx,{text:r("这条请求没有保存这一段报文")})]},o.label)})]})}function eZ({id:e,row:t,token:a,onClose:o}){const[c,d]=x.useState(zQ),[f,p]=x.useState(null),[h,b]=x.useState(null),[y,v]=x.useState("—"),[j,w]=x.useState("idle"),S=x.useRef(!0),N=x.useRef(null),k=x.useRef({detail:0,preview:0,raw:0}),A=x.useCallback(()=>!S.current||a!==B0,[a]);async function P(){try{const O=await z0().getStatsRequestRaw(e);if(A())return;const _=Sp(O)?O:null,z=String(_?.requestBody??"").trim()!==""||String(_?.responseBody??"").trim()!=="";p(_&&z?{body:_,truncated:!!_.truncated}:"gone")}catch(O){if(A())return;p("gone"),console.warn("读取原始正文失败(预览对话显示空态):",U0(O))}}async function R(){try{const O=await z0().getDebugTraffic(e);if(A())return;const _=Sp(O)?O:{};if(!tI.some(z=>(z.pick(_)||"").trim())){b("gone");return}b({data:_}),v(_.truncated?r("报文超过单条上限,请求体 / 响应体已按上限截断"):r("内容按原样保存,请求头中的凭据字段已替换为 [redacted]"))}catch(O){if(A())return;b("gone"),v(r("在设置 → 通用里开启「调试模式」后,新发生的请求才会保存报文")),console.warn("读取调试报文失败(原始报文标签隐藏):",U0(O))}}x.useEffect(()=>(S.current=!0,P(),R(),()=>{S.current=!1}),[]),x.useLayoutEffect(()=>{const O=N.current;O&&(O.scrollTop=k.current[c])},[c]);function C(O){if(O==="raw"&&!Sp(h)||O===c)return;const _=N.current;_&&(k.current[c]=_.scrollTop),d(O)}async function E(){if(!e||!yx(t))return;const O=Zu().wbConfirm?.ask;if(!(!O||!await O({title:r("终止请求"),html:r("确定终止这条正在转发的请求?
    上游连接会立即断开,明细将记为「请求已被手动终止」。"),okText:r("终止"),okClass:"danger"}))){w("pending");try{if(await z0().terminateStatsRequest(e),!S.current)return;w("accepted"),v(r("已受理终止:上游连接已断开,列表稍后刷新为「请求已被手动终止」"))}catch(z){if(!S.current)return;w("idle"),v(r("终止失败:{error}",{error:U0(z)}))}}}const D=Sp(h),I=x.useMemo(()=>D?ZD:ZD.filter(O=>O.value!=="raw"),[D]);return s.jsx(Yt,{open:!0,onOpenChange:O=>{O||o()},children:s.jsxs(Xt,{className:"w-[min(920px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("请求详情")})}),s.jsxs(Lt,{ref:N,className:"gap-3",children:[s.jsx(En,{options:I,value:c,onValueChange:C,"aria-label":r("详情内容"),className:"self-start"}),s.jsx("section",{hidden:c!=="detail",children:s.jsx(ZQ,{row:t})}),s.jsx("section",{hidden:c!=="preview",children:s.jsx(WQ,{state:f})}),D?s.jsx("section",{hidden:c!=="raw",children:s.jsx(JQ,{data:h.data})}):null]}),s.jsxs(tn,{children:[s.jsx("span",{className:"min-w-0 text-[11.5px] text-muted-foreground",children:y}),s.jsx("div",{className:"mr-auto"}),yx(t)?s.jsx(ne,{variant:"destructive",disabled:j!=="idle",onClick:()=>{E()},title:r("断开上游连接,明细记为「请求已被手动终止」"),children:r("终止请求")}):null,s.jsx(ne,{variant:"outline",onClick:o,children:r("关闭")})]})]})})}let Np=null,Wu=null;function nI(){Np&&(Np.unmount(),Np=null),Wu&&(Wu.remove(),Wu=null)}function sI(){B0+=1,nI()}function tZ(e,t){const a=String(e??"").trim();if(!a)return;nI();const o=++B0;Wu=document.createElement("div"),document.body.append(Wu),Np=jn.createRoot(Wu),Np.render(s.jsx(eZ,{id:a,row:Sp(t)?t:null,token:o,onClose:sI}))}window.wbRequestDetail={open:tZ,close:sI};const nZ=150,sZ=80,ic=8,wx=8,rZ=520,aZ=220,lZ=1.1,oZ=900,V0=12,F0="req-hover-panel",iZ=["fixed z-[35] pointer-events-none","max-h-[min(360px,60vh)] overflow-x-hidden overflow-y-auto","rounded-md p-[10px_12px] text-[12px] leading-[1.6] break-normal","bg-surface-2 text-foreground shadow-3","border-0 dark:border dark:border-border-strong dark:bg-surface-3"].join(" "),kp="rh-row rh-dim min-w-0 break-words text-muted-foreground",cZ="rh-row min-w-0 break-words";function uZ(){return window}function $0(e){return typeof e=="object"&&e!==null?e:null}const rI=e=>Array.isArray(e?.attemptDetails)?e.attemptDetails:[],aI=e=>Array.isArray(e?.retries)?e.retries:[],dZ=e=>Array.isArray(e?.sensitiveHits)?e.sensitiveHits:[];function q0(e){const t=String(e??"").trim();return t?uZ().wbProviders?.labelOf?.(t)||t:""}function fZ(e){const t=$0(e);return(Number(t?.attempts)||1)>1?!0:rI(t).some(a=>aI(a).length>0||!!a?.notice)}function lI(e){return e.dataset.reqHover==="sensitive"?"sensitive":"chain"}function pZ({details:e}){if(e.length<2)return null;const t=e.map(a=>q0(a.provider)||r("未知"));return s.jsxs("div",{className:"rh-chain mb-1.5 border-b border-border pb-1.5 break-words",children:[s.jsx("span",{className:"rh-chain-k font-semibold text-muted-foreground",children:r("切换路径:")}),s.jsx("span",{className:"rh-chain-v font-semibold text-foreground",children:t.join(" → ")})]})}function mZ({item:e}){const t=aI(e);return t.length?s.jsxs("div",{className:"rh-retry mt-0.5 mb-1 ml-2.5 border-l-2 border-border-strong pl-2",children:[s.jsx("div",{className:"rh-retry-head text-[11.5px] font-semibold text-warning",children:r("↻ 重试 {n} 次",{n:t.length})}),t.map((a,o)=>{const c=String(a?.reason??"").trim(),d=Number(a?.status),f=a?.status!==null&&a?.status!==void 0&&Number.isFinite(d),p=Number(a?.delayMs),h=Number.isFinite(p)&&p>0?p>=1e3?r(",{n}秒后重试",{n:Math.round(p/1e3)}):r(",{n}毫秒后重试",{n:Math.round(p)}):"";return s.jsxs("div",{className:"rh-retry-row min-w-0 break-words",children:[s.jsx("span",{className:"rh-retry-why mr-1 text-subtle [overflow-wrap:anywhere]",children:c||r("未知原因")}),f?s.jsx("span",{className:"rh-retry-status mr-1 text-muted-foreground tabular-nums whitespace-nowrap",children:`HTTP ${String(d)}`}):null,h?s.jsx("span",{className:"rh-dim text-muted-foreground",children:h}):null]},o)})]}):null}function hZ({item:e,index:t,inFlight:a}){const o=q0(e.provider),c=String(e.account??"").trim(),d=Number(e.status),f=e.status!==null&&e.status!==void 0&&Number.isFinite(d),p=e.error?String(e.error):"",h=String(e.notice??"").trim();return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:cZ,children:[s.jsx("span",{className:"rh-no mr-1 text-muted-foreground",children:r("尝试 {n} ·",{n:t+1})}),s.jsx("span",{className:"rh-who mr-1 font-semibold text-foreground",children:o||r("未知")}),c?s.jsx("span",{className:"rh-account mr-1 text-muted-foreground [overflow-wrap:anywhere]",children:c}):null,s.jsx("span",{className:"rh-arrow mr-1 text-muted-foreground",children:"→"}),p?s.jsx("span",{className:"rh-bad font-medium text-destructive [overflow-wrap:anywhere]",children:f?r("失败({status}):{error}",{status:String(d),error:p}):r("失败:{error}",{error:p})}):f?s.jsx("span",{className:"rh-ok font-medium text-success",children:r("成功({status})",{status:String(d)})}):a?s.jsx("span",{className:"rh-dim text-muted-foreground",children:r("进行中…")}):s.jsx("span",{className:"rh-dim text-muted-foreground",children:r("无结果记录")})]}),h?s.jsx("div",{className:"rh-notice mt-0.5 mb-1 ml-2.5 border-l-2 border-border-strong pl-2 text-warning [overflow-wrap:anywhere]",children:`⚠️ ${h}`}):null,s.jsx(mZ,{item:e})]})}function gZ({entry:e}){const t=Number(e.attempts)||1,a=rI(e);if(!a.length){const c=q0(e.provider),d=c?r("共 {n} 次尝试,最终由 {provider} 承载",{n:t,provider:c}):r("共 {n} 次尝试",{n:t});return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:kp,children:d}),s.jsx("div",{className:kp,children:r("这条记录的尝试明细未采集(该字段上线前的旧数据,或请求在转发前就失败)")})]})}const o=(Number(e.status)||0)===0&&!e.error;return s.jsxs(s.Fragment,{children:[s.jsx(pZ,{details:a}),a.map((c,d)=>s.jsx(hZ,{item:c,index:d,inFlight:o&&d===a.length-1},d)),a.lengths.jsxs("div",{className:"rh-row rh-hit flex items-baseline justify-between gap-2.5",children:[s.jsx("span",{className:"rh-hit-w break-words text-foreground",children:String(a?.word??"")}),s.jsx("span",{className:"rh-hit-c text-muted-foreground tabular-nums whitespace-nowrap",children:`× ${String(Number(a?.count)||0)}`})]},o)),t.length>V0?s.jsx("div",{className:kp,children:r("另有 {n} 个词命中",{n:t.length-V0})}):null]}):s.jsx("div",{className:kp,children:r("这条记录命中了敏感词,但没有留下命中明细")})}function bZ({kind:e,entry:t,panelRef:a}){return s.jsx("div",{ref:a,id:F0,role:"tooltip","data-kind":e,className:iZ,children:e==="sensitive"?s.jsx(xZ,{entry:t}):s.jsx(gZ,{entry:t})})}let On=null,Fo=0,Cp=0,Tp=null,Sx=null,G0=null,K0=null,cc=null,uc=null,Ep=null,oI="chain";function Y0(){window.clearTimeout(Fo),window.clearTimeout(Cp),Fo=0,Cp=0,Tp=null}function vZ(){const e=Ep?.current,t=On;if(!e||!t)return;const a=t.getBoundingClientRect(),o=window.innerWidth-ic*2;e.style.maxWidth="none",e.style.width="max-content";const c=e.offsetWidth,d=oI==="sensitive",p=Math.max(d?aZ:rZ,c)*(d?lZ:1),h=Math.min(p,o,oZ);e.style.maxWidth=`${h}px`,e.style.width=d?`${h}px`:"auto";const b=e.offsetWidth,y=e.offsetHeight,v=window.innerHeight-a.bottom-wx-ic,j=a.top-wx-ic,w=vv,S=a.left+a.width/2,N=Math.max(ic,Math.min(S-b/2,window.innerWidth-ic-b)),k=w?a.top-wx-y:a.bottom+wx;e.style.left=`${Math.round(N)}px`,e.style.top=`${Math.round(Math.max(ic,Math.min(k,window.innerHeight-ic-y)))}px`}function iI(e){if(!On)return;const t=e.target;t instanceof Node&&(t===On||On.contains(t)||Oa())}function cI(){Oa()}function uI(){Oa()}let Nx=!1;function yZ(){Nx||(Nx=!0,document.addEventListener("click",iI,!0),window.addEventListener("scroll",cI,!0),window.addEventListener("resize",uI))}function jZ(){Nx&&(Nx=!1,document.removeEventListener("click",iI,!0),window.removeEventListener("scroll",cI,!0),window.removeEventListener("resize",uI))}function wZ(){jZ(),uc&&(uc.unmount(),uc=null),cc&&(cc.remove(),cc=null),Ep=null}function dI(e,t){oI=e,(!cc||!uc||!Ep)&&(cc=document.createElement("div"),document.body.append(cc),Ep=x.createRef(),uc=jn.createRoot(cc));const a=uc,o=Ep;Ts.flushSync(()=>{a.render(s.jsx(bZ,{kind:e,entry:t,panelRef:o}))}),yZ(),vZ()}function fI(e){if(!e.isConnected)return;const t=$0(G0?.(e));t&&(Y0(),On&&On!==e&&Oa(),On=e,dI(lI(e),t),e.classList.add("active"),e.setAttribute("aria-describedby",F0))}function Oa(){Y0(),On&&(On.classList.remove("active"),On.removeAttribute("aria-describedby"),On=null),wZ()}function SZ(){if(!On)return;const e=String(On.dataset.reqHover||""),t=String(On.dataset.reqId||"");K0=!!(e&&t)&&On.matches(":hover")&&!Cp?{action:"move",kind:e,key:t}:{action:"close"}}function NZ(){const e=K0;if(K0=null,!e||!On)return;if(e.action==="close"){Oa();return}const t=Sx?kZ(Sx,e.kind,e.key):null,a=t?$0(G0?.(t)):null;if(!t||!a){Oa();return}t!==On&&(On.classList.remove("active"),On.removeAttribute("aria-describedby"),On=t,dI(lI(t),a),t.classList.add("active"),t.setAttribute("aria-describedby",F0))}function kZ(e,t,a){for(const o of e.querySelectorAll("[data-req-hover]"))if(String(o.dataset.reqHover||"")===t&&String(o.dataset.reqId||"")===a)return o;return null}function kx(e){const t=e.target;return t instanceof Element?t.closest("[data-req-hover]"):null}function CZ(e){const t=kx(e);if(!t||!Sx?.contains(t)||(Y0(),On===t&&uc))return;const a=On?0:nZ;On&&Oa(),Tp=t,Fo=window.setTimeout(()=>{Fo=0,Tp=null,fI(t)},a)}function TZ(e){const t=kx(e);if(t){if(Tp===t){window.clearTimeout(Fo),Fo=0,Tp=null;return}On===t&&(window.clearTimeout(Fo),Fo=0,Cp=window.setTimeout(()=>{Cp=0,On===t&&Oa()},sZ))}}function EZ(e){const t=kx(e);t&&fI(t)}function AZ(e){const t=kx(e);t&&On===t&&Oa()}function RZ(e){e.key!=="Escape"||!On||Oa()}function OZ(e){const t=e?.host;t&&(Sx=t,G0=e?.entryOf??null,t.addEventListener("pointerover",CZ),t.addEventListener("pointerout",TZ),t.addEventListener("focusin",EZ),t.addEventListener("focusout",AZ),t.addEventListener("keydown",RZ))}window.wbRequestHover={bind:OZ,close:Oa,hasProcessFacts:fZ,beforeListRedraw:SZ,afterListRedraw:NZ};function As(){return window}function X0(e){return e instanceof Error?e.message:String(e)}function Cx(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t]??t)}const Tx={connecting:{label:r("连接中"),cls:"phase-connecting"},waiting:{label:r("等待响应"),cls:"phase-waiting"},streaming:{label:r("响应中"),cls:"phase-streaming"},retrying:{label:r("重试中"),cls:"phase-retrying"},queued:{label:r("排队中"),cls:"phase-queued"}},pI=r("进行中"),MZ="running",mI={connecting:r("请求已受理,正在选路、取凭证、建立上游连接"),waiting:r("上游请求已发出,正在等第一个字节到达(模型的思考时间也在这段)"),streaming:r("首帧已到,上游内容正在下发"),retrying:r("本轮尝试失败,正在退避等待或切换到下一个账号"),queued:r("上游模型繁忙,请求已排进上游队列;网关正按上游建议的时长等待后重发(不是登录态或额度问题)"),"":r("请求正在转发中,用时列显示的是已用时")};function Q0(e){const t=String(e?.phase??"").trim().toLowerCase();return Object.prototype.hasOwnProperty.call(Tx,t)?t:""}function hI(e){const t=Q0(e);return t?Tx[t].label:pI}function gI(e){if(e==null||e==="")return"";const t=Number(e);if(!Number.isFinite(t)||t<0)return"";const a=Math.max(1,Math.floor(t/1e3));return a<60?r("{n}秒",{n:a}):r("{m}分{s}秒",{m:Math.floor(a/60),s:a%60})}function DZ(e){const t=e?.phaseElapsedMs;if(t!=null&&t!==""){const c=Number(t);if(Number.isFinite(c)&&c>=0)return c}const a=Number(e?.phaseStartedAt);if(!Number.isFinite(a)||a<=0)return null;const o=Date.now()-a;return Number.isFinite(o)?Math.max(0,o):null}function IZ(e){const t=Q0(e),a=t?Tx[t].label:pI,o=t?Tx[t].cls:MZ,c=mI[t]||mI[""];return`${Cx(a)}`}function PZ(e){const t=gI(DZ(e));if(!t)return"";const a=hI(e),o=r("进入「{phase}」阶段已持续 {time}",{phase:a,time:t});return`${Cx(t)}`}const Z0=[{key:"time",label:r("时间"),sel:".req-time",track:"92px"},{key:"target",label:r("提供商 / 账号"),sel:".req-target",track:"minmax(0, 1.1fr)"},{key:"retry",label:r("重试"),sel:".req-retry",track:"52px"},{key:"status",label:r("状态"),sel:".req-status",track:"96px"},{key:"model",label:r("模型"),sel:".req-model",track:"minmax(0, 1.3fr)"},{key:"client",label:r("客户端"),sel:".req-client",track:"110px"},{key:"dur",label:r("用时"),sel:".req-dur",track:"96px",align:"right"},{key:"usage",label:r("用量"),sel:".req-usage",track:"minmax(0, 1.6fr)"},{key:"error",label:r("错误"),sel:".req-error-cell",track:"minmax(0, 1.2fr)"},{key:"detail",label:r("详情"),sel:".req-detail",track:"60px",align:"right"}],xI=1e3,_Z=dg;function bI(e){return typeof e=="number"&&e>0?e:xu}const vI="workbuddy-desktop-logs-requests-range",yI="workbuddy-desktop-requests-filters",LZ=3e4,W0=["today","7","30","month","all"],J0="all",zZ={today:r("今天"),7:r("近 7 天"),30:r("近 30 天"),month:r("本月"),all:r("全部")},BZ={today:r("今天"),7:r("7 天"),30:r("30 天"),month:r("本月"),all:r("全部")},HZ=W0.map(e=>({value:e,label:BZ[e]})),jI=[{value:"",label:r("全部状态")},{value:"ok",label:r("成功")},{value:"error",label:r("失败")}],UZ=r("全部状态"),wI=r("全部提供商"),SI=r("全部模型"),Ex={status:"",provider:"",model:""};function Ax(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function VZ(e){const t=new Date;switch(e){case"today":return Ax(t);case"7":return Ax(new Date(t.getFullYear(),t.getMonth(),t.getDate()-6));case"30":return Ax(new Date(t.getFullYear(),t.getMonth(),t.getDate()-29));case"month":return Ax(new Date(t.getFullYear(),t.getMonth(),1));default:return null}}const sn={filters:{...Ex},range:FZ(),runningOnly:!1,offset:0,size:bI(pg("requests",dg))};let Rx={...Ex},eS=!1,NI=!1,tS=[],Ox=xI,Mx=!0,nS=!1,sS=!1,kI=0,rS=0,aS=null,CI=!1,Ju=null;function FZ(){try{const e=localStorage.getItem(vI);return e!==null&&W0.includes(e)?e:J0}catch{return J0}}function $Z(e){try{localStorage.setItem(vI,e)}catch{}}function TI(){const e=As().wbFilterMemory;return e?(eS=!0,Rx=e.load(yI,{...Ex}),sn.filters={...Rx},{...Rx}):{...Ex}}function qZ(e){Rx={...e},As().wbFilterMemory?.save(yI,{status:e.status||"",provider:e.provider||"",model:e.model||""})}function EI(){const e=new URLSearchParams,t=VZ(sn.range);t!==null&&e.set("start",String(t));const a=sn.runningOnly?"running":sn.filters.status;return a&&e.set("status",a),sn.filters.provider&&e.set("provider",sn.filters.provider),sn.filters.model&&e.set("model",sn.filters.model),e}function GZ(){const e=EI();return e.set("offset",String(sn.offset)),e.set("limit",String(sn.size)),e.toString()}function lS(e){const t=Math.round(Number(e)||0);if(t<1e3)return`${t}ms`;const a=Math.floor(t/1e3);if(a>=60)return r("{m}分{s}秒",{m:Math.floor(a/60),s:a%60});const o=t%1e3;return o>0?r("{s}秒{ms}ms",{s:a,ms:o}):r("{n}秒",{n:a})}const KZ=r("生成速度:输出 token ÷ 流式段用时(总用时 − 首响);流式段不足总用时一半时按总用时计"),YZ=500;function XZ(e){const t=Number(e.completionTokens)||0,a=Number(e.durationMs)||0;if(t<=0||a<=0)return"";const o=Number(e.firstResponseMs),c=Number.isFinite(o)&&o>0&&o=YZ&&c*2>=a,f=t/((d?c:a)/1e3);return`${f>=100?Math.round(f):f.toFixed(1)} tok/s`}function QZ(e){const t=Number(e);return!Number.isFinite(t)||t<=0?"-":lS(t)}function Dx(e){return As().wbUnits?.formatTokens?.(e)??(Number(e)||0).toLocaleString("zh-CN")}function ZZ(e){const t=Math.max(0,Date.now()-(Number(e)||0));return r("{n}秒",{n:Math.max(1,Math.floor(t/1e3))})}function WZ(e){const t=Number(e.promptTokens)||0;return t<=0?"-":`${((Number(e.cacheReadTokens)||0)/t*100).toFixed(2)}%`}function oS(e){const t=Number(e.status)||0;return t>=200&&t<300&&!e.error}function Ap(e){return(Number(e?.status)||0)===0&&!e?.error}const AI=e=>String(e?.id||e?.ts||"");function JZ(e){return(Array.isArray(e?.attemptDetails)?e.attemptDetails:[]).reduce((a,o)=>{const c=o?.retries;return a+(Array.isArray(c)?c.length:0)},0)}function RI(e){return r(As().wbProviders?.labelOf?.(e)||e)}function eW(e){const t=new Set;return e.map((a,o)=>{const c=AI(a)||`i${o}`;let d=c,f=1;for(;t.has(d);)d=`${c}#${f++}`;return t.add(d),d})}async function OI(){if(!(Date.now()-rS({value:String(o?.id||""),label:r(String(o?.label||o?.id||""))})).filter(o=>o.value),a=(Array.isArray(e?.models)?e.models:[]).map(o=>String(o||"")).filter(Boolean);Ju?.setFilterOptions(t,a)}catch(e){console.warn("读取请求日志筛选清单失败,筛选项退化为「全部」:",X0(e))}}}async function tW(){if(!nS)try{const e=await As().workbuddyDesktop?.getScheduledTasks(),t=(e?.tasks||[]).find(a=>a.id==="requestsAutoRefresh");iS(t||null),nS=Array.isArray(e?.tasks)}catch(e){console.warn("读取请求日志自动刷新间隔失败,按默认 1 秒:",X0(e)),iS(null)}}function iS(e){nS=!0;const t=Number(e?.interval),a=e?.unit;!!e&&typeof e=="object"&&Number.isFinite(t)&&t>0&&(a==="seconds"||a==="minutes")?(Mx=e.enabled!==!1,Ox=a==="minutes"?t*6e4:t*1e3):(Mx=!0,Ox=xI),Ju?.setAuto({ms:Ox,enabled:Mx})}function nW(){if(CI)return;const e=As().wbColSettings;e&&(CI=!0,aS=e.register({id:"requests",label:r("请求日志表"),columns:Z0.map(({key:t,label:a,align:o})=>({key:t,label:a,align:o})),mount:()=>document.querySelector('.page[data-page="requests"] .panel-head .head-actions'),onChange:()=>{Ts.flushSync(()=>Ju?.repaint()),As().wbTableColumns?.repaint?.("requests")}}))}function cS(){return(aS?aS.apply(Z0):Z0).map(t=>({...t,align:t.align||"left"}))}const sW={entries:[],total:0,matched:0,running:0,loaded:!1,error:""};function rW(e){return e.loaded?e.total?r("没有符合筛选条件的请求"):r("暂无请求日志,网关还没有转发过请求"):r("正在加载请求日志…")}function aW(e){const t=Number(e.firstResponseMs);return!Number.isFinite(t)||t<=0?null:s.jsx("span",{className:"req-dur-line sub",title:r("首响:上游首帧到达的耗时(请求仍在转发中)"),children:r("首响 {time}",{time:lS(t)})})}function lW(e,t){const{align:a,key:o}=t,c=t.sel.slice(1)+(o==="dur"?" req-num":""),d=`${c} ta-${a}`;switch(o){case"time":{if(!e.ts)return s.jsx("span",{className:d,children:"—"},o);const f=new Date(e.ts),p=h=>String(h).padStart(2,"0");return s.jsxs("span",{className:d,children:[s.jsx("span",{children:`${f.getFullYear()}-${p(f.getMonth()+1)}-${p(f.getDate())}`}),s.jsx("span",{children:`${p(f.getHours())}:${p(f.getMinutes())}:${p(f.getSeconds())}`})]},o)}case"target":{const f=String(e.provider??"").trim(),p=String(e.providerLabel??"").trim(),h=p?r(p):f?RI(f):"";return s.jsxs("span",{className:d,children:[h?s.jsx("span",{className:"req-provider",title:f&&f!==h?r("{name}({id})",{name:h,id:f}):h,children:h}):s.jsx("span",{className:"req-provider is-empty",title:r("这条明细没有记录提供商(旧数据或请求未走到转发)"),children:"—"}),e.accountName?s.jsx("span",{className:"req-acct",title:e.accountId||e.accountName,children:e.accountName}):s.jsx("span",{className:"req-acct is-empty",title:r("请求在任何账号接手之前就失败了"),children:"—"})]},o)}case"retry":{const f=Number(e.attempts)||1,p=AI(e),h=[];if(e.isTest&&h.push(s.jsx(ze,{variant:"brand",shape:"tag",title:r("这条明细是一次模型测试(人工发起):走的是真实转发链路,但不计入报表统计"),children:r("测试")},"test")),As().wbRequestHover?.hasProcessFacts?.(e)??f>1){const y=f>1?f:JZ(e);h.push(s.jsx(ze,{variant:"warning",shape:"tag",render:s.jsx("button",{type:"button"}),className:"req-hover-tag","data-req-hover":"chain","data-req-id":p,children:y>1?r("重试 {n}",{n:y}):r("重试")},"chain"))}return Array.isArray(e.sensitiveHits)&&e.sensitiveHits.length&&h.push(s.jsx(ze,{variant:"sensitive",shape:"tag",render:s.jsx("button",{type:"button"}),className:"req-hover-tag","data-req-hover":"sensitive","data-req-id":p,"aria-label":r("命中了敏感词"),children:r("敏")},"sensitive")),h.length?s.jsx("span",{className:d,children:h},o):s.jsx("span",{className:`req-none ta-${a}`,children:"-"},o)}case"status":{if(Ap(e)){const b=window.wbRequestPhase;if(!b?.badgeHtml)return s.jsx("span",{className:d,children:s.jsx("span",{className:"req-status-badge",children:s.jsxs(ze,{shape:"tag",variant:"info",title:r("请求正在转发中,用时列显示的是已用时"),children:[s.jsx(my,{className:"req-live-dot","aria-hidden":"true"}),r("进行中")]})})},o);const y=b.elapsedLineHtml?.(e)??"";return s.jsxs("span",{className:d,children:[s.jsx("span",{className:"req-status-badge",dangerouslySetInnerHTML:{__html:b.badgeHtml(e)}}),y?s.jsx("span",{className:"req-status-line",dangerouslySetInnerHTML:{__html:y}}):null]},o)}const f=Number(e.status)||0,p=oS(e),h=!p&&f>=200&&f<300?r("HTTP {status},但响应体阶段出错:见错误列",{status:f}):void 0;return s.jsx("span",{className:d,children:s.jsx(ze,{shape:"tag",variant:p?"success":"destructive",title:h,children:f||r("失败")})},o)}case"model":{const f=String(e.clientModel??"").trim(),p=String(e.upstreamModel??"").trim(),h=String(e.model??"").trim(),b=String(e.clientReasoning??"").trim(),y=String(e.upstreamReasoning??"").trim(),v=(S,N)=>N?`${S}(${N})`:S;if(!f||!p||p.toLowerCase()===f.toLowerCase()){const S=v(h,y||b);return s.jsx("span",{className:d,title:S,children:S||"—"},o)}const j=v(p,y),w=v(f,b);return s.jsxs("span",{className:`${d} req-model-split`,children:[s.jsxs("span",{className:"req-model-line",title:r("转发到上游的模型:{model}",{model:j}),children:["⬆️ ",j]}),s.jsxs("span",{className:"req-model-line sub",title:r("下游请求的模型:{model}",{model:w}),children:["⬇️ ",w]})]},o)}case"client":{const f=String(e.client??"").trim();if(!f)return s.jsx("span",{className:`${d} is-empty`,title:r("这条明细没有记录来源客户端(旧数据、模型测试,或请求未带 User-Agent)"),children:"—"},o);const p=f==="other"?r("其它"):f;return s.jsx("span",{className:d,title:f==="other"?r("识别到 User-Agent,但不属于已知的客户端类型:{ua}",{ua:f}):r("来源客户端:{client}",{client:p}),children:p},o)}case"dur":return Ap(e)?s.jsxs("span",{className:d,children:[s.jsx("span",{className:"req-dur-line",title:r("已用时(请求仍在转发中)"),children:ZZ(e.ts)}),aW(e)]},o):s.jsxs("span",{className:d,children:[s.jsx("span",{className:"req-dur-line",children:lS(e.durationMs)}),s.jsx("span",{className:"req-dur-line sub",title:r("首响:上游首帧到达的耗时"),children:r("首响 {time}",{time:QZ(e.firstResponseMs)})})]},o);case"usage":{if(Ap(e))return s.jsx("span",{className:d},o);if(!oS(e))return s.jsxs("span",{className:d,title:r("失败请求不记录用量"),children:[s.jsx("span",{className:"req-usage-line",children:"in: - / out: - / all: -"}),s.jsx("span",{className:"req-usage-line sub",children:r("缓存读取: - / 命中率: -")})]},o);const f=`in: ${Dx(e.promptTokens)} / out: ${Dx(e.completionTokens)} / all: ${Dx(e.totalTokens)}`,p=r("缓存读取: {cache} / 命中率: {rate}",{cache:Dx(e.cacheReadTokens),rate:WZ(e)}),h=XZ(e),b=h?`${p} · ${h}`:p;return s.jsxs("span",{className:d,title:[f,b].filter(Boolean).join(` -`),children:[s.jsx("span",{className:"req-usage-line",children:f}),s.jsxs("span",{className:"req-usage-line sub",children:[p,h?s.jsxs("span",{title:KZ,children:[" · ",h]}):null]})]},o)}case"error":return Ap(e)?s.jsx("span",{className:d},o):e.error?s.jsx("span",{className:d,title:String(e.error),children:String(e.error)},o):s.jsx("span",{className:`req-none ${c} ta-${a}`,children:"-"},o);case"detail":{const f=e.id?String(e.id):"";return f?s.jsx("span",{className:d,children:s.jsx(ne,{size:"sm",variant:"outline",className:"req-detail-btn",title:r("查看该请求的上游原始报文"),onClick:()=>{As().wbRequestDetail?.open?.(f,e)},children:r("详情")})},o):s.jsx("span",{className:`req-none ${c} ta-${a}`,children:"-"},o)}default:return null}}function oW(e){return s.jsx("div",{className:"req-head",children:e.map(t=>s.jsx("span",{"data-col":t.key,className:`${t.sel.slice(1)}${t.key==="dur"?" req-num":""} ta-${t.align}`,children:t.label},t.key))},"__head")}function iW(){const[e,t]=x.useState(sW),[a,o]=x.useState(()=>TI()),[c,d]=x.useState(()=>sn.range),[f,p]=x.useState(!1),[h,b]=x.useState(0),[y,v]=x.useState(()=>sn.size),[j,w]=x.useState(()=>({ms:Ox,enabled:Mx})),[S,N]=x.useState([]),[k,A]=x.useState([]),[,P]=x.useState(0),R=x.useRef(null),C=x.useRef(null),E=x.useRef(!1),D=x.useCallback(ee=>(sn.filters={...sn.filters,...ee},o({...sn.filters}),sn.filters),[]),I=x.useCallback(ee=>{sn.range=ee,d(ee)},[]),O=x.useCallback(ee=>{sn.offset=ee,b(ee)},[]),_=x.useCallback(ee=>{sn.runningOnly=ee,p(ee)},[]),z=x.useCallback(()=>{eS||!As().wbFilterMemory||(eS=!0,!NI&&D(TI()))},[D]),H=x.useCallback((ee,he)=>{As().wbRequestHover?.beforeListRedraw?.(),he&&(tS=he),E.current=!0,t(ee)},[]),B=x.useCallback(ee=>{As().wbRequestHover?.beforeListRedraw?.(),E.current=!0,t(he=>({...he,error:ee}))},[]),L=x.useCallback(async(ee={})=>{const{silent:he=!1,resetPage:te=!1}=ee;te&&O(0),tW(),z(),he||OI();const ke=++kI;try{const le=As().workbuddyDesktop;if(!le)throw new Error(r("后端桥不可用"));const de=await le.getStatsRequests(GZ());if(ke!==kI)return;const Se={entries:Array.isArray(de?.entries)?de.entries:[],total:Number(de?.total)||0,matched:Number(de?.matched)||0,running:Number(de?.running)||0,loaded:!0,error:""},Te=Math.max(0,(Math.ceil(Se.matched/sn.size)-1)*sn.size);if(sn.offset>Te)return O(Te),L({silent:he});te&&(C.current=0),H(Se,Se.entries)}catch(le){he||(console.warn("读取请求日志失败:",X0(le)),B(r("读取请求日志失败,详见控制台")))}},[O,H,B,z]);x.useEffect(()=>(Ju={load:L,setAuto:ee=>w(ee),setFilterOptions:(ee,he)=>{N(ee),A(he)},repaint:()=>P(ee=>ee+1)},As().wbRequestHover?.bind?.({host:R.current,entryOf:ee=>{const he=ee?.dataset?.reqId||"";return he&&(tS.find(te=>String(te?.id||"")===he)||tS.find(te=>String(te?.ts||"")===he))||null}}),L({silent:!0}),OI(),()=>{Ju=null}),[L]),x.useLayoutEffect(()=>{nW(),P(ee=>ee+1)},[]);const F=e.error||!e.entries.length?"":cS().map(ee=>ee.key).join("|");x.useLayoutEffect(()=>{F&&As().wbTableColumns?.repaint?.("requests")},[F]),x.useEffect(()=>{if(!j.enabled||j.ms<=0)return;const ee=window.setInterval(()=>{document.hidden||As().wbApp?.currentPage!=="requests"||sS||(sS=!0,L({silent:!0}).finally(()=>{sS=!1}))},j.ms);return()=>{window.clearInterval(ee)}},[j,L]),x.useLayoutEffect(()=>{E.current&&(E.current=!1,As().wbRequestHover?.afterListRedraw?.());const ee=C.current;if(ee===null)return;C.current=null;const he=R.current;he&&(he.scrollTop=ee)});function $(ee){const he=Math.max(1,Math.ceil(e.matched/sn.size)),ke=(Math.min(Math.max(1,ee),he)-1)*sn.size;ke!==sn.offset&&(O(ke),C.current=0,L())}function X(ee){const he=bI(ee);if(he===sn.size)return;sn.size=he,v(he),mg("requests",he);const te=sn.offset+1;O(Math.max(0,Math.floor((te-1)/he)*he)),C.current=0,L()}function K(ee){NI=!0,qZ(D(ee)),L({resetPage:!0})}function q(ee){const he=W0.includes(ee)?ee:J0;he!==sn.range&&(I(he),$Z(he),L({resetPage:!0}))}function Q(ee){ee!==sn.runningOnly&&(_(ee),L({resetPage:!0}))}const G=cS(),J=Math.max(1,Math.ceil(e.matched/sn.size)),Y=Math.min(J,Math.floor(h/sn.size)+1),re=e.matched?h+1:0,M=e.matched?h+e.entries.length:0,U=e.error?"—":e.matched===e.total?r("{n} 条",{n:e.total}):r("{matched} / {total} 条",{matched:e.matched,total:e.total}),Z=!f&&e.running>0?r(" · {n} 进行中",{n:e.running}):"",ae=[zZ[c]||r("全部")];f?ae.push(r("只看进行中")):a.status==="ok"?ae.push(r("只看成功")):a.status==="error"&&ae.push(r("只看失败")),a.provider&&ae.push(RI(a.provider)),a.model&&ae.push(a.model);const ce=x.useMemo(()=>!a.provider||S.some(ee=>ee.value===a.provider)?S:[{value:a.provider,label:a.provider},...S],[a.provider,S]),W=x.useMemo(()=>!a.model||k.includes(a.model)?k:[a.model,...k],[a.model,k]),ue=eW(e.entries),ve=e.entries.map((ee,he)=>s.jsx("div",{className:`req-row${Ap(ee)?" running":oS(ee)?"":" failed"}`,children:G.map(te=>lW(ee,te))},ue[he]));return s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("请求日志列表")}),s.jsx(ze,{id:"req-badge",variant:"outline","data-tone":"",children:U+Z}),s.jsx("span",{className:"panel-sub",children:r("按时间倒序,全量保留")}),s.jsx("div",{className:"head-actions",children:s.jsx(ne,{id:"btn-req-clear",variant:"destructive",onClick:()=>{As().wbRequestClearModal?.open?.()},children:r("清理")})})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"log-filters",children:[s.jsx(En,{options:HZ,value:c,onValueChange:q,"aria-label":r("请求日志时间范围"),className:"shrink-0"}),s.jsxs(ut,{value:a.status,disabled:f,onValueChange:ee=>K({status:String(ee??"")}),children:[s.jsx(ft,{id:"req-status",className:"min-w-[120px]",title:r(f?"「仅看进行中」开启时,状态固定为进行中":"按请求结果筛选"),"aria-label":r("按请求结果筛选"),children:s.jsx(dt,{children:jI.find(ee=>ee.value===a.status)?.label??UZ})}),s.jsx(pt,{children:jI.map(ee=>s.jsx($e,{value:ee.value,children:ee.label},ee.value))})]}),s.jsxs(ut,{value:a.provider,onValueChange:ee=>K({provider:String(ee??"")}),children:[s.jsx(ft,{id:"req-provider",className:"min-w-[120px]",title:r("按提供商筛选(只列日志里出现过的)"),"aria-label":r("按提供商筛选"),children:s.jsx(dt,{children:a.provider?ce.find(ee=>ee.value===a.provider)?.label||a.provider:wI})}),s.jsxs(pt,{children:[s.jsx($e,{value:"",children:wI}),ce.map(ee=>s.jsx($e,{value:ee.value,children:ee.label},ee.value))]})]}),s.jsxs(ut,{value:a.model,onValueChange:ee=>K({model:String(ee??"")}),children:[s.jsx(ft,{id:"req-model",className:"min-w-[120px]",title:r("按模型筛选(只列日志里出现过的;精确匹配模型名)"),"aria-label":r("按模型筛选"),children:s.jsx(dt,{children:a.model||SI})}),s.jsxs(pt,{children:[s.jsx($e,{value:"",children:SI}),W.map(ee=>s.jsx($e,{value:ee,children:ee},ee))]})]}),s.jsx(FF,{id:"btn-req-running",variant:"outline",size:"default",pressed:f,onPressedChange:Q,title:r("只显示正在转发中的请求(状态列按阶段显示:连接中 / 等待响应 / 响应中 / 重试中,用时列显示已用时)"),children:r("仅看进行中")}),s.jsx("div",{className:"spacer"}),s.jsx("span",{className:"panel-sub",id:"req-summary",children:ae.join(" · ")})]}),s.jsx("div",{className:"log-list",id:"req-list",ref:R,children:e.error?s.jsx("div",{className:"log-empty",children:e.error}):e.entries.length?[oW(G),...ve]:s.jsx("div",{className:"log-empty",children:rW(e)})})]}),s.jsx($i,{total:e.matched,range:{start:re,end:M},page:Y,pageCount:J,size:y,sizes:_Z,onSizeChange:X,onPageChange:$,disabled:!e.loaded&&!e.error})]})}async function MI(e={}){await Ju?.load(e)}function cW(){return EI().toString()}function uW(){return rS=0,MI({resetPage:!0})}const DI='.page[data-page="requests"]';let II=!1;function PI(){if(II)return;const e=document.querySelector(DI);e&&(II=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(iW,{})))}document.querySelector(DI)?PI():document.addEventListener("DOMContentLoaded",PI,{once:!0}),window.wbRequestsPanel={load:MI,applyAutoRefresh:iS,visibleColumns:cS,clearParams:cW,notifyCleared:uW},window.wbRequestPhase={labelOf:hI,badgeHtml:IZ,elapsedLineHtml:PZ,elapsedText:gI,phaseOf:Q0};function dW(e){if(e.status==="loading")return kt.appLoading;if(e.status==="unavailable")return kt.modelsDevUnavailable;const t=e.source==="builtin"?kt.modelsDevSourceBuiltin:e.source==="cache"?kt.modelsDevSourceCache:e.source==="network"?kt.modelsDevSourceNetwork:e.source,a=e.updatedAt>0?String(tt().wbApp?.formatTime?.(e.updatedAt)??""):"";if(!t&&!a&&!e.count)return kt.modelsDevEmpty;const o=a?r(",{time}",{time:a}):"",c=e.enabled?r("正在联网更新"):r("仅用现有数据、不联网刷新");return r("{count} 条 · 来自{origin}{at} · {mode}",{count:Number(e.count).toLocaleString("zh-CN"),origin:t||r("未知来源"),at:o,mode:c})}function tt(){return window}function Ot(e){return e instanceof Error?e.message:String(e)}function Ve(e,t){tt().wbApp?.toast?.(e,t)}async function fW(e){try{await tt().workbuddyDesktop?.openReleasePage?.(e)}catch(t){Ve(r("打开链接失败:{error}",{error:Ot(t)}),"err")}}const Ix=[{id:"general",label:r("通用"),icon:"sliders"},{id:"assistant",label:r("AI 助手"),icon:"spark"},{id:"display",label:r("显示"),icon:"display"},{id:"gateway",label:r("网关"),icon:"traffic"},{id:"routing",label:r("路由"),icon:"route"},{id:"retry",label:r("重试"),icon:"refresh"},{id:"timeout",label:r("超时"),icon:"timer"},{id:"security",label:r("安全"),icon:"shield"},{id:"data",label:r("数据"),icon:"database"},{id:"feedback",label:r("反馈与需求"),icon:"feedback"},{id:"about",label:r("更新"),icon:"download"}],_I="workbuddy-desktop-settings-cat",pW="workbuddy-desktop-theme",mW="workbuddy-desktop-zoom",LI="wb:theme",zI="wb:zoom",uS=80,BI=130,Px=5,hW=Array.from({length:(BI-uS)/Px+1},(e,t)=>uS+t*Px),gW=[{value:"system",label:r("跟随系统")},{value:"light",label:r("浅色")},{value:"dark",label:r("深色")}];function xW(){try{const e=localStorage.getItem(pW);return e==="light"||e==="dark"?e:"system"}catch{return"system"}}function bW(){try{const e=localStorage.getItem(mW);if(e===null||e.trim()==="")return 100;const t=Number(e);if(!Number.isFinite(t))return 100;const a=Math.round(t/Px)*Px;return Math.min(BI,Math.max(uS,a))}catch{return 100}}const dS=1,fS=99999,pS=[{key:"logRetentionDays",id:"settings-retention-log",label:r("事件日志保留天数"),unit:r("天"),min:dS,max:fS,hint:r("登录 / 账号切换 / 429 切换等系统事件,可填 1–99999 天。")},{key:"requestLogRetentionDays",id:"settings-retention-request",label:r("请求日志保留天数"),unit:r("天"),min:dS,max:fS,hint:r("「请求日志」页的逐条请求记录,默认 99999 天(近似全量保留),可填 1–99999 天。")},{key:"dailyAggregateRetentionDays",id:"settings-retention-daily",label:r("按天聚合保留天数"),unit:r("天"),min:dS,max:fS,hint:r("报表页的热力图与按天趋势,默认 99999 天(近似全量保留),可填 1–99999 天。")}],HI=[{key:"retryCount",id:"settings-retry-count",label:r("同一账号重试次数"),unit:r("次"),min:0,max:10,hint:r("在同一个账号上原地重发几次(不含首发;整条请求共用一份,用完后换来的账号只发一次就继续换)。可填 0–10,0 表示失败立即换号。")},{key:"retryCrossProviderCount",id:"settings-retry-cross-provider-count",label:r("切换账号重试次数"),unit:r("次"),min:0,max:10,hint:r("失败后最多再换几个账号试(填 N = 最多换 N 个,首发那个不算)。换到同一家名下另一个账号、或换到另一家,都各算一次;换满仍失败就返回错误。可填 0–10,0 表示失败立即报错。")},{key:"retryIntervalSeconds",id:"settings-retry-interval",label:r("重试间隔"),unit:r("秒"),min:0,max:300,hint:r("两次重试之间的等待时间,两项共用,可填 0–300 秒。")}],UI=[{key:"connectTimeoutSeconds",id:"settings-timeout-connect",label:r("连接中超时"),unit:r("秒"),min:1,max:3600,hint:r("建立上游 TCP/TLS 连接或代理隧道的最大等待时间(秒),默认 30 秒,范围 1~3600。")},{key:"headersTimeoutSeconds",id:"settings-timeout-headers",label:r("等待响应超时"),unit:r("秒"),min:1,max:3600,hint:r("请求发出后等待上游响应头的最大时间(秒),默认 300 秒,范围 1~3600。")},{key:"streamIdleTimeoutSeconds",id:"settings-timeout-stream-idle",label:r("流式响应空闲超时"),unit:r("秒"),min:1,max:3600,hint:r("流式响应相邻数据之间允许的最大空闲时间(秒),收到新数据后重新计时,默认 300 秒,范围 1~3600。")},{key:"bodyTimeoutSeconds",id:"settings-timeout-body",label:r("非流式响应超时"),unit:r("秒"),min:1,max:3600,hint:r("读取完整非流式响应体允许的最大时间(秒),默认 300 秒,范围 1~3600。")}],VI=[{key:"queueMaxWaits",id:"settings-queue-max-waits",label:r("排队等待次数"),unit:r("次"),min:0,max:10,hint:r("上游模型繁忙时会先排队(回一句「建议 N 秒后再来」,Qoder 免费模型就是这样):网关等一会儿再发同一请求,最多等几次。默认 2 次,可填 0–10;填 0 表示不等待,排队直接返回 503 并说明「不是登录态或额度问题」。")},{key:"queueWaitSeconds",id:"settings-queue-wait-seconds",label:r("排队等待秒数"),unit:r("秒"),min:0,max:120,hint:r("每次等待的时长,默认 0 = 跟随上游建议(实测 9~30 秒,上游没给建议时用 15 秒)。可填 0–120 秒强制一个固定时长。")}],FI="noRetryStatusCodes",mS=100,hS=599,$I=50,$o=[{value:"passthrough",optionLabel:r("透传客户端 system(默认)"),toastLabel:r("透传客户端 system")},{value:"custom",optionLabel:r("替换为网关提示词"),toastLabel:r("替换为网关提示词")},{value:"append",optionLabel:r("追加网关提示词"),toastLabel:r("追加网关提示词")}];function qI(e,t,a,o){const c=String(e??"").trim();if(!c)return{ok:!1,message:r("{noun}不能为空(可填 {min}–{max})",{noun:o,min:t,max:a})};if(!/^\d+$/.test(c))return{ok:!1,message:r("{noun}必须是整数",{noun:o})};const d=Number(c);return da?{ok:!1,message:r("{noun}必须在 {min}–{max} 之间(当前填的是 {text})",{noun:o,min:t,max:a,text:c})}:{ok:!0,value:d}}function vW(e,t){const a={...t};if(e&&typeof e=="object"){const o=e;typeof o.closeToTray=="boolean"&&(a.closeToTray=o.closeToTray),typeof o.autostart=="boolean"&&(a.autostart=o.autostart),typeof o.lanAccess=="boolean"&&(a.lanAccess=o.lanAccess),typeof o.lanPanel=="boolean"&&(a.lanPanel=o.lanPanel),typeof o.lightweightMode=="boolean"&&(a.lightweightMode=o.lightweightMode)}return a}function GI(e,t,a){if(!t||typeof t!="object")return null;const o=t,c={...a||{}};for(const d of e){const f=Number(o[d.key]);Number.isInteger(f)&&f>=d.min&&f<=d.max&&(c[d.key]=f)}return e.some(d=>Number.isInteger(c[d.key]))?c:null}function KI(e){if(!Number.isFinite(e)||e<=0)return"0 B";if(e<1024)return`${e} B`;const t=e/1024;if(t<1024)return`${t.toFixed(1)} KB`;const a=t/1024;return a<1024?`${a.toFixed(1)} MB`:`${(a/1024).toFixed(2)} GB`}function yW(e){const t=Number(e);return!Number.isFinite(t)||t<0?"—":t.toLocaleString("zh-CN")}const Wn={displayTheme:r("控制界面的深浅色,与左侧边栏底部的三个主题按钮是同一个设置(改哪一处,另一处立刻跟上)。「跟随系统」会随操作系统当前的浅色 / 深色自动切换,并在系统主题变化时即时跟上;选「浅色」或「深色」则把界面固定在该模式,不再随系统变化。窗口标题栏的深浅色会一并同步,不会出现深色界面配一条浅色标题栏的情况。"),displayZoom:r("等比放大或缩小整个界面(文字、控件、间距一起变),效果与浏览器按 Ctrl +/- 相同:80%–130%、5% 一档。窗口本身不缩放,变的是页面内容的显示比例,设置立即生效并记住,下次启动直接按这个比例打开。放得越大可视范围越小,窗口较窄或表格较宽时不建议调得太大。"),displayLanguage:r("界面语言。可选简体中文、繁體中文、English、日本語、한국어、Português (Brasil),或「跟随系统」(按浏览器 / 系统的语言列表自动选)。切换后整页立即刷新;该偏好只存在本机(localStorage),不影响账号、密钥与转发。"),tray:r("默认关闭窗口不会退出程序,而是把窗口缩到系统托盘,转发继续在后台运行(OpenAI 客户端不受影响);要彻底退出程序,请在托盘图标上右键选「退出」。关掉这个开关后,点关闭按钮即退出程序、转发随之中断。「开机自动启动」开启后,登录系统时会自动启动本程序(通常直接驻留托盘),不需要手动打开。"),lightweight:r("开启后,关闭窗口不只是隐藏,而是把界面窗口整个销毁:底层的 WebView2 六个常驻进程(约 200MB 内存)随之退出,网关转发、定时签到、余额查询都在后台进程里继续,不受影响;需要界面时点托盘图标重新打开(WebView 冷启动约 1 秒)。注意:界面销毁期间「ZCode 套餐池(Start Plan)」通道的验证码令牌由界面铸造,无法补充 —— 走该通道的请求会以 503 落进请求日志(写明原因),重新打开界面即自动恢复。此开关只在「关闭窗口时最小化到托盘」开启时有意义,最小化窗口不受影响。"),lan:r("默认网关只监听 127.0.0.1,只有本机能访问。开启后网关改听所有网卡,同一局域网内的设备可以把 API 地址指向本机 IP 一起使用。出于安全考虑,开启前必须先注册一个面板管理员:管理接口从此要求管理员会话或网关 Key,模型额度不会对局域网裸奔;一把启用的网关 Key 都没有时,转发接口也会拒绝服务,直到创建第一把。改动需要重启应用生效。「同时开放网页管理面板」把管理界面也出给局域网(其他设备的浏览器打开本机 IP 即可管理),默认关闭 —— 桌面端的面板仍只由本程序自己出。"),units:r("控制报表与请求日志里 Token 读数的写法:开启后按中文量级显示(1.2亿 / 8400万),关闭则用 k / M 缩写(与上游文档、接口字段的写法一致)。这只影响显示口径,不改变任何统计与存储的数值。"),queue:r("只对「排队制」的上游生效(目前是 Qoder 的免费模型):模型繁忙时上游不报错,只回一句「建议 N 秒后再来」(业务码 10605),网关按建议时长等一会儿再发同一请求,等满次数仍排不上才把「排队中」作为错误返回(HTTP 503,文案会说明这不是登录态或额度问题)。等待发生在首个字节之前,吃的是「等待响应超时」那份预算 —— 两项设置一起决定一次请求最多卡多久;排队不会标记账号限额、也不会换账号(换谁都一样在排队)。保存后对下一个请求立即生效,不用重启。"),captchaPool:r("ZCode「套餐池(Start Plan)」通道的每条推理请求都要附一个当次铸造的阿里云无痕验证令牌(一次性、约 2 分钟过期):令牌由界面里的铸造守卫静默铸好、推给网关入池,转发时逐条取用。这里的三个值管的是补货节奏:①「库存目标」= 库存低于它守卫才补铸、补到它为止,默认 3 个;②「轮询间隔」= 守卫多久看一次库存,默认 2500 毫秒,只影响反应速度(库存够用时不会多铸);③「单轮铸造上限」= 发现缺货时一轮最多铸几个,默认 1 个(连铸之间固定隔 500 毫秒)。请求密集、请求日志里连续出现「需要人机验证令牌」的 503 时,把目标与单轮上限适当调大、轮询调快,能让池子跟得上消耗 —— 代价是上游(阿里云)对铸造频率有风控,铸得越多越快越容易触发限流,且用不掉的令牌 2 分钟即过期作废、等于白烧配额,所以建议小步调。保存后对下一轮补货立即生效,不用重启。"),timeouts:r("上游请求四个阶段各自的等待上限(秒,1~3600):①「连接中超时」= 建立 TCP/TLS 连接或代理隧道的最大等待,默认 30 秒;②「等待响应超时」= 请求发出后等上游响应头的最大时间,默认 300 秒 —— 网关请求上游恒带 stream,响应头在 SSE 建立时就到达,与模型思考多久无关;③「流式响应空闲超时」= 流式响应相邻两块数据之间允许的最大空闲,收到新数据即重新计时,默认 300 秒 —— 上游长时间不吐数据即判定连接僵死并断开;④「非流式响应超时」= 读完整份非流式响应体的总预算(一次性计时、不重置),默认 300 秒。四项都是「等待上限」,只要数据还在来,正常的流式回答就一直往下传。保存后对下一个请求立即生效,不用重启。"),retry:r("请求转发到上游失败时(服务器瞬时错误、连接失败,以及 WorkBuddy 的 11-128 敏感词拦截),网关会等一段间隔后再发一次。次数分两档,管的是两件事:①「同一账号重试次数」在同一账号上原地重发几次 —— 一般是提示词被上游拦截、或链路瞬时抖动,等一会儿重发往往就好了;②「切换账号重试次数」这份请求最多再换几个账号试 —— 首发的那个账号不算,每换一个扣一次,不分是不是同一家(换到同一家的下一个账号也算一次),换满还失败就把错误返回给客户端。两项都设为 0 表示失败不重试、直接报错。注意账号级限额(429)不占这里的换号次数 —— 那类失败走「冷却该账号并换下一个账号」的降级,与这里的重试是两条路。另有「指定错误码直接换号」名单(默认 402):命中名单的上游状态码不在同一账号重发,直接按队列换下一个账号继续试(换号也占「切换账号重试次数」),换满仍失败才把错误返回给客户端。"),routing:r("转发一个请求时按什么顺序挑账号:①「路由策略」决定排队规则 —— 顺序优先是排第 1 的接走所有请求、直到它不能答(限流 / 故障 / 额度尽)才轮到下一位;负载均衡是每条请求换下一位,把负载摊到各个账号上。②「会话粘性」让同一会话(相同的模型 + 相同的开头消息)尽量跟住同一个账号 —— 多轮对话的上下文缓存能复用、少换号少浪费;自动档粘 5 分钟、会话内档粘 6 小时、每轮与关闭都不粘。账号的排队位次(账号表的第一列)在所有策略下都是地基,策略在它之上再排。此外路由还有三层自愈保护:转发失败的账号退避休息一会儿(15 分钟起步翻倍、封顶 1 小时)、被 429 的账号垫底排到队尾 30 分钟、余额不足 / Token 周期用量到顶的账号由限制器拦下 —— 前两层可以在下面按需开关,限制器由账号的「限制器」设置管。"),sanitize:r("上游用「逐字精确匹配」的方式审核请求体(不是语义审核):客户端注入的固定模板句、计费头字段名、以及某些裸错误码出现在报文里就会整单拦截,返回 400。开启本项后,网关在每次转发前改写这些指纹 —— 表头键值整段删除,承载语义的模板句只换一个词(如 official CLI for Claude → official CLI tool for Claude),对话内容与语义都不受影响。规则集是内置的,不需要也无法维护词表。关掉本项后客户端模板会原样发往上游,可能重新出现模板句被误拦的报错。"),developerRoleCompat:r("OpenAI 新版 API 用 developer 角色取代 system 承载指令,新版 OpenAI SDK 与部分客户端发的对话里会出现 role 为 developer 的消息;不少 OpenAI 兼容上游(尤其是自定义提供商的透传路径)不认识这个角色,收到就报 400。开启本项后,网关在每次转发前把 developer 角色的消息改写为 system —— 两类角色在 OpenAI 语义上等价(OpenAI 自己的迁移指南也是这么映射的),改写不影响对话内容与语义;对本来就只认 system 的各家内置上游同样无害。默认开启;关掉后 developer 消息会原样发往上游,不认识它的上游会报「角色不存在」一类的错误。"),clineHeaders:r("Cline 上游按请求头判定「调用方是不是 Cline 自家产品」:X-CLIENT-TYPE: cline-sdk 是硬门槛(缺了它免费池模型一律 403),版本号与平台标识让请求更贴近官方客户端的形态。这里列出的是网关默认会发的头:改某一行的值 = 覆盖默认值(也可以新增默认清单之外的自定义头);把值清空保存 = 这个头不发送;在界面删掉被改过的行 = 回落默认值。改完点「保存」,下一个 Cline 请求立即生效。不懂某一行的含义就不要动它 —— 伪装头的价值在「与官方客户端逐字一致」。"),cors:r("网关面(/v1/*)默认不应答浏览器跨源请求:页面直连会被预检拦下,只报「无法连接 API」。注意来源是 * —— 未配「网关 Key」时任何网页都能借本机网关打上游,故默认关闭;只给自己用的话,让页面与网关同源(本地反代 /v1)更稳妥。面板接口(/api/*)不受影响。"),prompt:r("客户端(Claude Code / Codex 等 CLI)会在 system 提示词里注入几十句固定模板,上游按逐字匹配审核,命中就整单拦截(HTTP 400)。指纹脱敏能改写实测命中过的那几句,但换一个客户端版本就可能冒出新的。这里可以把 system 整段换成网关自己那份:①「透传」= 不动客户端 system(默认,行为与之前完全一致);②「替换」= 删掉客户端所有 system / developer 消息,换成网关的提示词(客户端项目规范随之消失);③「追加」= 在开头连续 system 块之后插入一条网关提示词,既有消息逐字不动(客户端规范与网关提示词并用)。那份提示词有两个来源:提示词文件(留空用内置默认),或直接在界面上编辑正文 —— 编辑过就以那份正文为准(优先于文件),清空则回到文件 / 内置默认。另外,透传 / 追加模式下撞了内容拦截(多半是指纹误报)时,网关会自动换一段最小中性提示词重试一次,并把「降级期」开到次日 00:00 —— 期间所有请求直接带中性提示词出门,不再先撞一次 400;这里能看见并提前解除它。上面几项是**默认值**:想给某个提供商单独配,用下面的「按提供商」加一行(带「网关自带」的家默认就列在那里)—— 不同的上游对这些内容的接受程度不一样。"),debug:r("开启后,网关会把每次转发**发给上游的请求**(请求头 + 请求体)与**上游返回的响应**(状态码 + 响应头 + 响应体)完整保存到本地,供请求日志页的「详情」查看。请求头里的 Authorization、Cookie、API Key 等凭据字段一律替换成 [redacted],不会明文落盘;请求体与响应体按原样保存(可能包含你的对话内容)。报文只保留最近 500 条,超出后丢弃最旧的。这是排障用的临时开关,不需要时建议关闭。"),io:r("导出会把全部账号与自定义提供商定义写入一个 JSON 文件,可以拷到另一台机器上导入后继续使用。导入采用合并策略:同提供商下按业务身份(UID / userId / apiKey 等)去重 —— 已存在的账号只更新凭证,保留本机原有的优先级顺序;新账号追加到转发顺序末尾,不会抢占当前正在使用的账号;自定义提供商定义按 id 合并,本机缺失时自动补建。"),backup:r("把整份数据库(账号、网关配置、事件日志、请求统计、调试报文与桌面设置)导出成一个 SQL 文件,恢复时整体替换本机全部数据 —— 与上面「账号导入 / 导出」的逐条合并是两种语义:恢复会连配置、日志与当前启用状态一起换成备份那台机器的状态。导出默认包含日志与调试报文(文件可能很大),不需要时可以取消勾选只备业务数据。恢复前会自动把当前数据备份到配置目录的 backups/ 下,恢复后需要重新登录管理面板。"),retention:r("三档数据各自独立计时,超出保留天数的部分会被删除:事件日志是登录、账号切换、429 切换这类系统事件;请求日志是网关每次转发到上游的逐条记录;按天聚合供报表页的热力图与按天趋势使用。请求日志与按天聚合默认 99999 天(约 274 年,效果上等于全量保留),事件日志默认 30 天。把某一档改小(例如 30 天改成 7 天)保存后会立即删除超出的历史数据,此操作不可恢复;改大或保持不变不会删除任何数据。三档的可填范围均为 1–99999 天。"),storage:r("全部数据(账号、事件日志、请求记录、调试报文、设置)统一保存在配置目录下的 agent2api.db 这一个 SQLite 数据库里。备份时只需拷贝这个文件;更换保存位置请设置环境变量 AGENT2API_PROXY_HOME 后重启程序。"),modelsDev:r("models.dev 是一个开源的模型资料库(社区维护),这里用它补齐「上游没告诉我们」的模型能力:上下文窗口、最大输出、工具调用、图片、视频、是否支持思考,以及这个模型认识哪些思考档位。优先级是:你在「模型能力」里手工改的值 > 上游清单自己声明的值 > models.dev 的值 —— 它只填上游没声明的空位,从不推翻上游已声明的。网关随包内嵌了一份快照,所以离线、首次启动、访问不通时也有数据;开启时会按「模型目录刷新」任务的间隔联网更新(同一轮里一并刷新,也可在这里立即刷新)。关闭只停联网刷新,已经拿到的数据继续用。")},Un={timeouts:r("保存后立即生效,不用重启;超时按上游失败处理(计入请求日志的「错误」列,并按「请求重试」的设置决定是否重试)。"),queue:r("等待期间请求日志的状态列会显示「排队中」阶段,详情弹窗的「内部重试」里能逐次看到等待时长;等待用尽后返回 HTTP 503(不是 401/429:既不会刷新凭证,也不会把账号标成限额)。"),captchaPool:r("保存后对下一轮补货立即生效,不用重启。守卫跑在应用界面里:轻量模式关窗销毁界面期间无法铸造,走套餐池(Start Plan)通道的请求会以 503 落进请求日志(写明原因),重新打开界面即自动恢复。"),retry:r("保存后立即生效,不用重启;次数用尽仍失败时,错误原样返回给客户端。"),routing:r("保存后立即生效,不用重启:策略与粘性作用于**下一次**转发的选路,进行中的请求不受影响。"),retryCodes:r("命中这些上游状态码的失败不在同一账号重发,直接换下一个账号继续试(换号占用「切换账号重试次数」,换满仍失败才把错误原样返回给客户端)。输入 100–599 的状态码后回车添加,点 × 或退格删除;默认 402(积分不足)。清空全部表示任何错误都照常重试。"),sanitize:r("默认开启。命中明细会记进请求日志的「敏」标签(悬停可看命中了哪几条规则)。本项只改发给上游的副本,客户端看到的响应内容不变。"),developerRoleCompat:r("默认开启。只改 role 字段本身,消息内容与顺序都不动;本项只改发给上游的副本,客户端看到的响应内容不变。"),clineHeaders:r("值与默认值相同的行不占覆盖(存的是「改过的键」,不是全量配置);值留空保存表示这个头不发送,删除改过的行表示回落默认值。改完立即生效,不用重启。"),cors:r("默认关闭。改动立即生效,不用重启;关闭期间的跨源请求会被预检拦下。"),debug:r("开启后新发生的请求才会被记录(已经过去的请求补不回来)。报文统一存放在本地数据库里,只保留最近 500 条(超出后丢弃最旧的),条数见左侧「数据 → 数据存储」的「调试报文」。"),promptMode:r("替换 = 客户端 system / developer 消息全部删掉,换成网关的提示词;追加 = 保留客户端内容,只在开头 system 块之后多插一条。两者都只改发给上游的副本,客户端看到的响应不变。"),promptFile:r("UTF-8 文本文件路径,留空用内置默认提示词(通用编码助手提示词,不含任何会被上游拦截的模板句)。只在「替换 / 追加」模式下生效,透传模式不读它。"),promptText:r("在这里直接编辑提示词正文:保存后以这份文本为准(优先于上面的提示词文件),清空则回到文件 / 内置默认。改一个字不必再去编辑器里开文件。"),promptGatewayText:r("上游按「结构」校验身份:三段必须各自成块,所以这里分开编辑三段(不能合成一段)。动态段里的运行值写成占位符,发请求时才替换:{cwd} 工作目录、{platform} 平台、{shell} shell、{os_version} 系统版本、{git} 是否 git 仓库、{provider} 提供方标识、{model} 模型名。清空某一段 = 那一段恢复官方原文。第三段发出时前面会自带一个空行(官方形状)。"),prompt:r("改完立即生效,不用重启(下一个请求就用新模式)。降级是自动的临时状态,解除后本模式自己的提示词立刻恢复。"),promptProviders:r("「用哪份提示词」本来是按上游分别决定的事,所以每家可以有自己的模式、提示词文件与正文:不在这里列出的提供商一律沿用上面那份默认设置,「跟随默认」把这一家取消、回到默认。带「网关自带」那一行的家(目前是 ZCode 两家)默认就列在这里 —— 那一段是网关自己装上去的文本,不来自客户端也不来自提示词文件,默认开启、可以关掉,也可以改它的正文(改过的那一段以你的文本为准);关掉后还能不能通过上游校验,取决于上游当下的口径,行内说明了实测依据。「模式 / 提示词文件 / 正文」管的是客户端自己的 system 怎么处理,与那个开关是两件事。"),modelsDev:r("「模型管理」里每个能力的来源标记(上游 / models.dev / 已覆盖)读的就是这份数据;映射弹窗的思考档位下拉也按这里的数据只列该模型真实认识的档位。"),retention:r("保存后立即生效:改小保留天数会立刻删除超出的历史数据,且不可恢复。"),storageFile:r("配置目录下的 agent2api.db(账号、日志、请求记录、调试报文与设置都在里面)。"),storageSize:r("库主文件的大小(不含运行期间的 WAL 临时文件,退出时已自动并回)。"),storage:r("数据统一保存在配置目录下的 agent2api.db;如需更换位置,请设置环境变量 AGENT2API_PROXY_HOME 后重启程序。"),captcha:r("开启后,登录页在浏览器后台自动完成验证(对真人无感),而脚本每次尝试都要先算一道题 —— 暴力破解与抢注的成本显著上升。仅影响面板的登录 / 注册,与 API 客户端的 API Key 无关。"),panelLogin:r("当前浏览器以管理员身份登录着本面板。「退出登录」会撤销这台设备的登录会话(30 天内的自动续期一并失效),需要重新输入账号密码;其他已登录的设备不受影响。"),exportDanger:r("导出文件内含 accessToken / refreshToken / apiKey 等凭证与自定义提供商定义,可直接用于登录。请妥善保管,不要外传或上传到公共位置。"),backupDanger:r("备份文件内含全部账号凭证、网关 API Key 与面板管理员凭据,可直接用于登录。请妥善保管,不要外传或上传到公共位置。")},kt={appLoading:"—",appUnavailable:r("主进程未返回启动设置,请更新桌面端后重试"),appTrayOn:r("关闭窗口时程序不退出,转发继续在后台运行;退出请用托盘菜单"),appTrayOff:r("关闭窗口即退出程序,后台转发随之中断"),appLightOn:r("轻量模式已开启:关窗即销毁界面进程(释放约 200MB 内存),网关在后台继续;界面销毁期间 ZCode 套餐池(Start Plan)通道不可用,相关请求会在请求日志里注明原因"),appLightOff:r("未开启轻量模式:关窗仅隐藏窗口,界面进程常驻内存,随时打开不等待"),unitsOn:r("当前显示为「1.2亿 / 8400万」这类中文量级。"),unitsOff:r("当前显示为「1.20M / 8.4k」这类英文缩写。"),debugUnavailable:r("未能读取调试模式设置,请稍后重试"),debugOn:r("正在保存上游原始报文:"),debugOff:r("未开启,转发时不保存任何原始报文。"),sanitizeUnavailable:r("未能读取指纹脱敏设置,请稍后重试"),sanitizeOn:r("正在剥离出站请求里的审核指纹:表头键值整段删除,模板句最小改写。"),sanitizeOff:r("未开启,客户端 system 模板会原样发往上游,可能被内容审核误拦(400)。"),roleCompatUnavailable:r("未能读取开发者角色兼容设置,请稍后重试"),roleCompatOn:r("正在归一角色:developer 角色消息转发前改写为 system。"),roleCompatOff:r("未开启,developer 角色消息会原样发往上游,不认识该角色的上游会报错(400)。"),corsUnavailable:r("未能读取网关跨域访问设置,请稍后重试"),corsOn:r("正在应答跨源请求:浏览器跨域请求可直连 /v1/*。"),corsOff:r("未开启,浏览器跨域无法直连网关。"),modelsDevUnavailable:r("未能读取 models.dev 元数据状态,请稍后重试"),modelsDevSourceBuiltin:r("随包内嵌的快照(发版时的那份)"),modelsDevSourceCache:r("上次成功刷新的结果(存在本机数据库里)"),modelsDevSourceNetwork:r("刚刚从 models.dev 拉到的最新数据"),modelsDevEmpty:r("还没有装载任何数据。"),promptUnavailable:r("未能读取系统提示词设置,请稍后重试"),degradeUntilFallback:r("次日 00:00"),themeSystem:r("当前跟随操作系统的深浅色设置,系统切换时界面会自动跟上。"),themeLight:r("当前固定为浅色模式,不随系统变化。"),themeDark:r("当前固定为深色模式,不随系统变化。"),zoomWeb:r("网页端的界面缩放由浏览器自己控制(Ctrl + / Ctrl -,或浏览器菜单里的缩放),此项不可调。"),zoomDefault:r("当前按 100% 显示(默认比例)。"),languageHint:r("界面语言只保存在本机(localStorage)。切换后整页立即刷新,不影响账号、密钥与转发。")},_x=[{value:"order",label:r("顺序优先"),tip:r("排第 1 的接走所有请求,直到它不能答(限流 / 故障 / 额度尽)才轮到下一位 —— 就是「从上往下」的现状行为。")},{value:"rotate",label:r("负载均衡"),tip:r("每条请求轮换到下一个可用账号;新会话交给当前最闲的那位。适合想把手里的号摊开用、不让某一个一直扛。")},{value:"provider",label:r("家内轮询"),tip:r("家之间仍按优先级,只有同一家内部轮流用各账号 —— 想优先用某几家、又不愿把某一家的某个账号焊死时用它。")}],Lx=[{value:"auto",label:r("自动"),tip:r("同一会话在 5 分钟内尽量跟住同一个账号;停了 5 分钟再发就算新会话。多数场景用它 —— 多轮对话少换号,也不至于把账号焊死。")},{value:"session",label:r("会话内"),tip:r("同一会话在 6 小时内跟住同一个账号;适合一坐几个小时的长会话,上游的上下文缓存能吃到更多。")},{value:"turn",label:r("每轮"),tip:r("每条请求都重新按策略选路 —— 行为与「关闭」一致,仅保留会话识别的记录。")},{value:"off",label:r("关闭"),tip:r("不做会话识别,每条请求都重新按策略选路。")}],jW=[{key:"routingFailoverBackoff",label:r("失败退避"),defaultOn:!0,tip:r("转发失败的账号休息一会儿再回来:15 分钟起步,连续失败翻倍,封顶 1 小时;成功一次立即恢复。目的是「让这次失败先凉一会儿」,免得一条条地反复撞同一个坏账号。")},{key:"routingSink",label:r("限流垫底"),defaultOn:!0,tip:r("还有额度时被 429 的账号排到队尾,30 分钟后自动回到队列(成功转发一次也会立即回来)。它标记的是「疑似共享池被别人抢」,不是「这个账号本身有问题」。⚠️ 注意它与路由策略的配合:在「家内轮询」下,队尾意味着这一家整体被往后排 —— 如果某个提供商的账号被批量限流,它们会集体沉到队尾,那个家可能长时间轮不到。这时可以关掉本项,让 429 过的账号只受冷却约束(冷却到点自动回来)。")},{key:"routingBreakerEnabled",label:r("熔断"),defaultOn:!1,tip:r("连续失败到阈值后把这个账号整个打开(默认关)。与失败退避的分工:退避管「单次失败先凉一会儿」,惩罚轻、自动恢复;熔断管「这个账号现在整体不对劲,别再一条条地试」,要连续成功若干次才关。打开期间该账号被跳过,除非全场只剩它 —— 那时仍放行试一次。")}],YI=[{key:"zcodeCaptchaPoolTarget",id:"settings-captcha-pool-target",label:r("库存目标"),unit:r("个"),min:1,max:10,hint:r("ZCode 套餐池(Start Plan)通道每条请求都要消耗一个当次铸造的人机验证令牌(一次性,2 分钟过期),库存低于该值时界面自动补铸到它。默认 3 个。调大能吸收突发并发,但用不掉的令牌 2 分钟就过期作废,烧的是上游风控配额。可填 1–10。")},{key:"zcodeCaptchaPoolPollMs",id:"settings-captcha-pool-poll-ms",label:r("轮询间隔"),unit:r("毫秒"),min:1e3,max:3e4,hint:r("铸造守卫每隔多久看一次库存(毫秒)。只影响发现缺货的反应速度 —— 库存够用时轮询不会铸造任何令牌。默认 2500 毫秒,可填 1000–30000。")},{key:"zcodeCaptchaPoolMaxPerRound",id:"settings-captcha-pool-max-per-round",label:r("单轮铸造上限"),unit:r("个"),min:1,max:5,hint:r("发现缺货时一轮最多铸几个(连铸之间固定隔 500 毫秒)。默认 1 个:SDK 同一实例连铸容易互相干扰。调大补货更快,但单轮连铸越多越容易触发上游风控。可填 1–5。")}];function XI(){return tt().workbuddyDesktop?.platform==="web"}let ht={...{category:Ix[0].id,scrollReset:0,busy:null,app:{status:"loading",closeToTray:!1,autostart:!1,lanAccess:!1,lanPanel:!1,lightweightMode:!1,lanIp:null,port:0,adminRegistered:null},unitsChinese:!0,retention:{status:"loading",values:null},retry:{status:"loading",values:null},retryCodes:null,timeouts:{status:"loading",values:null},queue:{status:"loading",values:null},captchaPool:{status:"loading",values:null},routing:{status:"loading",strategy:"order",sticky:"auto",failoverBackoff:!0,sink:!0,breakerEnabled:!1},debug:{status:"loading",on:!1,count:null,limit:null},sanitize:{status:"loading",on:!1},developerRoleCompat:{status:"loading",on:!1},clineHeaders:{status:"loading",defaults:{},overrides:{},effective:{}},cors:{status:"loading",on:!1},prompt:{status:"loading",mode:"passthrough",file:"",text:"",source:"",lines:0,fileError:"",degradeActive:!1,degradeUntilText:"",providers:[],gateway:{},gatewayText:{},options:[]},storage:{status:"loading",available:!0,file:"",bytes:0,accounts:null,logs:null,requests:null,dailyDays:null,debug:null},captcha:{available:!0,enabled:!1},modelsDev:{status:"loading",enabled:!0,source:"",updatedAt:0,count:0},ioFailure:null,retentionConfirm:null,dbIncludeLogs:!0,dbBackupConfirm:null,dbWarning:null,lanConfirm:null,lanRegister:null,panelLogin:!1},panelLogin:XI()};const gS=new Set;function wW(e){return gS.add(e),()=>{gS.delete(e)}}function SW(){return ht}function NW(){return x.useSyncExternalStore(wW,SW)}function Xe(e){ht={...ht,...e};for(const t of gS)t()}function Ma(e){Xe({app:{...ht.app,...e}})}function Da(){Xe({})}let Sn=null;function is(e){Sn=e,Xe({busy:e})}function Jn(){Sn=null,Xe({busy:null})}function xS(e){const t=Ix.some(a=>a.id===e)?String(e):Ix[0].id;Xe({category:t,scrollReset:ht.scrollReset+1})}function kW(e){xS(e);try{localStorage.setItem(_I,e)}catch{}}function QI(){let e=null;try{e=localStorage.getItem(_I)}catch{e=null}xS(e)}function ZI(){Xe({unitsChinese:tt().wbUnits?.isChinese?.()!==!1})}function CW(e){tt().wbUnits?.setChinese?.(e),ZI(),Ve(r(e?"✅ 已改用本地量级词(万 / 亿式)":"✅ 已改用 k / M 缩写"))}function bS(e){if(e===void 0)return;if(!e||typeof e!="object"){Ma({status:"unavailable"});return}const t=e;Ma({status:"ready",closeToTray:t.closeToTray===!0,autostart:t.autostart===!0,lanAccess:t.lanAccess===!0,lanPanel:t.lanPanel===!0,lightweightMode:t.lightweightMode===!0})}async function WI(){try{bS(await tt().workbuddyDesktop?.getAppSettings())}catch(e){console.warn("读取应用设置失败:",Ot(e)),bS(null)}}async function TW(){const e=tt().workbuddyDesktop;if(e?.localIp){try{Ma({lanIp:await e.localIp()||null})}catch{}try{const t=Number((await e.getBackendStatus?.())?.port)||0;t&&Ma({port:t})}catch{}try{const t=(await e.panelAdminStatus?.())?.registered===!0;Ma({adminRegistered:t})}catch{}}}async function vS(e,t){if(Sn){Da();return}const a=ht.app,o={closeToTray:e==="tray"?t:a.closeToTray,autostart:e==="autostart"?t:a.autostart,lanAccess:a.lanAccess,lanPanel:a.lanPanel,lightweightMode:e==="lightweight"?t:a.lightweightMode};is("app"),Ma(o);const c=r(e==="autostart"?"开机自动启动":e==="lightweight"?"轻量模式":"关闭窗口时最小化到托盘");try{const d=tt().workbuddyDesktop;if(!d)throw new Error(r("主进程桥不可用"));const f=await d.saveAppSettings(o);Ma({status:"ready",...vW(f,o)}),Ve(r("✅ 已更新「{label}」",{label:c}))}catch(d){Ma(a),Ve(r("保存失败:{message}",{message:Ot(d)}),"err")}finally{Jn()}}function EW(e){if(Sn){Da();return}Xe({lanConfirm:{mode:e?"enable":"disable",panel:ht.app.lanPanel}})}function AW(e){if(Sn){Da();return}Xe({lanConfirm:{mode:"panel",panel:e}})}function yS(e){const t=ht.lanConfirm;if(Xe({lanConfirm:null}),!(!t||!e)){if(t.mode==="disable"){zx(!1,!1);return}if(t.mode==="panel"){zx(!0,t.panel);return}RW()}}async function RW(){const e=tt().workbuddyDesktop;if(!e?.panelAdminStatus){Ve(r("当前环境不支持局域网访问设置"),"err");return}is("lan");let t;try{t=(await e.panelAdminStatus())?.registered===!0}catch(a){Jn(),Ve(r("查询管理员状态失败:{message}",{message:Ot(a)}),"err");return}if(Jn(),Ma({adminRegistered:t}),t){await zx(!0,ht.app.lanPanel);return}Xe({lanRegister:{busy:!1,error:""}})}async function OW(e,t){if(Sn)return;const a=tt().workbuddyDesktop;if(!a?.panelRegister)return;const o=e.trim();if(!o||o.length>64){Xe({lanRegister:{busy:!1,error:r("请填写管理员账号(64 字符以内)")}});return}if(t.length<8){Xe({lanRegister:{busy:!1,error:r("密码至少 8 位")}});return}Xe({lanRegister:{busy:!0,error:""}});try{if(await a.panelRegister(o,t),ht.lanRegister===null)return;Xe({lanRegister:null}),Ma({adminRegistered:!0}),await zx(!0,ht.app.lanPanel)}catch(c){Xe({lanRegister:{busy:!1,error:Ot(c)}})}}function JI(){Xe({lanRegister:null})}async function zx(e,t){if(Sn)return;const a=tt().workbuddyDesktop;if(!a?.changeLanAccess){Ve(r("当前环境不支持局域网访问设置"),"err");return}is("lan"),Ma({lanAccess:e,lanPanel:t});try{(await a.changeLanAccess(e,t))?.createdKey&&Ve(r("✅ 已自动创建网关 Key「默认」(可在「网关 Key」页查看)")),Ve(r("✅ 设置已保存,应用正在重启…"))}catch(o){Ve(r("保存失败:{message}",{message:Ot(o)}),"err"),await WI()}finally{Jn()}}async function MW(){if(!Sn){Xe({ioFailure:null}),is("export");try{const e=await tt().workbuddyDesktop?.exportAccounts();if(e?.canceled){Ve(r("已取消导出"));return}const t=Number(e?.count)||0,a=Number(e?.customProviders)||0;if(!t&&!a){Ve(r("没有可导出的账号"),"err");return}const o=a?r("、{n} 个自定义提供商",{n:a}):"",c=e?.file?r(" 到 {file}",{file:e.file}):"";Ve(r("✅ 已导出 {count} 个账号{note}{file}",{count:t,note:o,file:c}))}catch(e){Ve(r("操作失败:{message}",{message:Ot(e)}),"err")}finally{Jn()}}}async function DW(){if(!Sn){Xe({ioFailure:null}),is("import");try{const e=await tt().workbuddyDesktop?.importAccounts();if(e?.canceled){Ve(r("已取消导入"));return}const t=Number(e?.added)||0,a=Number(e?.updated)||0,o=Number(e?.skipped)||0,c=Number(e?.failed)||0,d=Array.isArray(e?.errors)?e.errors:[],f=e?.customProviders??{},p=Number(f.added)||0,h=Number(f.updated)||0,b=[];o&&b.push(r("跳过 {n} 个",{n:o})),c&&b.push(r("失败 {n} 个",{n:c}));const y=b.length?r(",{items}",{items:b.join(r("、"))}):"",v=p||h?r(",自定义提供商新增 {added} 个、更新 {updated} 个",{added:p,updated:h}):"",j=r("新增 {added} 个、更新 {updated} 个{suffix}{note}",{added:t,updated:a,suffix:y,note:v});if(c){Ve(r("导入完成:{summary}",{summary:j}),"err");const w=d.slice(0,3).map(S=>{const N=S?.customProvider?r("自定义提供商 {id}",{id:S?.id||r("(无 id)")}):S?.id??r("未知账号"),k=S?.message??r("未知原因");return r("{label}({message})",{label:N,message:k})}).join(r(";"));Xe({ioFailure:{failed:c,detail:w,more:d.length>3}})}else Ve(r("✅ 导入完成:{summary}",{summary:j}));(t||a||p||h)&&await tt().wbApp?.refresh?.()}catch(e){Ve(r("操作失败:{message}",{message:Ot(e)}),"err")}finally{Jn()}}}function IW(e){Xe({dbIncludeLogs:e})}async function PW(){if(!Sn){is("dbExport");try{const e=tt().workbuddyDesktop;if(!e?.exportDatabase){Ve(r("当前环境不支持整库备份(仅桌面端可用)"),"err");return}const t=await e.exportDatabase(ht.dbIncludeLogs);if(t?.canceled){Ve(r("已取消导出"));return}const a=Number(t?.bytes)||0,o=Array.isArray(t?.tables)?t.tables.length:0;Ve(r("✅ 已备份 {n} 张表({size})到 {file}",{n:o,size:KI(a),file:t?.file||""}))}catch(e){Ve(r("操作失败:{message}",{message:Ot(e)}),"err")}finally{Jn()}}}function _W(){Sn||Xe({dbBackupConfirm:{includeLogs:ht.dbIncludeLogs}})}function jS(e){Xe({dbBackupConfirm:null}),e&&LW()}async function LW(){if(Sn)return;const e=tt().workbuddyDesktop;if(!e?.importDatabase){Ve(r("当前环境不支持整库恢复(仅桌面端可用)"),"err");return}is("dbImport"),Xe({dbWarning:null});try{const t=await e.importDatabase(),a=Array.isArray(t?.tables)?t.tables.length:0,o=t?.safetyBackup?r(",替换前的数据已备份为 {name}",{name:t.safetyBackup}):"";Ve(r("✅ 已恢复 {n} 张表{note}",{n:a,note:o}));const c=typeof t?.warning=="string"?t.warning.trim():"";c&&Xe({dbWarning:c}),await _S(),await tt().wbApp?.refresh?.()}catch(t){Ve(r("恢复失败:{message}",{message:Ot(t)}),"err")}finally{Jn()}}function Bx(e){if(e===void 0)return;const t=GI(pS,e,ht.retention.values);Xe({retention:{status:t===null?"unavailable":"ready",values:t}})}async function Hx(){try{Bx(await tt().workbuddyDesktop?.getRetention())}catch(e){console.warn("读取数据保留设置失败:",Ot(e)),Bx(null)}}let Ux=null;function Vx(e){const t=Ux;Ux=null,Xe({retentionConfirm:null}),t?.(e)}function zW(e){return new Promise(t=>{Ux&&Vx(!1),Ux=t,Xe({retentionConfirm:{head:e}})})}function BW(e,t,a){return t===null?r("没能读到「{label}」的当前值,改为 {days} 天可能会删除超出的历史数据。",{label:e.label,days:a}):r("「{label}」将从 {previous} 天改为 {days} 天。",{label:e.label,previous:t,days:a})}async function HW(e,t){if(Sn||ht.retentionConfirm)return;const a=qI(t,e.min,e.max,r("天数"));if(!a.ok){Ve(a.message,"err");return}const o=ht.retention.values?.[e.key],c=typeof o=="number"&&Number.isInteger(o)?o:null;if(c!==null&&a.value===c)return;const d=c===null||a.valueNumber.isInteger(d?.[f.key]))){const f=d?.[e.key]??t;Ve(a?r("✅ 已保留 {days} 天,超出部分已清理",{days:f}):r("✅ 已保留 {days} 天",{days:f}));return}await Hx(),Ve(a?r("✅ 已保留 {days} 天,超出部分已清理",{days:t}):r("✅ 已保留 {days} 天",{days:t}))}catch(c){Ve(r("保存失败:{message}",{message:Ot(c)}),"err"),await Hx()}finally{Jn()}}function Rp(e,t){if(t===void 0)return;const a=GI(e.fields,t,e.read().values);e.write({status:a===null?"unavailable":"ready",values:a}),e.syncExtras?.(a===null?null:t)}async function ed(e){try{Rp(e,await e.get())}catch(t){console.warn(`${e.consoleLabel}失败:`,Ot(t)),Rp(e,null)}}async function Fx(e,t,a){if(Sn)return;const o=qI(a,t.min,t.max,t.label);if(!o.ok){Ve(o.message,"err");return}const c=e.read().values?.[t.key];if(Number.isInteger(c)&&o.value===c)return;is(e.scope);const d=e.read().values;d&&e.write({status:"ready",values:{...d,[t.key]:o.value}});try{const f=await e.save({[t.key]:o.value});Rp(e,f);const p=e.read().values?.[t.key],h=Number.isInteger(p)?p:o.value;Ve(r("✅ 已保存:{label} {value}",{label:t.label,value:String(h)}))}catch(f){Ve(r("保存失败:{message}",{message:Ot(f)}),"err"),await ed(e)}finally{Jn()}}const eP={scope:"queue",fields:VI,consoleLabel:"读取排队等待设置",get:()=>tt().workbuddyDesktop?.getQueue(),save:e=>tt().workbuddyDesktop?.saveQueue(e),read:()=>ht.queue,write:e=>Xe({queue:e})};async function tP(){await ed(eP)}async function VW(e,t){await Fx(eP,e,t)}const nP={scope:"captchaPool",fields:YI,consoleLabel:"读取验证码令牌池设置",get:()=>tt().workbuddyDesktop?.getCaptchaPool(),save:e=>tt().workbuddyDesktop?.saveCaptchaPool(e),read:()=>ht.captchaPool,write:e=>Xe({captchaPool:e})};async function sP(){await ed(nP)}async function FW(e,t){await Fx(nP,e,t)}const rP="routingStrategy",aP="routingSticky",$W="routingFailoverBackoff",qW="routingSink",GW="routingBreakerEnabled",KW={[rP]:new Set(_x.map(e=>e.value)),[aP]:new Set(Lx.map(e=>e.value))};function lP(e){const t=e&&typeof e=="object"?e:{},a=(c,d)=>{const f=t[c];return typeof f=="string"&&KW[c].has(f)?f:d},o=(c,d)=>{const f=t[c];return typeof f=="boolean"?f:d};return{strategy:a(rP,"order"),sticky:a(aP,"auto"),failoverBackoff:o($W,!0),sink:o(qW,!0),breakerEnabled:o(GW,!1)}}async function $x(){try{const e=await tt().workbuddyDesktop?.getRoutingConfig();if(e===void 0){Xe({routing:{...ht.routing,status:"unavailable"}});return}Xe({routing:{status:"ready",...lP(e)}})}catch(e){console.warn("读取路由设置失败:",Ot(e)),Xe({routing:{...ht.routing,status:"unavailable"}})}}async function wS(e){if(Sn)return;const t=tt().workbuddyDesktop;if(!t?.setRoutingConfig){Ve(r("桌面运行时不可用,暂时无法保存"),"err");return}is("routing");try{const a=await t.setRoutingConfig(e);a!==void 0?Xe({routing:{status:"ready",...lP(a)}}):await $x(),Ve(r("✅ 路由设置已保存"))}catch(a){Ve(r("保存失败:{message}",{message:Ot(a)}),"err"),await $x()}finally{Jn()}}const Op={scope:"retry",fields:HI,consoleLabel:"读取请求重试设置",get:()=>tt().workbuddyDesktop?.getRetry(),save:e=>tt().workbuddyDesktop?.saveRetry(e),read:()=>ht.retry,write:e=>Xe({retry:e}),syncExtras:e=>{if(e===null){Xe({retryCodes:null});return}const t=e[FI];if(!Array.isArray(t))return;Xe({retryCodes:t.filter(o=>typeof o=="number"&&Number.isInteger(o)&&o>=mS&&o<=hS)})}};function YW(e){Rp(Op,e)}async function oP(){await ed(Op)}async function XW(e,t){await Fx(Op,e,t)}async function SS(e){if(!Sn){Xe({retryCodes:e}),is("codes");try{const t=await tt().workbuddyDesktop?.saveRetry({[FI]:e});Rp(Op,t),Ve(r("✅ 已保存:指定错误码直接换号"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await ed(Op)}finally{Jn()}}}async function QW(e){const t=ht.retryCodes;if(t===null)return;const a=String(e??"").trim();if(!a)return;if(!/^\d+$/.test(a)||Number(a)hS){Ve(r("状态码必须是 {min}–{max} 的整数(收到: {text})",{min:mS,max:hS,text:a}),"err");return}const o=Number(a);if(t.includes(o)){Ve(r("状态码 {code} 已在名单里",{code:o}));return}if(t.length>=$I){Ve(r("名单最多 {max} 个状态码",{max:$I}),"err");return}await SS([...t,o])}async function ZW(e){const t=ht.retryCodes;!t||!t.includes(e)||await SS(t.filter(a=>a!==e))}async function WW(){const e=ht.retryCodes;e?.length&&await SS(e.slice(0,-1))}const iP={scope:"timeouts",fields:UI,consoleLabel:"读取请求超时设置",get:()=>tt().workbuddyDesktop?.getTimeouts(),save:e=>tt().workbuddyDesktop?.saveTimeouts(e),read:()=>ht.timeouts,write:e=>Xe({timeouts:e})};async function cP(){await ed(iP)}async function JW(e,t){await Fx(iP,e,t)}function qx(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({debug:{status:"unavailable",on:!1,count:null,limit:null}});return}const t=e,a=Number(t.count),o=Number(t.limit);Xe({debug:{status:"ready",on:t.debugMode===!0,count:Number.isInteger(a)?a:null,limit:Number.isInteger(o)?o:null}})}async function NS(){try{qx(await tt().workbuddyDesktop?.getDebug())}catch(e){console.warn("读取调试模式设置失败:",Ot(e)),qx(null)}}async function eJ(e){if(Sn){Da();return}is("debug"),Xe({debug:{...ht.debug,on:e}});try{const t=await tt().workbuddyDesktop?.saveDebug(e);qx(t),Ve(r(e?"✅ 调试模式已开启":"✅ 调试模式已关闭"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await NS()}finally{Jn()}}function Gx(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({sanitize:{status:"unavailable",on:!1}});return}Xe({sanitize:{status:"ready",on:e.sanitizeBlacklistFingerprints===!0}})}async function kS(){try{Gx(await tt().workbuddyDesktop?.getSanitize())}catch(e){console.warn("读取出站指纹脱敏设置失败:",Ot(e)),Gx(null)}}async function tJ(e){if(Sn){Da();return}is("sanitize"),Xe({sanitize:{status:"ready",on:e}});try{const t=await tt().workbuddyDesktop?.saveSanitize(e);Gx(t),Ve(r(e?"✅ 出站指纹脱敏已开启":"已关闭出站指纹脱敏"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await kS()}finally{Jn()}}function CS(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({developerRoleCompat:{status:"unavailable",on:!1}});return}Xe({developerRoleCompat:{status:"ready",on:e.developerRoleCompat===!0}})}async function TS(){try{CS(await tt().workbuddyDesktop?.getDeveloperRoleCompat())}catch(e){console.warn("读取开发者角色兼容设置失败:",Ot(e)),CS(null)}}async function nJ(e){if(Sn){Da();return}is("developerRoleCompat"),Xe({developerRoleCompat:{status:"ready",on:e}});try{const t=await tt().workbuddyDesktop?.saveDeveloperRoleCompat(e);CS(t),Ve(r(e?"✅ 开发者角色兼容已开启":"已关闭开发者角色兼容"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await TS()}finally{Jn()}}function ES(e){if(!e||typeof e!="object")return{};const t={};for(const[a,o]of Object.entries(e))typeof o=="string"&&(t[a]=o);return t}function AS(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({clineHeaders:{status:"unavailable",defaults:{},overrides:{},effective:{}}});return}const t=e;Xe({clineHeaders:{status:"ready",defaults:ES(t.defaults),overrides:ES(t.overrides),effective:ES(t.effective)}})}async function RS(){try{AS(await tt().workbuddyDesktop?.getClineHeaders())}catch(e){console.warn("读取 Cline 伪装头失败:",Ot(e)),AS(null)}}async function sJ(){await RS(),Ve(r("Cline 伪装头已刷新"))}async function uP(e){if(Sn){Da();return}is("clineHeaders");try{const t=await tt().workbuddyDesktop?.saveClineHeaders(e);AS(t),Ve(r("✅ Cline 伪装头已保存"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await RS()}finally{Jn()}}function OS(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({cors:{status:"unavailable",on:!1}});return}Xe({cors:{status:"ready",on:e.corsEnabled===!0}})}async function MS(){try{OS(await tt().workbuddyDesktop?.getCors())}catch(e){console.warn("读取网关跨域访问设置失败:",Ot(e)),OS(null)}}async function rJ(e){if(Sn){Da();return}is("cors"),Xe({cors:{status:"ready",on:e}});try{const t=await tt().workbuddyDesktop?.saveCors(e);OS(t),Ve(r(e?"网关跨域访问已开启":"已关闭网关跨域访问"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await MS()}finally{Jn()}}async function dP(){try{const e=await tt().workbuddyDesktop?.getCaptchaSetting();Xe({captcha:{available:!0,enabled:e?.captchaEnabled===!0}})}catch(e){Xe({captcha:{available:!1,enabled:!1}}),console.warn("读取机器人校验设置失败:",Ot(e))}}async function aJ(e){if(Sn){Da();return}is("captcha"),Xe({captcha:{...ht.captcha,enabled:e}});try{const t=await tt().workbuddyDesktop?.saveCaptchaSetting(e);Xe({captcha:{available:!0,enabled:t?.captchaEnabled===!0}}),Ve(r(e?"✅ 机器人校验已开启":"⚠️ 机器人校验已关闭"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await dP()}finally{Jn()}}function DS(e){return!e||typeof e!="object"?{status:"unavailable",enabled:!0,source:"",updatedAt:0,count:0}:{status:"ready",enabled:e.modelsDevEnabled!==!1,source:typeof e.source=="string"?e.source:"",updatedAt:Number(e.updatedAt)||0,count:Number(e.count)||0}}async function IS(){try{const e=await tt().workbuddyDesktop?.getModelsDev?.();Xe({modelsDev:DS(e)})}catch(e){Xe({modelsDev:{...ht.modelsDev,status:"unavailable"}}),console.warn("读取 models.dev 元数据设置失败:",Ot(e))}}async function lJ(e){if(Sn){Da();return}is("modelsDev"),Xe({modelsDev:{...ht.modelsDev,enabled:e}});try{const t=await tt().workbuddyDesktop?.saveModelsDev?.(e);Xe({modelsDev:DS(t)}),Ve(r(e?"✅ models.dev 模型元数据已开启":"已关闭 models.dev 联网刷新"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await IS()}finally{Jn()}}async function oJ(){if(Sn){Da();return}is("modelsDevRefresh");try{const e=await tt().workbuddyDesktop?.refreshModelsDev?.();Xe({modelsDev:DS(e?.status)});const t=e?.result,a=String(t?.status||"");a==="refreshed"?Ve(r("models.dev 元数据已更新({count} 条)",{count:Number(t?.count)||0})):a==="failed"?Ve(r("刷新失败:{message}",{message:String(t?.message||"")}),"err"):Ve(String(t?.message||r("本次无需刷新")))}catch(e){Ve(r("刷新失败:{message}",{message:Ot(e)}),"err"),await IS()}finally{Jn()}}function td(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({prompt:{...ht.prompt,status:"unavailable"}});return}const t=e,a=uJ(t.promptGateway);Xe({prompt:{status:"ready",mode:String(t.promptMode||"passthrough"),file:String(t.promptFile||""),text:String(t.promptText||""),source:String(t.promptSource||""),lines:Number(t.promptLines)||0,fileError:String(t.promptFileError||""),degradeActive:t.degradeActive===!0,degradeUntilText:String(t.degradeUntilText||""),providers:iJ(t.promptProviders,a),gateway:a,gatewayText:dJ(t.promptGatewayText),options:cJ(t.promptProviderOptions)}})}function iJ(e,t){return!e||typeof e!="object"?[]:Object.entries(e).filter(([a,o])=>!!a&&!!o&&typeof o=="object").map(([a,o])=>{const c=o;return{id:a,mode:String(c.promptMode||"passthrough"),file:String(c.promptFile||""),text:String(c.promptText||""),source:String(c.promptSource||""),lines:Number(c.promptLines)||0,fileError:String(c.promptFileError||""),gateway:t[a]??!0,configured:!0}}).sort((a,o)=>a.id.localeCompare(o.id))}function cJ(e){return Array.isArray(e)?e.filter(t=>!!t&&typeof t=="object"&&String(t.id||"")).map(t=>{const a=t;return{id:String(a.id),label:String(a.label||a.id),gatewayNote:String(a.gatewayNote||""),gatewayChars:Number(a.gatewayChars)||0,gatewayBlocks:fJ(a.gatewayBlocks)}}):[]}function uJ(e){if(!e||typeof e!="object")return{};const t={};for(const[a,o]of Object.entries(e)){const c=String(a||"").trim();!c||typeof o!="boolean"||(t[c]=o)}return t}function dJ(e){if(!e||typeof e!="object")return{};const t={};for(const[a,o]of Object.entries(e)){const c=String(a||"").trim();if(!c||!o||typeof o!="object")continue;const d=o,f={identity:"",stable:"",dynamic:""};let p=!1;for(const h of["identity","stable","dynamic"]){const b=String(d[h]||"");f[h]=b,b.trim()&&(p=!0)}p&&(t[c]=f)}return t}function fJ(e){if(!e||typeof e!="object")return null;const t=e,a={identity:String(t.identity||""),stable:String(t.stable||""),dynamic:String(t.dynamic||"")};return!a.identity.trim()&&!a.stable.trim()&&!a.dynamic.trim()?null:a}async function dc(){try{td(await tt().workbuddyDesktop?.getPrompt())}catch(e){console.warn("读取系统提示词设置失败:",Ot(e)),td(null)}}async function Mp(e,t){if(Sn)return await dc(),!1;is("prompt");try{const a=await tt().workbuddyDesktop?.savePrompt(t);return td(a),Ve(r("✅ 已保存:{label}",{label:e})),!0}catch(a){return Ve(r("保存失败:{message}",{message:Ot(a)}),"err"),await dc(),!1}finally{Jn()}}async function pJ(e){const t=$o.find(a=>a.value===e);await Mp(r("模式改为「{mode}」",{mode:t?.toastLabel??e}),{promptMode:e})}async function mJ(e){await Mp(e.trim()?r("提示词文件已更新"):r("已改回内置默认提示词"),{promptFile:e})}async function hJ(e){const t=!e.trim();return Mp(r(t?"已清掉界面编辑的提示词(回落文件 / 内置默认)":"提示词正文已更新"),{promptText:t?"":e})}function qo(e,t){return e.options.find(a=>a.id===t)?.label||t}function fc(e){const t=e==null?"":String(e).trim();return t&&ht.prompt.options.some(a=>a.id===t)?t:""}async function Dp(e,t,a){return Mp(e,{promptProviders:{[t]:a}})}function Kx(e,t){const a=!t.configured;return{promptMode:t.mode,promptFile:t.file,promptText:a&&e.source==="inline"?e.text:""}}async function gJ(e){const t=fc(e);if(!t)return;const a=ht.prompt;await Dp(r("已为「{label}」单独配置提示词",{label:qo(a,t)}),t,Kx(a,{mode:a.mode,file:a.file,text:a.text,source:a.source,lines:a.lines,fileError:a.fileError,gateway:a.gateway[t]??!0,configured:!1}))}async function xJ(e,t){const a=fc(e.id);if(!a||!$o.some(c=>c.value===t))return;const o=$o.find(c=>c.value===t);await Dp(r("「{label}」的模式改为「{mode}」",{label:qo(ht.prompt,a),mode:o?.toastLabel??t}),a,{...Kx(ht.prompt,e),promptMode:t})}async function bJ(e,t){const a=fc(e.id);a&&await Dp(t.trim()?r("「{label}」的提示词文件已更新",{label:qo(ht.prompt,a)}):r("「{label}」改用内置默认提示词",{label:qo(ht.prompt,a)}),a,{...Kx(ht.prompt,e),promptFile:t})}async function vJ(e,t){const a=fc(e.id);if(!a)return!1;const o=!t.trim(),c=qo(ht.prompt,a);return Dp(o?r("已清掉「{label}」界面编辑的正文",{label:c}):r("「{label}」的提示词正文已更新",{label:c}),a,{...Kx(ht.prompt,e),promptText:o?"":t})}async function yJ(e){const t=fc(e);t&&await Dp(r("已取消「{label}」的单独配置",{label:qo(ht.prompt,t)}),t,null)}async function jJ(e,t){const a=fc(e);if(!a)return;const o=qo(ht.prompt,a);if(Sn){await dc();return}is("prompt");try{const c=await tt().workbuddyDesktop?.savePrompt({promptGateway:{[a]:t}});td(c),Ve(t?r("✅ 已为「{label}」装上网关自带提示词",{label:o}):r("已关闭「{label}」的网关自带提示词:能否通过上游校验取决于上游当前口径",{label:o}),t?"ok":"err")}catch(c){Ve(r("保存失败:{message}",{message:Ot(c)}),"err"),await dc()}finally{Jn()}}async function wJ(e,t){const a=fc(e);if(!a)return!1;const o=qo(ht.prompt,a),c=!t||!(t.identity.trim()||t.stable.trim()||t.dynamic.trim());return Mp(c?r("「{label}」的网关自带提示词已改回官方原文",{label:o}):r("「{label}」的网关自带提示词正文已更新",{label:o}),{promptGatewayText:{[a]:c?null:t}})}async function SJ(){if(!Sn){is("prompt");try{const e=await tt().workbuddyDesktop?.savePrompt({clearDegrade:!0});td(e),Ve(r("✅ 已解除内容拦截降级"))}catch(e){Ve(r("解除失败:{message}",{message:Ot(e)}),"err"),await dc()}finally{Jn()}}}function Ip(e){const t=Number(e);return Number.isFinite(t)?t:null}function PS(e){if(e===void 0)return;const t=e&&typeof e=="object"?e.database:null;if(!t||typeof t!="object"){Xe({storage:{...ht.storage,status:"unavailable"}});return}const a=t;Xe({storage:{status:"ready",available:a.available!==!1,file:String(a.file||""),bytes:Number(a.bytes)||0,accounts:Ip(a.accounts),logs:Ip(a.logs),requests:Ip(a.requests),dailyDays:Ip(a.dailyDays),debug:Ip(a.debug)}})}async function fP(){try{PS(await tt().workbuddyDesktop?.getStorage())}catch(e){console.warn("读取数据存储概况失败:",Ot(e)),PS(null)}}async function NJ(){try{return await tt().workbuddyDesktop?.panelLogout(),window.location.href="/login",!0}catch(e){return Ve(r("退出失败:{message}",{message:Ot(e)}),"err"),!1}}async function _S(){QI(),ZI(),Xe({panelLogin:XI()}),await Promise.all([WI(),TW(),Hx(),oP(),cP(),tP(),sP(),$x(),NS(),kS(),TS(),RS(),MS(),dc(),fP(),dP(),IS(),tt().wbUpdatePanel?.load?.()])}async function kJ(){await Hx(),Ve(r("保留天数已刷新"))}async function CJ(){await oP(),Ve(r("重试设置已刷新"))}async function TJ(){await cP(),Ve(r("超时设置已刷新"))}async function EJ(){await tP(),Ve(r("排队等待设置已刷新"))}async function AJ(){await sP(),Ve(r("验证码令牌池设置已刷新"))}async function RJ(){await $x(),Ve(r("路由设置已刷新"))}async function OJ(){await NS(),Ve(r("调试模式设置已刷新"))}async function MJ(){await kS(),Ve(r("指纹脱敏设置已刷新"))}async function DJ(){await TS(),Ve(r("开发者角色兼容设置已刷新"))}async function IJ(){await MS(),Ve(r("网关跨域访问设置已刷新"))}async function PJ(){await dc(),Ve(r("系统提示词设置已刷新"))}async function _J(){await fP(),Ve(r("存储概况已刷新"))}const Yx=[{key:"identity",label:r("第一段(身份句)"),short:r("第一段"),hint:r("官方原文只有一句:声明自己是 ZCode。")},{key:"stable",label:r("第二段(稳定段)"),short:r("第二段"),hint:r("工具用法与环境说明那一大段。")},{key:"dynamic",label:r("第三段(动态段)"),short:r("第三段"),hint:r("沟通方式 / 上下文管理 + Environment 段。")}];function LJ(e){return r(e==="inline"?"界面里编辑的正文":e==="file"?"提示词文件":e==="builtin"?"内置默认提示词":"(未生效)")}function pP({title:e,text:t,source:a,file:o,disabled:c,save:d,onClose:f}){const[p,h]=x.useState(t),[b,y]=x.useState(!1),v=b||c,j=p!==t;async function w(S){y(!0);try{await d(S)&&f()}finally{y(!1)}}return s.jsx(Yt,{open:!0,onOpenChange:S=>{S||v||f()},children:s.jsxs(Xt,{className:"w-[min(880px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:e})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("保存后以这里的文本为准")}),s.jsxs("p",{children:[r("这一份就是「替换 / 追加」模式下网关要发的 system 正文。"),a==="none"?r("当前是透传模式:存下来也不会发出,切成「替换 / 追加」之后才生效。"):r("当前生效的正文来自{source}{file}。保存后这一份会盖过提示词文件与内置默认{note}。",{source:LJ(a),file:o.trim()&&a!=="inline"?r("(文件:{path})",{path:o.trim()}):"",note:a!=="inline"&&o.trim()?r(",文件里后续的改动在清空这里之前不再生效"):""}),r("想回到原来那份,把这里清空再保存即可(不会删掉你配的文件路径)。")]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"settings-prompt-body",children:r("提示词正文")}),s.jsx(Mi,{id:"settings-prompt-body",rows:18,className:"min-h-[320px]",spellCheck:!1,disabled:v,value:p,onChange:S=>h(S.currentTarget.value)}),s.jsx("div",{className:"hint",children:p.trim()?r("{lines} 行、{chars} 字符(按当前草稿计)",{lines:p.split(` -`).length,chars:p.length}):r("空 = 不要这一份,回落提示词文件 / 内置默认提示词。")})]})]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",className:"mr-auto",disabled:v||a!=="inline",onClick:()=>{w("")},children:r("清除这里的正文")}),s.jsx(ne,{variant:"outline",disabled:v,onClick:f,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:v||!j,onClick:()=>{w(p)},children:r(b?"保存中…":"保存")})]})]})})}function zJ({prompt:e,locked:t,busy:a}){const[o,c]=x.useState(!1);return s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:"btn-prompt-edit-body",variant:"outline",disabled:t||a,onClick:()=>c(!0),children:r("编辑正文")}),o?s.jsx(pP,{title:r("编辑提示词正文 · 全局"),text:e.text,source:e.source,file:e.file,disabled:a,save:hJ,onClose:()=>c(!1)}):null]})}function BJ({item:e,label:t,locked:a,busy:o}){const[c,d]=x.useState(!1);return s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:`btn-prompt-edit-body-${e.id}`,variant:"outline",disabled:a||o,onClick:()=>d(!0),children:r("编辑正文")}),c?s.jsx(pP,{title:r("编辑提示词正文 · {label}",{label:t}),text:e.text,source:e.source,file:e.file,disabled:o,save:f=>vJ(e,f),onClose:()=>d(!1)}):null]})}function HJ({id:e,title:t,official:a,over:o,enabled:c,disabled:d,onClose:f}){const[p,h]=x.useState(()=>({identity:o?.identity?.trim()?o.identity:a.identity,stable:o?.stable?.trim()?o.stable:a.stable,dynamic:o?.dynamic?.trim()?o.dynamic:a.dynamic})),[b,y]=x.useState(!1),v=b||d,j=Yx.some(N=>p[N.key]!==a[N.key]),w=Yx.filter(N=>o?.[N.key]?.trim()).map(N=>N.label);async function S(N){y(!0);try{await wJ(e,N)&&f()}finally{y(!1)}}return s.jsx(Yt,{open:!0,onOpenChange:N=>{N||v||f()},children:s.jsxs(Xt,{className:"w-[min(880px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:t})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("三段各自成块,所以分开编辑")}),s.jsxs("p",{children:[r("上游按"),s.jsx("strong",{children:r("结构")}),r("校验身份:这三段必须各自成块排在最前(实测:三段并成一段会被回 405 / 3012)。因此这里按段编辑,不能合成一段。改过的段以你的文本为准,没改的段继续用官方原文;清空某一段 = 那一段恢复官方原文。"),w.length?r("当前已改过:{edited}。",{edited:w.join(r("、"))}):r("当前三段都是官方原文。"),c?"":r("注意:这一家的「网关自带」开关现在是关的,改过的正文要等开关打开才生效。")]}),s.jsx("p",{children:Un.promptGatewayText})]}),Yx.map(N=>s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs(Je,{htmlFor:`settings-prompt-block-${e}-${N.key}`,children:[N.label,s.jsx("span",{className:"ml-2 font-normal text-subtle",children:p[N.key]===a[N.key]?r("(官方原文)"):r("(已改)")})]}),s.jsx(Mi,{id:`settings-prompt-block-${e}-${N.key}`,rows:N.key==="identity"?2:10,className:N.key==="identity"?"min-h-[64px]":"min-h-[200px]",spellCheck:!1,disabled:v,value:p[N.key],onChange:k=>{const A=k.currentTarget.value;h(P=>({...P,[N.key]:A}))}}),s.jsx("div",{className:"hint",children:N.hint})]},N.key))]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",className:"mr-auto",disabled:v||!w.length,onClick:()=>{S(null)},children:r("恢复官方原文")}),s.jsx(ne,{variant:"outline",disabled:v,onClick:f,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:v||!j,onClick:()=>{S(p)},children:r(b?"保存中…":"保存")})]})]})})}function UJ({item:e,option:t,over:a,locked:o,busy:c}){const[d,f]=x.useState(!1),p=t.gatewayBlocks;return p?s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:`btn-prompt-gateway-text-${e.id}`,variant:"outline",disabled:o||c,onClick:()=>f(!0),children:r("编辑正文")}),d?s.jsx(HJ,{id:e.id,title:r("编辑网关自带提示词 · {label}",{label:t.label}),official:p,over:a,enabled:e.gateway,disabled:c,onClose:()=>f(!1)}):null]}):null}function VJ(e){return e?Yx.filter(t=>(e[t.key]||"").trim()).map(t=>t.short).join(r("、")):""}function mP(e,t){return tt().wbIcons?.icon?.(e,t)||""}function Jt({tone:e,children:t}){const a=e==="ok"?"success":e==="bad"?"destructive":"outline";return s.jsx(ze,{variant:a,children:t})}function Gn({title:e,tip:t,badge:a,actions:o}){return s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:e}),t?s.jsx("span",{className:"tip-q","data-tip":t}):null,a,o?s.jsx("div",{className:"head-actions",children:o}):null]})}function FJ({title:e,tip:t,badge:a,actions:o,children:c}){function d(f){f.target.closest(".tip-q, .head-actions")&&f.preventDefault()}return s.jsxs("details",{className:"panel panel-fold",children:[s.jsxs("summary",{className:"panel-head",onClick:d,children:[s.jsx("span",{className:"fold-caret","aria-hidden":!0,dangerouslySetInnerHTML:{__html:mP("caretRight",14)}}),s.jsx("h2",{children:e}),t?s.jsx("span",{className:"tip-q","data-tip":t}):null,a,o?s.jsx("div",{className:"head-actions",children:o}):null]}),c]})}function Ur({id:e,label:t,checked:a,disabled:o,tip:c,onCheckedChange:d}){return s.jsxs("label",{className:"switch",children:[s.jsx(ns,{id:e,checked:a,disabled:o,onCheckedChange:f=>d(f)}),s.jsx("span",{children:t}),c?s.jsx("span",{className:"tip-q","data-tip":c}):null]})}function Pp({field:e,value:t,disabled:a,onCommit:o}){const[c,d]=x.useState(null),f=c!==null?c:t===null?"":String(t);async function p(){const h=c;if(h!==null)try{await o(h)}finally{d(null)}}return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:e.id,children:e.label}),s.jsxs("span",{className:"retention-input",children:[s.jsx(Fe,{id:e.id,type:"number",min:e.min,max:e.max,step:1,inputMode:"numeric",className:"w-[92px] max-w-[92px] text-center tabular-nums",value:f,disabled:a||t===null,onChange:h=>d(h.target.value),onFocus:()=>d(String(t??"")),onBlur:()=>{p()},onKeyDown:h=>{h.key==="Enter"&&h.currentTarget.blur()}}),s.jsx("span",{className:"unit",children:e.unit})]}),s.jsx("div",{className:"hint",children:e.hint})]})}function _p(e){return e.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):e.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")})}function kr({id:e,onClick:t}){return s.jsx(ne,{id:e,variant:"outline",onClick:t,children:r("刷新")})}function $J(e){const{lanAccess:t,lanPanel:a,lanIp:o,port:c}=e.app;if(!t)return r("未开启:网关只监听 127.0.0.1,仅本机可以访问。");const d=`http://${o||r("<本机IP>")}${c?`:${c}`:""}`,f=a?r(";网页管理面板已一并开放(浏览器打开同一地址)"):"";return r("已开启:其他设备把 API 地址指向 {url}{panel}。",{url:`${d}/v1`,panel:f})}function qJ({snap:e}){const t=e.app,a=t.status==="unavailable"?kt.appUnavailable:t.status==="loading"?kt.appLoading:t.closeToTray?t.lightweightMode?kt.appLightOn:kt.appTrayOn:kt.appTrayOff;return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("启动与托盘"),tip:Wn.tray,badge:t.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已应用")}):t.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"settings-switches",children:[s.jsx(Ur,{id:"settings-close-to-tray",label:r("关闭窗口时最小化到托盘"),checked:t.closeToTray,disabled:e.busy==="app",onCheckedChange:o=>{vS("tray",o)}}),s.jsx(Ur,{id:"settings-lightweight",label:r("轻量模式(关窗释放界面内存)"),tip:Wn.lightweight,checked:t.lightweightMode,disabled:e.busy==="app"||!t.closeToTray,onCheckedChange:o=>{vS("lightweight",o)}}),s.jsx(Ur,{id:"settings-autostart",label:r("开机自动启动"),checked:t.autostart,disabled:e.busy==="app",onCheckedChange:o=>{vS("autostart",o)}})]}),s.jsx("div",{className:"settings-state",children:a})]})]}),!e.panelLogin&&s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("局域网访问"),tip:Wn.lan}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"settings-switches",children:[s.jsx(Ur,{id:"settings-lan-access",label:r("允许局域网内的设备访问网关"),checked:e.app.lanAccess,disabled:e.busy==="lan",onCheckedChange:EW}),s.jsx(Ur,{id:"settings-lan-panel",label:r("同时开放网页管理面板"),checked:e.app.lanPanel,disabled:e.busy==="lan"||!e.app.lanAccess,onCheckedChange:AW})]}),s.jsx("div",{className:"settings-state",children:$J(e)})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("计量单位"),tip:Wn.units}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-chinese-units",label:r("使用中文单位(亿 / 万)"),checked:e.unitsChinese,onCheckedChange:CW})}),s.jsx("div",{className:"settings-state",children:e.unitsChinese?kt.unitsOn:kt.unitsOff})]})]})]})}function GJ(e){return e==="light"?kt.themeLight:e==="dark"?kt.themeDark:kt.themeSystem}function KJ(){const[e,t]=x.useState(xW),[a,o]=x.useState(bW),c=tt().workbuddyDesktop?.platform==="web";x.useEffect(()=>{const f=h=>t(String(h.detail||"system")),p=h=>o(Number(h.detail)||100);return window.addEventListener(LI,f),window.addEventListener(zI,p),()=>{window.removeEventListener(LI,f),window.removeEventListener(zI,p)}},[]);const d=a===100?r("100%(默认)"):`${a}%`;return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("显示模式"),tip:Wn.displayTheme}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{children:s.jsx(En,{"aria-label":r("显示模式"),options:gW,value:e,onValueChange:f=>tt().wbApp?.applyTheme?.(f)})}),s.jsx("div",{className:"settings-state",children:GJ(e)})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("界面缩放"),tip:Wn.displayZoom}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-zoom",children:r("缩放比例")}),s.jsx("span",{className:"prompt-input",children:s.jsxs(ut,{value:String(a),onValueChange:f=>tt().wbApp?.applyZoom?.(Number(f)),children:[s.jsx(ft,{id:"settings-zoom",className:"w-[140px]",disabled:c,"aria-label":r("界面缩放比例"),children:s.jsx(dt,{children:d})}),s.jsx(pt,{children:hW.map(f=>s.jsx($e,{value:String(f),children:f===100?r("100%(默认)"):`${f}%`},f))})]})}),s.jsx("div",{className:"hint",children:r("放大或缩小整个界面(文字与控件一起变),效果与浏览器 Ctrl +/- 相同:共 11 档,立即生效并记住。")})]})}),s.jsx("div",{className:"settings-state",children:c?kt.zoomWeb:a===100?kt.zoomDefault:r("当前按 {n}% 显示。",{n:a})})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("语言设置"),tip:Wn.displayLanguage}),s.jsxs("div",{className:"panel-body",children:[s.jsx(YJ,{}),s.jsx("div",{className:"settings-state",children:kt.languageHint})]})]})]})}function YJ(){const e=window.wbI18n,t=e?.rawLocale?.()??"auto",a=e?.LOCALES??[],o=c=>c==="auto"?r("跟随系统"):a.find(d=>d.code===c)?.label??c;return s.jsx("div",{className:"retention-list",children:s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-language",children:r("界面语言")}),s.jsx("span",{className:"prompt-input",children:s.jsxs(ut,{value:t,onValueChange:c=>{c&&e?.setLocale(c)},children:[s.jsx(ft,{id:"settings-language",className:"w-[200px]","aria-label":r("界面语言"),children:s.jsx(dt,{children:o(t)})}),s.jsxs(pt,{children:[s.jsx($e,{value:"auto",children:r("跟随系统")}),a.map(c=>s.jsx($e,{value:c.code,children:c.label},c.code))]})]})})]})})}function XJ({codes:e,status:t,busy:a}){const[o,c]=x.useState(""),d=x.useRef(null),f=t==="unavailable";return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-retry-no-codes-input",children:r("指定错误码直接换号")}),s.jsx("div",{className:"retention-input",children:s.jsxs("div",{className:f?"tag-input disabled":"tag-input",onClick:()=>d.current?.focus(),children:[(e||[]).map(p=>s.jsxs("span",{className:"tag-chip",children:[s.jsx("span",{className:"v",children:p}),s.jsx(ne,{type:"button",variant:"ghost",size:"icon-2xs",className:"tag-x text-muted-foreground hover:bg-destructive-soft hover:text-destructive",title:r("删除 {code}",{code:p}),"aria-label":r("删除状态码 {code}",{code:p}),onClick:h=>{h.stopPropagation(),ZW(p)},children:"✕"})]},p)),s.jsx(Fe,{ref:d,id:"settings-retry-no-codes-input",type:"text",className:"tag-input-field h-auto border-0 bg-transparent px-0 shadow-none focus:shadow-none",placeholder:f?"—":r("输入状态码,回车添加"),inputMode:"numeric",autoComplete:"off",value:o,disabled:f||a,onChange:p=>c(p.target.value),onKeyDown:p=>{if(p.key==="Enter"){p.preventDefault(),QW(o),c("");return}p.key==="Backspace"&&!o&&WW()}})]})}),s.jsx("div",{className:"hint",children:Un.retryCodes})]})}function QJ({prompt:e,locked:t,busy:a}){const[o,c]=x.useState(null);async function d(){const f=o;if(f!==null)try{await mJ(f)}finally{c(null)}}return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-prompt-file",children:r("提示词文件")}),s.jsx("span",{className:"prompt-input",children:s.jsx(Fe,{id:"settings-prompt-file",type:"text",placeholder:r("留空 = 用内置默认提示词"),value:o!==null?o:e.file,disabled:t||a,onChange:f=>c(f.target.value),onFocus:()=>c(e.file),onBlur:()=>{d()},onKeyDown:f=>{f.key==="Enter"&&f.currentTarget.blur()}})}),s.jsx("div",{className:"hint",children:Un.promptFile})]})}function ZJ(e){if(e.status==="loading")return kt.appLoading;if(e.status==="unavailable")return kt.promptUnavailable;const t=hP(e.source),a=[];return e.mode==="passthrough"?a.push(r("客户端 system 原样出站(只靠指纹脱敏改写模板句)。")):a.push(r("{mode}生效:上游收到的 system 来自{source}{lines}。",{mode:e.mode==="custom"?r("替换"):r("追加"),source:t,lines:e.lines?r("({n} 行)",{n:e.lines}):""})),e.fileError&&a.push(`⚠️ ${e.fileError}`),a.join("")}function hP(e){return e==="inline"?r("界面里编辑的正文"):e==="file"?r("提示词文件"):e==="builtin"?r("内置默认提示词"):""}function WJ(e){return r("已自动切换到最小中性提示词(撞了上游内容拦截,多半是 system 指纹误报),到 {until} 自动解除。",{until:e.degradeUntilText||kt.degradeUntilFallback})+r("期间本模式自己的提示词不会发出;把提示词改好后可以立即解除。")}function JJ({item:e,label:t,locked:a,busy:o}){const[c,d]=x.useState(null);async function f(){const p=c;if(p!==null)try{p!==e.file&&await bJ(e,p)}finally{d(null)}}return s.jsx("span",{className:"prompt-input",children:s.jsx(Fe,{id:`settings-prompt-file-${e.id}`,type:"text",placeholder:r("留空 = 用内置默认提示词"),"aria-label":r("{label} 提示词文件",{label:t}),value:c!==null?c:e.file,disabled:a||o,onChange:p=>d(p.target.value),onFocus:()=>d(e.file),onBlur:()=>{f()},onKeyDown:p=>{p.key==="Enter"&&p.currentTarget.blur()}})})}function eee(e,t){if(!t)return r("未单独配置:模式、提示词文件与正文都跟随上面的全局配置(当前「{mode}」)。",{mode:$o.find(o=>o.value===e.mode)?.toastLabel??e.mode});if(e.mode==="passthrough")return r("客户端 system 原样出站。");const a=r("{mode}生效:上游收到的 system 来自{source}{lines}。",{mode:e.mode==="custom"?r("替换"):r("追加"),source:hP(e.source),lines:e.lines?r("({n} 行)",{n:e.lines}):""});return e.fileError?`${a} ⚠️ ${e.fileError}`:a}function tee({item:e,option:t,over:a,locked:o,busy:c}){const d=e.gateway,f=t.gatewayChars,p=f?r("约 {n} 字符",{n:f.toLocaleString("zh-CN")}):r("一段内置装配"),h=VJ(a);return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{className:"prompt-gateway-label",children:r("网关自带")}),s.jsxs("span",{className:"prompt-input",children:[s.jsx(Ur,{id:`settings-prompt-gateway-${e.id}`,label:r("装上{size}的官方身份提示词",{size:p}),checked:d,disabled:o||c,onCheckedChange:b=>{jJ(e.id,b)}}),s.jsx(UJ,{item:e,option:t,over:a,locked:o,busy:c})]}),s.jsxs("div",{className:d?"hint":"hint prompt-gateway-off",children:[d?t.gatewayNote:r("已关闭。{note}",{note:t.gatewayNote}),h?r(" 正文已改:{edited}(其余段用官方原文)。",{edited:h}):""]})]})}function nee({prompt:e,locked:t,busy:a}){const o=e.options,c=new Map(e.providers.map(w=>[w.id,w])),d=[];for(const w of o)w.gatewayNote&&d.push(c.get(w.id)??{id:w.id,mode:e.mode,file:e.file,text:e.text,source:e.source,lines:e.lines,fileError:e.fileError,gateway:e.gateway[w.id]??!0,configured:!1});for(const w of e.providers)d.some(S=>S.id===w.id)||d.push({...w,gateway:e.gateway[w.id]??!0,configured:!0});const f=new Set(d.map(w=>w.id)),p=o.filter(w=>!w.gatewayNote&&!f.has(w.id)),[h,b]=x.useState(""),y=w=>o.find(S=>S.id===w)?.label||w,v=w=>o.find(S=>S.id===w),j=w=>v(w)?.gatewayNote||"";return s.jsxs(s.Fragment,{children:[d.map(w=>{const S=y(w.id),N=$o.find(P=>P.value===w.mode)?.optionLabel??w.mode,k=j(w.id),A=v(w.id);return s.jsxs(x.Fragment,{children:[s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:`settings-prompt-mode-${w.id}`,children:S}),s.jsxs("span",{className:"prompt-input",children:[s.jsxs(ut,{value:w.mode,onValueChange:P=>{P!=null&&String(P)&&xJ(w,String(P))},children:[s.jsx(ft,{id:`settings-prompt-mode-${w.id}`,className:"w-[240px]",disabled:t||a,"aria-label":r("{label} 的提示词模式",{label:S}),children:s.jsx(dt,{children:N})}),s.jsx(pt,{children:$o.map(P=>s.jsx($e,{value:P.value,children:P.optionLabel},P.value))})]}),s.jsx(JJ,{item:w,label:S,locked:t,busy:a}),s.jsx(BJ,{item:w,label:S,locked:t,busy:a}),w.configured?s.jsx(ne,{variant:"outline",disabled:t||a,onClick:()=>{yJ(w.id)},children:r("跟随默认")}):null]}),s.jsx("div",{className:"hint",children:eee(w,w.configured)})]}),A&&k?s.jsx(tee,{item:w,option:A,over:e.gatewayText[w.id],locked:t,busy:a}):null]},w.id)}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-prompt-provider-add",children:r("添加提供商")}),s.jsx("span",{className:"prompt-input",children:s.jsxs(ut,{value:h,onValueChange:w=>{b("");const S=w==null?"":String(w);S&&gJ(S)},children:[s.jsx(ft,{id:"settings-prompt-provider-add",className:"w-[240px]",disabled:t||a||p.length===0,"aria-label":r("添加要单独配置的提供商"),children:s.jsx(dt,{children:h?y(h):p.length?r("添加提供商…"):r("全部已配置")})}),s.jsx(pt,{children:p.map(w=>s.jsx($e,{value:w.id,children:w.label},w.id))})]})}),s.jsx("div",{className:"hint",children:Un.promptProviders})]})]})}function see({snap:e}){const t=e.prompt,a=t.status!=="ready",o=e.busy==="prompt",c=$o.find(d=>d.value===t.mode)?.optionLabel??t.mode;return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("系统提示词"),tip:Wn.prompt,badge:t.status==="ready"?s.jsx(Jt,{tone:"ok",children:t.mode==="passthrough"?r("透传"):r("已接管")}):t.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(kr,{id:"btn-prompt-refresh",onClick:()=>{PJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[s.jsxs("div",{className:"prompt-group",children:[r("全局配置"),s.jsx("span",{className:"note",children:r("所有未单独配置的提供商都用这一份")})]}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-prompt-mode",children:r("模式")}),s.jsx("span",{className:"prompt-input",children:s.jsxs(ut,{value:t.mode,onValueChange:d=>{d!=null&&String(d)&&pJ(String(d))},children:[s.jsx(ft,{id:"settings-prompt-mode",className:"w-[240px]",disabled:a||o,"aria-label":r("系统提示词模式"),children:s.jsx(dt,{children:c})}),s.jsx(pt,{children:$o.map(d=>s.jsx($e,{value:d.value,children:d.optionLabel},d.value))})]})}),s.jsx("div",{className:"hint",children:Un.promptMode})]}),s.jsx(QJ,{prompt:t,locked:a,busy:o}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"btn-prompt-edit-body",children:r("提示词正文")}),s.jsx("span",{className:"prompt-input",children:s.jsx(zJ,{prompt:t,locked:a,busy:o})}),s.jsxs("div",{className:"hint",children:[Un.promptText,t.source==="inline"?r("(当前生效的就是这一份,{n} 行)",{n:t.lines}):t.text.trim()?r("(已存一份正文,{n} 行;切成「替换 / 追加」后生效)",{n:t.lines}):""]})]}),s.jsxs("div",{className:"prompt-group",children:[r("按提供商配置"),s.jsx("span",{className:"note",children:r("只列单独配置过的家,其余沿用上面的全局配置")})]}),s.jsx(nee,{prompt:t,locked:a,busy:o}),t.status==="ready"&&t.degradeActive?s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{children:r("内容拦截降级")}),s.jsx("span",{className:"prompt-input",children:s.jsx(ne,{id:"btn-prompt-clear-degrade",variant:"outline",disabled:o,onClick:()=>{SJ()},children:r("立即解除")})}),s.jsx("div",{className:"hint",children:WJ(t)})]}):null]}),s.jsx("div",{className:"settings-state",children:ZJ(t)}),s.jsx("div",{className:"hint retention-note",children:Un.prompt})]})]})}function ree(e){if(e.status==="loading")return kt.appLoading;if(e.status==="unavailable")return kt.debugUnavailable;const t=e.count!==null&&e.limit!==null?r("已保存 {count} / {limit} 条报文(超出后丢弃最旧的)。",{count:e.count,limit:e.limit}):"";return e.on?`${kt.debugOn}${t}${r("凭据类请求头已脱敏。")}`:kt.debugOff}function aee({snap:e}){return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("请求超时"),tip:Wn.timeouts,badge:_p(e.timeouts),actions:s.jsx(kr,{id:"btn-timeouts-refresh",onClick:()=>{TJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:UI.map(t=>s.jsx(Pp,{field:t,value:e.timeouts.values?.[t.key]??null,disabled:e.busy==="timeouts",onCommit:a=>JW(t,a)},t.key))}),s.jsx("div",{className:"hint retention-note",children:Un.timeouts})]})]})}function lee({snap:e}){return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("请求重试"),tip:Wn.retry,badge:_p(e.retry),actions:s.jsx(kr,{id:"btn-retry-refresh",onClick:()=>{CJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[HI.map(t=>s.jsx(Pp,{field:t,value:e.retry.values?.[t.key]??null,disabled:e.busy==="retry",onCommit:a=>XW(t,a)},t.key)),s.jsx(XJ,{codes:e.retryCodes,status:e.retry.status,busy:e.busy==="codes"||e.busy==="retry"})]}),s.jsx("div",{className:"hint retention-note",children:Un.retry})]})]})}const oee={routingFailoverBackoff:"failoverBackoff",routingSink:"sink",routingBreakerEnabled:"breakerEnabled"};function iee({snap:e}){const t=e.routing,a=e.busy==="routing"||t.status!=="ready",o=_x.find(d=>d.value===t.strategy)?.value??"order",c=Lx.find(d=>d.value===t.sticky)?.value??"auto";return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("账号路由"),tip:Wn.routing,badge:t.status==="ready"?void 0:t.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(kr,{id:"btn-routing-refresh",onClick:()=>{RJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[s.jsx("div",{className:"prompt-group",children:r("选路规则")}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{children:r("路由策略")}),s.jsxs("div",{className:"routing-row",children:[s.jsx("span",{className:"tip-q","data-tip":_x.find(d=>d.value===o)?.tip}),s.jsx(En,{options:_x.map(d=>({value:d.value,label:d.label})),value:o,disabled:a,"aria-label":r("路由策略"),onValueChange:d=>{wS({routingStrategy:String(d)})}})]})]}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{children:r("会话粘性")}),s.jsxs("div",{className:"routing-row",children:[s.jsx("span",{className:"tip-q","data-tip":Lx.find(d=>d.value===c)?.tip}),s.jsx(En,{options:Lx.map(d=>({value:d.value,label:d.label})),value:c,disabled:a,"aria-label":r("会话粘性"),onValueChange:d=>{wS({routingSticky:String(d)})}})]})]}),s.jsxs("div",{className:"prompt-group",children:[r("自愈保护"),s.jsx("span",{className:"note",children:r("默认值通常够用,出问题时才需要调")})]}),jW.map(d=>{const f=`route-protection-${d.key}`;return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:f,children:d.label}),s.jsxs("div",{className:"routing-row",children:[s.jsx("span",{className:"tip-q","data-tip":d.tip}),s.jsx(ns,{id:f,checked:t[oee[d.key]],disabled:a,onCheckedChange:p=>{wS({[d.key]:p})}})]})]},d.key)})]}),s.jsx("div",{className:"hint retention-note",children:Un.routing})]})]})}function cee({snap:e}){return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("排队等待"),tip:Wn.queue,badge:_p(e.queue),actions:s.jsx(kr,{id:"btn-queue-refresh",onClick:()=>{EJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:VI.map(t=>s.jsx(Pp,{field:t,value:e.queue.values?.[t.key]??null,disabled:e.busy==="queue",onCommit:a=>VW(t,a)},t.key))}),s.jsx("div",{className:"hint retention-note",children:Un.queue})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("验证码令牌池"),tip:Wn.captchaPool,badge:_p(e.captchaPool),actions:s.jsx(kr,{id:"btn-captcha-pool-refresh",onClick:()=>{AJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:YI.map(t=>s.jsx(Pp,{field:t,value:e.captchaPool.values?.[t.key]??null,disabled:e.busy==="captchaPool",onCommit:a=>FW(t,a)},t.key))}),s.jsx("div",{className:"hint retention-note",children:Un.captchaPool})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("models.dev 模型元数据"),tip:Wn.modelsDev,badge:e.modelsDev.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("{count} 条",{count:Number(e.modelsDev.count).toLocaleString("zh-CN")})}):e.modelsDev.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(kr,{id:"btn-modelsdev-refresh",onClick:()=>{oJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx(Ur,{id:"settings-modelsdev",label:r("用 models.dev 补齐上游没声明的模型能力与思考档位(联网刷新,内嵌快照始终生效)"),checked:e.modelsDev.enabled,disabled:e.modelsDev.status!=="ready"||e.busy==="modelsDev",onCheckedChange:t=>{lJ(t)}}),s.jsx("div",{className:"settings-state",children:dW(e.modelsDev)}),s.jsx("div",{className:"hint retention-note",children:Un.modelsDev})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("指纹脱敏"),tip:Wn.sanitize,badge:e.sanitize.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):e.sanitize.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(kr,{id:"btn-sanitize-refresh",onClick:()=>{MJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-sanitize",label:r("剥离上游审核黑名单指纹(改写请求体里的模板句与表头)"),checked:e.sanitize.on,disabled:e.sanitize.status!=="ready"||e.busy==="sanitize",onCheckedChange:t=>{tJ(t)}})}),s.jsx("div",{className:"settings-state",children:e.sanitize.status==="loading"?kt.appLoading:e.sanitize.status==="unavailable"?kt.sanitizeUnavailable:e.sanitize.on?kt.sanitizeOn:kt.sanitizeOff}),s.jsx("div",{className:"hint retention-note",children:Un.sanitize})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("开发者角色兼容"),tip:Wn.developerRoleCompat,badge:e.developerRoleCompat.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):e.developerRoleCompat.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(kr,{id:"btn-role-compat-refresh",onClick:()=>{DJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-developer-role-compat",label:r("转发前将 developer 角色消息转换为 system,兼容不支持 developer 角色的 OpenAI 兼容上游"),checked:e.developerRoleCompat.on,disabled:e.developerRoleCompat.status!=="ready"||e.busy==="developerRoleCompat",onCheckedChange:t=>{nJ(t)}})}),s.jsx("div",{className:"settings-state",children:e.developerRoleCompat.status==="loading"?kt.appLoading:e.developerRoleCompat.status==="unavailable"?kt.roleCompatUnavailable:e.developerRoleCompat.on?kt.roleCompatOn:kt.roleCompatOff}),s.jsx("div",{className:"hint retention-note",children:Un.developerRoleCompat})]})]}),s.jsx(dee,{snap:e}),s.jsx(see,{snap:e}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("调试模式"),tip:Wn.debug,badge:e.debug.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):e.debug.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(kr,{id:"btn-debug-refresh",onClick:()=>{OJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-debug-mode",label:r("保存上游原始报文(请求头、请求体、响应头、响应体)"),checked:e.debug.on,disabled:e.debug.status!=="ready"||e.busy==="debug",onCheckedChange:t=>{eJ(t)}})}),s.jsx("div",{className:"settings-state",children:ree(e.debug)}),s.jsx("div",{className:"hint retention-note",children:Un.debug})]})]})]})}function gP(e){const t=Object.entries(e.defaults).map(([a,o])=>({key:a,value:a in e.overrides?e.overrides[a]:o,isDefault:!0}));for(const[a,o]of Object.entries(e.overrides))a in e.defaults||t.push({key:a,value:o,isDefault:!1});return t}function uee(e,t){const a=Object.keys(e);return a.length!==Object.keys(t).length?!1:a.every(o=>e[o]===t[o])}function dee({snap:e}){const t=e.clineHeaders,[a,o]=x.useState(()=>gP(t));x.useEffect(()=>{o(gP(t))},[t]);const c=e.busy==="clineHeaders",d=t.status==="ready";function f(b,y){o(v=>v.map((j,w)=>w===b?{...j,...y}:j))}function p(){const b={};for(const y of a){const v=y.key.trim();v&&(y.isDefault?y.value!==(t.defaults[v]??"")&&(b[v]=y.value):y.value!==""&&(b[v]=y.value))}return b}const h=d&&!uee(p(),t.overrides);return s.jsx(FJ,{title:r("Cline 伪装头"),tip:Wn.clineHeaders,badge:t.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):t.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(kr,{id:"btn-cline-headers-refresh",onClick:()=>{sJ()}}),children:s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[d?a.map((b,y)=>s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(Fe,{className:"w-[190px] shrink-0 font-mono text-[13px]",value:b.key,readOnly:b.isDefault,disabled:c,placeholder:"X-Custom-Header",onChange:v=>f(y,{key:v.target.value})}),s.jsx(Fe,{className:"flex-1 font-mono text-[13px]",value:b.value,disabled:c,placeholder:b.isDefault?r("值(留空 = 不发送)"):r("值"),onChange:v=>f(y,{value:v.target.value})}),s.jsx(ne,{variant:"ghost",disabled:c,onClick:()=>{b.isDefault?f(y,{value:t.defaults[b.key]??""}):o(v=>v.filter((j,w)=>w!==y))},children:b.isDefault?r("还原"):r("删除")})]},String(y))):null,s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(ne,{variant:"outline",disabled:c||!d,onClick:()=>o(b=>[...b,{key:"",value:"",isDefault:!1}]),children:r("添加自定义头")}),s.jsx("div",{className:"flex-1"}),s.jsx(ne,{variant:"ghost",disabled:c||!d||Object.keys(t.overrides).length===0,onClick:()=>{uP({})},children:r("恢复默认")}),s.jsx(ne,{disabled:c||!d||!h,onClick:()=>{uP(p())},children:r("保存")})]})]}),s.jsx("div",{className:"settings-state",children:t.status==="loading"?kt.appLoading:t.status==="unavailable"?r("未能读取 Cline 伪装头设置,请稍后重试"):h?r("有未保存的修改"):r("{n} 个头将随每个 Cline 请求发送",{n:Object.keys(t.effective).length})+(Object.keys(t.overrides).length>0?r("({n} 项被覆盖)",{n:Object.keys(t.overrides).length}):r("(全部为默认值)"))}),s.jsx("div",{className:"hint retention-note",children:Un.clineHeaders})]})})}function fee({snap:e}){const[t,a]=x.useState(!1);async function o(){a(!0),await NJ()||a(!1)}return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("网关跨域访问(CORS)"),tip:Wn.cors,badge:e.cors.status==="ready"?e.cors.on?s.jsx(Jt,{tone:"bad",children:r("已开启")}):s.jsx(Jt,{tone:"ok",children:r("已关闭")}):e.cors.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(kr,{id:"btn-cors-refresh",onClick:()=>{IJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-cors",label:r("允许浏览器里的页面跨来源调用网关(/v1/*)"),checked:e.cors.on,disabled:e.cors.status!=="ready"||e.busy==="cors",onCheckedChange:c=>{rJ(c)}})}),s.jsx("div",{className:"settings-state",children:e.cors.status==="loading"?kt.appLoading:e.cors.status==="unavailable"?kt.corsUnavailable:e.cors.on?kt.corsOn:kt.corsOff}),s.jsx("div",{className:"hint retention-note",children:Un.cors})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("机器人校验")}),s.jsxs("div",{className:"panel-body",children:[s.jsx(Ur,{id:"settings-captcha",label:r("登录 / 注册需要通过 ALTCHA 人机验证(工作量证明)"),checked:e.captcha.enabled,disabled:!e.captcha.available||e.busy==="captcha",onCheckedChange:c=>{aJ(c)}}),s.jsx("div",{className:"hint",children:Un.captcha})]})]}),e.panelLogin?s.jsxs("section",{className:"panel",id:"panel-login-section",children:[s.jsx(Gn,{title:r("面板登录")}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"hint",children:Un.panelLogin}),s.jsx("div",{className:"mt-2.5",children:s.jsx(ne,{id:"btn-panel-logout",variant:"outline",disabled:t,onClick:()=>{o()},children:r("退出登录")})})]})]}):null]})}function Lp({label:e,value:t}){return s.jsxs("div",{className:"storage-count",children:[s.jsx("span",{className:"k",children:e}),s.jsx("span",{className:"v",children:t})]})}function pee(e){return e.status==="loading"?s.jsx(Jt,{tone:"idle",children:r("检测中…")}):e.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:e.available?"ok":"bad",children:e.available?r("已生效"):r("数据库不可用")})}function mee({snap:e}){const t=e.busy,a=e.storage,o=tt().workbuddyDesktop?.platform==="web",c=a.status==="ready",d=c&&a.available,f=c&&a.file?a.file:"—",p=h=>d&&h!==null?yW(h):"—";return s.jsxs(s.Fragment,{children:[!o&&s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("整库备份 / 恢复"),tip:Wn.backup,actions:s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:"btn-settings-db-export",variant:"outline",disabled:t==="dbExport"||t==="dbImport",onClick:()=>{PW()},children:r(t==="dbExport"?"备份中…":"备份整库")}),s.jsx(ne,{id:"btn-settings-db-restore",variant:"destructive",disabled:t==="dbExport"||t==="dbImport",onClick:()=>_W(),children:r(t==="dbImport"?"恢复中…":"恢复整库")})]})}),s.jsxs("div",{className:"panel-body",children:[e.dbWarning?s.jsxs("div",{className:"danger-zone",id:"settings-db-warning",children:[s.jsx("strong",{children:r("⚠️ 密钥警告")}),s.jsx("br",{}),e.dbWarning]}):null,s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-db-include-logs",children:r("包含日志与调试报文")}),s.jsx(ns,{id:"settings-db-include-logs",checked:e.dbIncludeLogs,disabled:t!==null,onCheckedChange:IW}),s.jsx("div",{className:"hint",children:r("取消勾选后只备份业务数据(账号、配置与余额记录),文件显著变小;事件日志、请求统计与调试报文不会进备份文件。")})]}),s.jsx("div",{className:"danger-zone",children:s.jsx("strong",{children:Un.backupDanger})})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("账号导入 / 导出"),tip:Wn.io,actions:s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:"btn-settings-export",variant:"outline",disabled:t==="export",onClick:()=>{MW()},children:r(t==="export"?"导出中…":"导出账号")}),s.jsx(ne,{id:"btn-settings-import",variant:"default",disabled:t==="import",onClick:()=>{DW()},children:r(t==="import"?"导入中…":"导入账号")})]})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"danger-zone",children:[s.jsx("strong",{children:r("导出文件内含 accessToken / refreshToken / apiKey 等凭证与自定义提供商定义")}),r(",可直接用于登录。请妥善保管,不要外传或上传到公共位置。")]}),e.ioFailure?s.jsx("div",{className:"io-result",children:s.jsxs("span",{className:"text-destructive",children:[r("失败 {n} 个:{detail}",{n:e.ioFailure.failed,detail:e.ioFailure.detail}),e.ioFailure.more?r(" 等"):""]})}):null]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("数据保留"),tip:Wn.retention,badge:_p(e.retention),actions:s.jsx(kr,{id:"btn-retention-refresh",onClick:()=>{kJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:pS.map(h=>s.jsx(Pp,{field:h,value:e.retention.values?.[h.key]??null,disabled:e.busy==="retention",onCommit:b=>HW(h,b)},h.key))}),s.jsx("div",{className:"hint retention-note",children:Un.retention})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("数据存储"),tip:Wn.storage,badge:pee(a),actions:s.jsx(kr,{id:"btn-storage-refresh",onClick:()=>{_J()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"storage-db-path",children:r("数据库文件")}),s.jsx("span",{className:"storage-line",children:s.jsx("span",{className:"storage-path",id:"storage-db-path",title:f,children:f})}),s.jsx("div",{className:"hint",children:Un.storageFile})]}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"storage-db-size",children:r("占用大小")}),s.jsx("span",{className:"storage-line",children:s.jsx("span",{className:"storage-path",id:"storage-db-size",children:d?KI(a.bytes):"—"})}),s.jsx("div",{className:"hint",children:Un.storageSize})]})]}),s.jsxs("div",{className:"retention-list storage-counts",children:[s.jsx(Lp,{label:r("账号"),value:p(a.accounts)}),s.jsx(Lp,{label:r("事件日志"),value:p(a.logs)}),s.jsx(Lp,{label:r("请求记录"),value:p(a.requests)}),s.jsx(Lp,{label:r("报表天数"),value:p(a.dailyDays)}),s.jsx(Lp,{label:r("调试报文"),value:p(a.debug)})]}),s.jsx("div",{className:"hint retention-note",children:Un.storage})]})]})]})}const hee=[{title:r("问题反馈"),desc:r("遇到 Bug、报错或异常行为"),cta:r("去反馈"),url:"https://github.com/aimod-cc/agent2api/issues/new?template=bug_report.yml"},{title:r("功能建议"),desc:r("想要的新功能或改进想法"),cta:r("提建议"),url:"https://github.com/aimod-cc/agent2api/issues/new?template=feature_request.yml"},{title:r("请求提供商 / 模型支持"),desc:r("希望接入新的提供商或模型"),cta:r("去申请"),url:"https://github.com/aimod-cc/agent2api/issues/new?template=provider_request.yml"}];function gee(){return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("反馈与需求")}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"hint",children:r("点下面的入口会用系统默认浏览器打开 GitHub 的对应表单(需要 GitHub 账号,模板已预设好,填完直接提交即可)。")}),s.jsx("div",{className:"mt-3 flex flex-col gap-2",children:hee.map(e=>s.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-md border border-hairline bg-surface-2 px-3 py-2.5",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsx("div",{className:"text-[12.5px] text-foreground",children:e.title}),s.jsx("div",{className:"mt-0.5 text-[12px] text-subtle",children:e.desc})]}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>{fW(e.url)},children:e.cta})]},e.url))})]})]})}function xee({confirm:e}){const t=x.useRef(null);return s.jsx(Yt,{open:e!==null,onOpenChange:a=>{a||Vx(!1)},children:s.jsxs(Xt,{className:"w-[min(440px,calc(100vw-48px))]",initialFocus:t,children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("确认缩短保留天数")})}),s.jsx(Lt,{children:s.jsxs("div",{className:"danger-zone",children:[e?.head,s.jsx("br",{}),s.jsx("strong",{children:r("超出的历史数据会被立即删除,且不可恢复。")}),r("确定继续?")]})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:t,variant:"outline",onClick:()=>Vx(!1),children:r("取消")}),s.jsx(ne,{variant:"destructive",onClick:()=>Vx(!0),children:r("继续并清理")})]})]})})}const LS={enable:{title:r("开启局域网访问"),body:()=>s.jsxs(s.Fragment,{children:[r("为了安全,开启前需要先注册一个"),s.jsx("b",{children:r("面板管理员账号")}),r("(已注册过会跳过这一步,直接生效)。"),s.jsx("br",{}),r("开启后网关将监听所有网卡,同一局域网内的设备即可把 API 地址指向本机 IP 一起使用;管理接口从此要求管理员会话或网关 Key,转发接口在没有一把启用的 Key 时也会拒绝服务(届时会自动创建一把名为「默认」的 Key)。"),s.jsx("br",{}),s.jsx("strong",{children:r("保存后应用将重启以生效。")}),r("确定继续?")]}),label:r("继续")},disable:{title:r("关闭局域网访问"),body:()=>s.jsxs(s.Fragment,{children:[r("关闭后网关回到只监听 127.0.0.1,局域网内的设备将无法继续访问;已配置的网关 Key 与账号都不受影响。"),s.jsx("br",{}),s.jsx("strong",{children:r("保存后应用将重启以生效。")}),r("确定继续?")]}),label:r("关闭并重启")},panel:{title:r("变更网页管理面板"),body:e=>e?s.jsxs(s.Fragment,{children:[r("开放后,局域网内其他设备的浏览器打开本机 IP 即可进入管理面板(需管理员账号登录)。"),s.jsx("br",{}),s.jsx("strong",{children:r("保存后应用将重启以生效。")}),r("确定继续?")]}):s.jsxs(s.Fragment,{children:[r("关闭后,管理界面不再从局域网提供,只有本机的桌面程序可以管理;已开启的 API 转发不受影响。"),s.jsx("br",{}),s.jsx("strong",{children:r("保存后应用将重启以生效。")}),r("确定继续?")]}),label:r("保存并重启")}};function bee({confirm:e}){const t=x.useRef(null);return s.jsx(Yt,{open:e!==null,onOpenChange:a=>{a||jS(!1)},children:s.jsxs(Xt,{className:"w-[min(440px,calc(100vw-48px))]",initialFocus:t,children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("恢复整库备份")})}),s.jsx(Lt,{children:s.jsxs("div",{className:"danger-zone",children:[r("本机的全部数据(账号、网关配置、日志统计与桌面设置)将被所选备份文件"),s.jsx("strong",{children:r("整体替换")}),r(",包括恢复后需要重新登录管理面板。"),s.jsx("br",{}),s.jsx("strong",{children:r("替换前会自动把当前数据备份到配置目录的 backups/ 文件夹。")}),r("确定继续?")]})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:t,variant:"outline",onClick:()=>jS(!1),children:r("取消")}),s.jsx(ne,{variant:"destructive",onClick:()=>jS(!0),children:r("选择备份文件并恢复")})]})]})})}function vee({confirm:e,register:t}){const a=x.useRef(null),o=x.useRef(null),c=x.useRef(null),d=e!==null||t!==null,f=()=>{t!==null?JI():yS(!1)},p=()=>{OW(o.current?.value??"",c.current?.value??"")};return s.jsx(Yt,{open:d,onOpenChange:h=>{h||f()},children:s.jsx(Xt,{className:"w-[min(480px,calc(100vw-48px))]",initialFocus:a,children:t!==null?s.jsxs(s.Fragment,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("注册管理员账号")})}),s.jsxs(Lt,{children:[s.jsx("div",{children:r("局域网开放后,管理接口要求登录。请设置管理员账号与密码,注册完成会直接继续开启流程。")}),s.jsxs("form",{onSubmit:h=>{h.preventDefault(),t.busy||p()},children:[s.jsx(Je,{htmlFor:"lan-admin-name",className:"mt-3.5 mb-[5px] block text-[12.5px]",children:r("账号")}),s.jsx(Fe,{ref:o,id:"lan-admin-name",autoComplete:"username",placeholder:r("管理员账号"),disabled:t.busy}),s.jsx(Je,{htmlFor:"lan-admin-password",className:"mt-3.5 mb-[5px] block text-[12.5px]",children:r("密码")}),s.jsx(Fe,{ref:c,id:"lan-admin-password",type:"password",autoComplete:"new-password",placeholder:r("至少 8 位"),disabled:t.busy})]}),s.jsx("div",{className:"mt-3 min-h-5 text-[13px] whitespace-pre-wrap text-destructive",children:t.error})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:a,variant:"outline",onClick:JI,disabled:t.busy,children:r("取消")}),s.jsx(ne,{onClick:p,disabled:t.busy,children:t.busy?r("正在注册…"):r("注册并开启")})]})]}):s.jsxs(s.Fragment,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:e?LS[e.mode].title:""})}),s.jsx(Lt,{children:s.jsx("div",{children:e?LS[e.mode].body(e.panel):null})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:a,variant:"outline",onClick:()=>yS(!1),children:r("取消")}),s.jsx(ne,{onClick:()=>yS(!0),children:e?LS[e.mode].label:r("继续")})]})]})})})}function yee(){const e=NW(),t=x.useRef(null);x.useEffect(()=>{const o=t.current;o&&(o.scrollTop=0)},[e.scrollReset]);const a=o=>e.category===o?"settings-pane active":"settings-pane";return s.jsxs("div",{className:"settings-layout",children:[s.jsx("nav",{className:"settings-nav",id:"settings-nav",children:Ix.map(o=>s.jsxs("button",{type:"button",className:e.category===o.id?"settings-nav-item active":"settings-nav-item","data-cat":o.id,onClick:()=>kW(o.id),children:[s.jsx("span",{className:"ico",dangerouslySetInnerHTML:{__html:mP(o.icon,17)}}),o.label]},o.id))}),s.jsxs("div",{className:"settings-panes",ref:t,children:[s.jsx("div",{className:a("general"),"data-cat":"general",children:s.jsx(qJ,{snap:e})}),s.jsx("div",{className:a("assistant"),"data-cat":"assistant",children:s.jsx(U7,{})}),s.jsx("div",{className:a("display"),"data-cat":"display",children:s.jsx(KJ,{})}),s.jsx("div",{className:a("gateway"),"data-cat":"gateway",children:s.jsx(cee,{snap:e})}),s.jsx("div",{className:a("routing"),"data-cat":"routing",children:s.jsx(iee,{snap:e})}),s.jsx("div",{className:a("retry"),"data-cat":"retry",children:s.jsx(lee,{snap:e})}),s.jsx("div",{className:a("timeout"),"data-cat":"timeout",children:s.jsx(aee,{snap:e})}),s.jsx("div",{className:a("security"),"data-cat":"security",children:s.jsx(fee,{snap:e})}),s.jsx("div",{className:a("data"),"data-cat":"data",children:s.jsx(mee,{snap:e})}),s.jsx("div",{className:a("feedback"),"data-cat":"feedback",children:s.jsx(gee,{})}),s.jsx("div",{className:a("about"),"data-cat":"about"})]}),s.jsx(xee,{confirm:e.retentionConfirm}),s.jsx(bee,{confirm:e.dbBackupConfirm}),s.jsx(vee,{confirm:e.lanConfirm,register:e.lanRegister})]})}const xP='.page[data-page="settings"]';let zS=null;function bP(){if(zS)return;const e=document.querySelector(xP);e&&(e.replaceChildren(),zS=jn.createRoot(e),Ts.flushSync(()=>{zS?.render(s.jsx(yee,{}))}))}QI(),document.querySelector(xP)?bP():document.addEventListener("DOMContentLoaded",bP,{once:!0}),window.wbSettingsPanel={load:_S,render:bS,renderRetention:Bx,renderRetry:YW,renderDebug:qx,renderSanitize:Gx,renderPrompt:td,renderStorage:PS,showCategory:xS},tt().wbApp?.currentPage==="settings"&&_S();const vP="agent2api-col-config:",BS=[{value:"left",label:r("左")},{value:"center",label:r("中")},{value:"right",label:r("右")}],jee=e=>BS.some(t=>t.value===e),wee=BS.map(e=>`ta-${e.value}`),yP="colset-dragging",jP="open";let HS=null;const wP="grid grid-cols-[18px_minmax(78px,1fr)_44px_minmax(106px,auto)] items-center gap-2";function SP(){return window}const Xx=new Map;function US(e){return e.columns.map(t=>({key:t.key,visible:t.visible!==!1,align:t.align||"left"}))}function See(e,t){const a=Array.isArray(t),o=!a&&t&&typeof t=="object"?t:null,c=a?t:Array.isArray(o?.items)?o.items:[],d=o?.defaults&&typeof o.defaults=="object"?o.defaults:null,f=new Map(e.columns.map(y=>[y.key,y])),p=new Map(US(e).map(y=>[y.key,y])),h=[],b=new Set;for(const y of c){const v=y&&typeof y=="object"?y:{},j=String(v.key||"");if(!f.has(j)||b.has(j))continue;b.add(j);const w=f.get(j),S=w.align||"left",N=d?d[j]??S:w.legacyAlign??S,k=jee(v.align)?v.align:null;h.push({key:j,visible:v.visible!==!1,align:k&&k!==N?k:S})}for(const y of e.columns)b.has(y.key)||Nee(h,e,{...p.get(y.key)});return h}function Nee(e,t,a){const o=t.columns.findIndex(c=>c.key===a.key);for(let c=o-1;c>=0;c-=1){const d=e.findIndex(f=>f.key===t.columns[c].key);if(d>=0){e.splice(d+1,0,a);return}}e.unshift(a)}function kee(e){try{const t=localStorage.getItem(vP+e.id);return See(e,t?JSON.parse(t):[])}catch{return US(e)}}function Cee(e){try{const t={};for(const a of e.columns)t[a.key]=a.align||"left";localStorage.setItem(vP+e.id,JSON.stringify({v:2,defaults:t,items:e.config}))}catch{}}const Tee=e=>Xx.get(e)?.config||null,Eee=(e,t)=>e.columns.find(a=>a.key===t)?.label||t;function NP(e,t){const a=Xx.get(e);if(!a)return t;const o=new Map(t.map(c=>[c.key,c]));return a.config.filter(c=>c.visible&&o.has(c.key)).map(c=>({...o.get(c.key),align:c.align}))}function zp(e,{silent:t=!1}={}){Cee(e),t||e.onChange?.(e.config),_l&&_l.id===e.id&&_l.repaint()}let _l=null;function Qx(){if(!_l)return;const e=_l;_l=null,e.destroy()}function Aee(e,t){Qx();const a=document.createElement("div");document.body.append(a);const o=jn.createRoot(a),c={current:null};_l={id:e.id,spec:e,repaint:()=>c.current?.(),destroy:()=>{o.unmount(),a.remove()}},o.render(s.jsx(Iee,{spec:e,anchor:t,repaintRef:c,onClose:Qx}))}function Ree(e,t){_l&&_l.id===e.id?Qx():Aee(e,t)}function Oee(e,t,a){const o=[...e],[c]=o.splice(t,1);return o.splice(a,0,c),o}function Mee(e,t,a,o){const c=document.elementFromPoint(e,t)?.closest?.("[data-col-key]");if(!c||!a||!a.contains(c))return"";const d=c.getAttribute("data-col-key")||"";return o.some(f=>f.key===d)?d:""}const Dee=s.jsxs("svg",{viewBox:"0 0 24 24",width:13,height:13,fill:"currentColor","aria-hidden":"true",className:"block",children:[s.jsx("circle",{cx:"9",cy:"6",r:"1.6"}),s.jsx("circle",{cx:"15",cy:"6",r:"1.6"}),s.jsx("circle",{cx:"9",cy:"12",r:"1.6"}),s.jsx("circle",{cx:"15",cy:"12",r:"1.6"}),s.jsx("circle",{cx:"9",cy:"18",r:"1.6"}),s.jsx("circle",{cx:"15",cy:"18",r:"1.6"})]});function Iee({spec:e,anchor:t,repaintRef:a,onClose:o}){const c=t,d=x.useRef(null),[f,p]=x.useState(null),h=x.useRef(null),[,b]=x.useState(0),y=x.useCallback(()=>b(N=>N+1),[]);x.useLayoutEffect(()=>(a.current=y,()=>{a.current=null}),[y,a]),x.useEffect(()=>(c.classList.add(jP),c.setAttribute("aria-expanded","true"),()=>{c.classList.remove(jP),c.setAttribute("aria-expanded","false")}),[c]),x.useEffect(()=>{const N=()=>{const k=c.getBoundingClientRect();(!c.isConnected||!k.width||k.bottom<=0||k.top>=window.innerHeight)&&o()};return window.addEventListener("scroll",N,!0),window.addEventListener("resize",N),()=>{window.removeEventListener("scroll",N,!0),window.removeEventListener("resize",N)}},[c,o]),x.useEffect(()=>()=>{const N=h.current;N&&(N.teardown(),zp(e))},[e]);function v(N,k){const A=e.config.find(P=>P.key===N);A&&(!k&&e.config.filter(P=>P.visible).length<=1||(A.visible=k,zp(e)))}function j(N,k){const A=e.config.find(P=>P.key===N);!A||A.align===k||(A.align=k,zp(e))}function w(){e.config=US(e),zp(e)}function S(N,k){k.preventDefault(),h.current?.teardown(),p(N),document.body.classList.add(yP);const A=d.current;function P(){window.removeEventListener("pointermove",R),window.removeEventListener("pointerup",C),document.body.classList.remove(yP),h.current=null,p(null)}function R(E){const D=Mee(E.clientX,E.clientY,A,e.config);if(!D||D===N)return;const I=e.config.findIndex(_=>_.key===N),O=e.config.findIndex(_=>_.key===D);I<0||O<0||(e.config=Oee(e.config,I,O),y())}function C(){P(),zp(e)}h.current={teardown:P},window.addEventListener("pointermove",R),window.addEventListener("pointerup",C)}return s.jsx(wf,{open:!0,modal:!1,onOpenChange:(N,k)=>{N||(k?.reason==="outside-press"&&(HS=k.event??null),o())},children:s.jsxs(Sf,{anchor:c,side:"bottom",align:"end",sideOffset:6,collisionPadding:8,className:"w-[336px]","aria-label":r("{name}的列设置",{name:e.label||e.id}),children:[s.jsxs("div",{className:Ue(wP,"border-b border-hairline px-3 pt-[9px] pb-[7px]","text-[10.5px] font-semibold tracking-[.05em] text-muted-foreground"),children:[s.jsx("span",{}),s.jsx("span",{className:"text-center",children:r("列")}),s.jsx("span",{className:"text-center",children:r("显示")}),s.jsx("span",{className:"text-center",children:r("对齐")})]}),s.jsx("div",{ref:d,className:"min-h-0 flex-1 overflow-y-auto px-3 py-1",children:e.config.map(N=>{const k=Eee(e,N.key),A=f===N.key;return s.jsxs("div",{"data-col-key":N.key,className:Ue(wP,"rounded-sm py-[5px] hover:bg-nav-hover",A&&"opacity-50"),children:[s.jsx("span",{className:"flex cursor-grab items-center justify-center text-muted-foreground opacity-50 hover:opacity-100",title:r("按住拖动调整列顺序"),onPointerDown:P=>S(N.key,P),children:Dee}),s.jsx("span",{className:"min-w-0 truncate text-xs text-foreground",title:k,children:k}),s.jsx(ns,{className:"justify-self-center",checked:N.visible,onCheckedChange:P=>v(N.key,P),"aria-label":r("显示「{label}」列",{label:k}),title:N.visible?r("这一列正在显示"):r("这一列已隐藏")}),s.jsx(En,{className:"w-full justify-center",options:BS,value:N.align,onValueChange:P=>j(N.key,P),"aria-label":r("「{label}」列的对齐",{label:k})})]},N.key)})}),s.jsxs("div",{className:"flex items-center gap-2 border-t border-hairline px-3 pt-2 pb-[9px]",children:[s.jsx("span",{className:"flex-1 text-[11px] text-muted-foreground",children:r("拖动 ⋮⋮ 调整顺序")}),s.jsx(ne,{variant:"outline",size:"sm",onClick:w,children:r("恢复默认")})]})]})})}function Pee(e,t){e&&(e.classList.remove(...wee),e.classList.add(`ta-${t}`))}const kP=new Map;function _ee(e,t){const a=kP.get(e);if(a&&a.table===t&&a.row.isConnected)return a;const o=t?.querySelector("thead tr");if(!o)return null;const c=t?.querySelector("colgroup")??null,d={table:t,row:o,group:c,ths:new Map([...o.querySelectorAll("th[data-col]")].map(f=>[f.getAttribute("data-col")||"",f])),cols:new Map([...c?.querySelectorAll("col[data-col]")||[]].map(f=>[f.getAttribute("data-col")||"",f]))};return kP.set(e,d),d}function Lee(e,t,a){const o=Xx.get(e);if(!o||!t)return;const c=_ee(e,t);if(!c)return;const{row:d,group:f,ths:p,cols:h}=c;for(const b of o.config){const y=p.get(b.key);if(!y)continue;const v=h.get(b.key);if(!b.visible||a?.has(b.key)){y.remove(),v?.remove();continue}Pee(y,b.align),d.appendChild(y),v&&f&&f.appendChild(v)}SP().wbTableColumns?.repaint?.(e)}function zee(e){const t=document.createElement("button");return t.type="button",t.className=`sm colset-btn${e.buttonClass?` ${e.buttonClass}`:""}`,t.id=`btn-colset-${e.id}`,t.title=r("调整「{name}」的列:显示 / 隐藏、顺序、对齐",{name:e.label||e.id}),t.innerHTML=`${SP().wbIcons?.icon?.("settings",14)||""}${r("列设置")}`,t.setAttribute("aria-haspopup","dialog"),t.setAttribute("aria-expanded","false"),t.addEventListener("click",a=>{if(HS===a){HS=null;return}Ree(e,t)}),t}function Bee(e){return(typeof e.mount=="function"?e.mount():e.mount?document.querySelector(e.mount):null)||null}function Hee(e){const t={...e,config:kee(e)};Xx.set(e.id,t);const a=Bee(e),o=zee(t);return a&&(e.buttonPlacement==="last"?a.appendChild(o):a.insertBefore(o,a.firstChild)),{apply:c=>NP(e.id,c),config:()=>t.config}}window.wbColSettings={register:Hee,apply:NP,configOf:Tee,syncStaticHead:Lee,close:Qx};function rl(){return window}const Uee=new Set(["updateCheck"]);function CP(e){return(Array.isArray(e?.tasks)?e.tasks:[]).filter(a=>!Uee.has(a.id))}const Vee=2e4,TP=1,Fee=" · ";function nd(e,t){rl().wbApp?.toast?.(e,t)}function Zx(e){return e instanceof Error?e.message:String(e)}function EP(e){return r(e==="seconds"?"秒":"分钟")}function AP(e){const t=Number(e)||0;return t?new Date(t).toLocaleTimeString("zh-CN",{hour12:!1}):""}function RP(e){const t=Number(e)||0;if(!t)return"";const a=t-Date.now();if(a<=0)return r("即将执行");const o=Math.round(a/1e3);if(o<60)return r("{n} 秒后",{n:o});const c=Math.round(o/60);if(c<60)return r("{n} 分钟后",{n:c});const d=Math.round(c/60);return d<24?r("{n} 小时后",{n:d}):r("{n} 天后",{n:Math.round(d/24)})}function $ee(e){const t=e.runner==="backend",a=[];if(e.lastRunAt){const o=AP(e.lastRunAt);a.push(e.lastResult?r("上次执行 {time}({result})",{time:o,result:e.lastResult}):r("上次执行 {time}",{time:o}))}else a.push(r(t?"还没有执行记录":"由页面按间隔自动刷新"));return t&&e.enabled&&e.nextRunAt&&a.push(r("下次执行 {time}({relative})",{time:AP(e.nextRunAt),relative:RP(e.nextRunAt)})),t&&e.retryAt&&e.retryAt>Date.now()&&a.push(r("冷却中,{relative}重试",{relative:RP(e.retryAt)})),a.join(Fee)}function qee(e,t){const a=String(t??"").trim(),o=EP(e.unit);if(!a)return{ok:!1,message:r("间隔不能为空(可填 {min}–{max} {unit})",{min:e.min,max:e.max,unit:o})};if(!/^\d+$/.test(a))return{ok:!1,message:r("间隔必须是整数")};const c=Number(a);return ce.max?{ok:!1,message:r("间隔必须在 {min}–{max} {unit} 之间(当前填的是 {value})",{min:e.min,max:e.max,unit:o,value:a})}:{ok:!0,value:c}}function Gee(e){const t=rl();e.id==="logsAutoRefresh"?t.wbLogsPanel?.applyAutoRefresh?.(e):e.id==="requestsAutoRefresh"?t.wbRequestsPanel?.applyAutoRefresh?.(e):e.id==="reportAutoRefresh"&&t.wbReport?.applyAutoRefresh?.(e)}let pc=!1,Wx=null,VS=!1;async function OP(){if(!Wx){VS=!0;return}await Wx()}function Kee(){const[e,t]=x.useState([]),[a,o]=x.useState(!1),[c,d]=x.useState(null),[f,p]=x.useState({});function h(D){p(I=>{if(!(D in I))return I;const O={...I};return delete O[D],O})}const b=x.useCallback(async()=>{const D=rl().workbuddyDesktop;try{if(!D)throw new Error(r("后端桥不可用"));const I=await D.getScheduledTasks();t(CP(I)),o(!0)}catch(I){console.warn("读取定时任务失败:",Zx(I)),t([]),o(!0)}},[]),y=x.useCallback(async()=>{if(pc||document.hidden||rl().wbApp?.currentPage!=="tasks")return;const D=rl().workbuddyDesktop;if(D)try{const I=await D.getScheduledTasks();t(CP(I))}catch(I){console.warn("同步定时任务状态失败:",Zx(I))}},[]);x.useEffect(()=>{const D=window.setInterval(()=>{y()},Vee);return()=>{window.clearInterval(D)}},[y]),x.useEffect(()=>{rl().wbApp?.renderTopbarStatus?.()},[e,a]),x.useEffect(()=>(Wx=b,VS&&(VS=!1,b()),()=>{Wx=null}),[b]);async function v(D,I,O){if(pc)return;const _=rl().workbuddyDesktop;if(_){pc=!0;try{const z=await _.saveScheduledTask(D,I);t(H=>H.map(B=>B.id===D?z:B)),Gee(z),nd(r("✅ 已更新「{label}」",{label:O}))}catch(z){nd(r("保存失败:{reason}",{reason:Zx(z)}),"err"),await b()}finally{pc=!1}}}async function j(D,I){const O=qee(D,I);if(!O.ok){nd(O.message,"err"),h(D.id);return}if(O.value===D.interval){h(D.id);return}await v(D.id,{interval:O.value},r("{name}间隔",{name:r(D.label)})),h(D.id)}async function w(D){if(pc)return;const I=rl().workbuddyDesktop;if(I){pc=!0,d(D.id);try{const O=await I.runScheduledTask(D.id);if(O?.task){const _=O.task;t(z=>z.map(H=>H.id===D.id?_:H))}nd(r("✅ {task}:{summary}",{task:r(D.label),summary:O?.summary||r("已执行")})),D.id==="credentialMaintenance"&&await rl().wbApp?.refresh?.()}catch(O){nd(r("执行失败:{reason}",{reason:Zx(O)}),"err"),await b()}finally{pc=!1,d(null)}}}function S(D){const I=EP(D.unit),O=c===D.id;return s.jsxs("div",{className:"task-item","data-task":D.id,children:[s.jsxs("div",{className:"task-main",children:[s.jsxs("div",{className:"task-title",children:[s.jsxs("label",{className:"switch",children:[s.jsx(ns,{checked:D.enabled===!0,onCheckedChange:_=>{v(D.id,{enabled:_},r("{name}开关",{name:r(D.label)}))}}),s.jsx("span",{className:"task-name",children:r(D.label)})]}),s.jsx("span",{className:"tip-q","data-tip":r(D.description)}),s.jsx(ze,{className:"task-badge",variant:D.enabled?"success":"outline",children:D.enabled?r("已开启"):r("已关闭")}),D.running?s.jsx(ze,{className:"task-badge",variant:"warning",children:r("执行中…")}):null]}),s.jsx("div",{className:"task-state",children:$ee(D)})]}),s.jsxs("div",{className:"task-actions",children:[s.jsxs("span",{className:"task-interval",children:[s.jsx("span",{className:"task-interval-label",children:r("每")}),s.jsx(Fe,{type:"number",inputMode:"numeric",min:D.min,max:D.max,step:1,className:"w-[74px] max-w-[74px] text-center tabular-nums",value:f[D.id]??String(D.interval),title:r("可填 {min}–{max} {unit}(默认 {def} {unit})",{min:D.min,max:D.max,unit:I,def:D.defaultInterval}),onChange:_=>{const z=_.currentTarget.value;p(H=>({...H,[D.id]:z}))},onBlur:_=>{j(D,_.currentTarget.value)},onKeyDown:_=>{_.key==="Enter"&&_.currentTarget.blur()}}),s.jsx("span",{className:"task-interval-unit",children:I})]}),D.canRun===!0?s.jsx(ne,{size:"sm",variant:"outline",disabled:O||D.running===!0,onClick:()=>{w(D)},children:r(O?"执行中…":"立即执行")}):null]})]},D.id)}const N=e.length===0,k=e.filter(D=>D.enabled).length,A=N?a?r("不可用"):"—":r("{enabled} / {total} 个已开启",{enabled:k,total:e.length}),P=N?a?"destructive":"outline":k?"success":"outline",R=P==="destructive"?"bad":P==="success"?"ok":"",C=e.map(D=>S(D)),E=C.slice(TP);return s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("任务清单")}),s.jsx(ze,{id:"tasks-badge",variant:P,"data-tone":R,children:A}),s.jsx("span",{className:"panel-sub",children:r("状态每 20 秒自动同步")}),s.jsx("div",{className:"head-actions",children:s.jsx(ne,{variant:"outline",onClick:()=>{b().then(()=>nd(r("定时任务已刷新")))},children:r("刷新")})})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"task-list",children:N?s.jsx("div",{className:"log-empty",children:r(a?"没有可显示的定时任务。后端未返回任务清单,请确认网关正在运行。":"正在加载定时任务…")}):s.jsxs(s.Fragment,{children:[C.slice(0,TP),E.length?s.jsx("div",{className:"task-grid",children:E}):null]})})}),s.jsxs("div",{className:"panel-foot",children:[s.jsxs("span",{children:[r("任务配置保存在 "),s.jsx("code",{children:"~/.agent2api/config.json"}),r(" 的 "),s.jsx("code",{children:"scheduledTasks"}),r(" 字段")]}),s.jsx("span",{children:r("改动立即生效,不需要重启程序")})]})]})}const MP='.page[data-page="tasks"]';let DP=!1;function IP(){if(DP)return;const e=document.querySelector(MP);e&&(DP=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(Kee,{})))}document.querySelector(MP)?IP():document.addEventListener("DOMContentLoaded",IP,{once:!0}),window.wbTasksPanel={load:OP},rl().wbApp?.currentPage==="tasks"&&OP();const PP="workbuddy-desktop-update-skip";function Yee(){try{return localStorage.getItem(PP)||""}catch{return""}}function Xee(e){try{localStorage.setItem(PP,e)}catch{}}let _P="";function Jx(e,t){if(!e||e.hasUpdate!==!0||e.pendingRestart===!0)return;const a=String(e.latestVersion||"").trim();a&&nn().wbApp?.currentPage!=="settings"&&(a===Yee()||a===_P||(_P=a,LP(),sd=document.createElement("div"),document.body.append(sd),Bp=jn.createRoot(sd),Bp.render(s.jsx(Qee,{info:e,onGoUpdate:t,onClose:LP}))))}function Qee({info:e,onGoUpdate:t,onClose:a}){const o=String(e.latestVersion||""),c=String(e.notes||"").trim(),d=c?dD(c):"";function f(){Xee(o),a()}function p(){a();const h=nn();h.wbApp?.showPage?.("settings"),h.wbSettingsPanel?.showCategory?.("about"),t(e)}return s.jsx(Yt,{open:!0,onOpenChange:h=>{h||a()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("检测到更新")})}),s.jsxs(Lt,{children:[s.jsxs("p",{className:"text-[12.5px] leading-[1.6] text-subtle",children:[r("新版本 "),s.jsx("strong",{className:"text-foreground",children:o}),r(" 已发布(当前 {current}),更新日志如下:",{current:e.currentVersion||r("未知")})]}),s.jsx("div",{className:"max-h-[46vh] overflow-y-auto overscroll-contain pr-1.5",onClick:Xu,children:d?s.jsx("div",{className:"md-body",dangerouslySetInnerHTML:{__html:d}}):s.jsx("div",{className:"md-body",children:s.jsx("p",{className:"md-body-empty",children:r("这个版本没有填写发布说明。")})})})]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",size:"sm",onClick:f,children:r("跳过此次更新")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:a,children:r("取消")}),s.jsx(ne,{variant:"default",onClick:p,children:r("去更新")})]})]})})}let Bp=null,sd=null;function LP(){Bp&&(Bp.unmount(),Bp=null),sd&&(sd.remove(),sd=null)}const zP="updateCheck",rd=1,eb=1440,Zee="https://github.com/settings/tokens/new?description="+encodeURIComponent("Agent2API 更新检查");function Wee(e){return e?e.error?{badge:s.jsx(ze,{shape:"tag",variant:"destructive",title:e.error,children:r("无法解密")}),hint:r("重新粘贴保存一次即可自愈")}:e.filled&&e.origin==="stored"?{badge:s.jsx(ze,{shape:"tag",variant:"success",children:r("已填写")}),hint:r("已加密存储在本地,不显示具体值;粘贴新令牌可覆盖")}:e.filled?{badge:s.jsx(ze,{shape:"tag",variant:"secondary",children:r("环境变量")}),hint:r("已配置 GITHUB_TOKEN 环境变量,界面保存的令牌优先于它")}:{badge:s.jsx(ze,{shape:"tag",variant:"outline",children:r("未填写")}),hint:r("填写后检查限额 60 → 5000 次/小时(创建令牌无需勾选任何权限)")}:{badge:s.jsx(ze,{shape:"tag",variant:"outline",children:r("读取中")}),hint:""}}function Jee({open:e,onClose:t}){const[a,o]=x.useState(fD),[c,d]=x.useState(null),[f,p]=x.useState(""),[h,b]=x.useState(!1),[y,v]=x.useState(null),[j,w]=x.useState(""),[S,N]=x.useState(!1),[k,A]=x.useState(null),[P,R]=x.useState(!1),C=pD(a);x.useEffect(()=>{e&&(p(""),wX().then(o),(async()=>{try{d(await nn().workbuddyDesktop?.getUpdateToken()??null)}catch{}})(),(async()=>{try{const F=await nn().workbuddyDesktop?.getUpdateBeta();A({enabled:F?.enabled===!0})}catch{}})(),(async()=>{try{const $=((await nn().workbuddyDesktop?.getScheduledTasks?.())?.tasks??[]).find(q=>q.id===zP),X=$?.enabled===!0,K=Math.max(rd,Math.round(Number($?.interval)||0));v({enabled:X,interval:K}),w(String(K))}catch{}})())},[e]);async function E(F){if(!S){N(!0);try{const $=await nn().workbuddyDesktop?.saveScheduledTask?.(zP,F),X=$?.enabled===!0,K=Math.max(rd,Math.round(Number($?.interval)||0));v({enabled:X,interval:K}),w(String(K)),Es(r("✅ 自动检查更新已保存"))}catch($){Es(r("保存失败:{error}",{error:pr($)}),"err")}finally{N(!1)}}}async function D(){const F=Math.round(Number(j));if(!Number.isFinite(F)||Feb){Es(r("检查间隔必须是 {min} ~ {max} 分钟",{min:rd,max:eb}),"err");return}y&&F===y.interval||await E({interval:F})}async function I(F){if(P)return;R(!0);let $=!1;try{const X=await nn().workbuddyDesktop?.setUpdateBeta({enabled:F});A({enabled:X?.enabled===!0}),$=!0,X?.saved===!1?Es(r("通道已切换,但写入磁盘失败(重启后会回到原设置)"),"err"):Es(r(F?"✅ 已加入 beta 版,之后的检查会包含 beta 版":"✅ 已退出 beta 版,之后的检查只看正式版"))}catch(X){Es(r("保存失败:{error}",{error:pr(X)}),"err")}finally{R(!1)}if($)try{await nn().workbuddyDesktop?.checkUpdate(),await jX()}catch{}}async function O(F){const $=await SX(F);$&&o(X=>({...X,proxyChoice:$.choice}))}async function _(){const F=f.trim();if(!F){Es(r("请先粘贴 GitHub 令牌"),"err");return}b(!0);try{const $=await nn().workbuddyDesktop?.setUpdateToken({token:F});d($??null),p(""),$?.saved===!1?Es(r("令牌已生效,但写入磁盘失败(重启后会丢失)"),"err"):Es(r("✅ GitHub 令牌已保存(加密存储,界面不再显示)"))}catch($){Es(r("保存失败:{error}",{error:pr($)}),"err")}finally{b(!1)}}async function z(){b(!0);try{const F=await nn().workbuddyDesktop?.setUpdateToken({token:null});d(F??null),Es(r("✅ 已清除界面保存的 GitHub 令牌(环境变量若配置过则继续生效)"))}catch(F){Es(r("清除失败:{error}",{error:pr(F)}),"err")}finally{b(!1)}}const H=Wee(c),B=!!c?.error||c?.origin==="stored",L=c?.filled&&c?.origin!=="env"?r("已填写(粘贴新令牌可覆盖)"):r("粘贴 GitHub 令牌(ghp_… / github_pat_…)");return s.jsx(Yt,{open:e,onOpenChange:F=>{F||t()},children:s.jsxs(Xt,{className:"w-[min(460px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("更新设置")})}),s.jsxs(Lt,{className:"gap-3.5",children:[s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center justify-between gap-2",children:[s.jsx("div",{className:"text-[13px] font-semibold text-foreground",children:r("自动检查更新")}),s.jsx(ns,{checked:y?.enabled===!0,disabled:S||!y,onCheckedChange:F=>{E({enabled:F===!0})},"aria-label":r("自动检查更新")})]}),s.jsxs("div",{className:"mt-1.5 flex items-center gap-2",children:[s.jsx(Fe,{type:"number",min:rd,max:eb,step:1,className:"w-[110px]",disabled:S||!y||y.enabled!==!0,value:j,onChange:F=>w(F.currentTarget.value),onKeyDown:F=>{F.key==="Enter"&&(F.preventDefault(),D())},"aria-label":r("检查间隔(分钟)")}),s.jsx("span",{className:"text-[12px] text-subtle",children:r("分钟({min} ~ {max})",{min:rd,max:eb})}),s.jsx(ne,{variant:"outline",size:"sm",disabled:S||!y||Math.round(Number(j))===y.interval,onClick:()=>{D()},children:r("保存")})]}),s.jsx("div",{className:"mt-1.5 text-[12px] text-subtle",children:r("到点自动向 GitHub 查询新版本,查到就走「检测到更新」弹窗;关闭后「检查更新」按钮仍可手动触发")})]}),s.jsx("div",{className:"h-px bg-hairline"}),s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center justify-between gap-2",children:[s.jsx("div",{className:"text-[13px] font-semibold text-foreground",children:r("加入 beta 版")}),s.jsx(ns,{checked:k?.enabled===!0,disabled:P||!k,onCheckedChange:F=>{I(F===!0)},"aria-label":r("加入 beta 版")})]}),s.jsx("div",{className:"mt-1.5 text-[12px] text-subtle",children:r("开启后只更新到 beta 版(预发布),取版本最高的一个;beta 版可能不稳定。开启期间不会因为正式版发布而自动切回正式版 —— 想切回请关闭本开关。关闭后只更新到正式版,且不会降级到版本号更低的版本。")})]}),s.jsx("div",{className:"h-px bg-hairline"}),s.jsxs("div",{children:[s.jsx("div",{className:"text-[13px] font-semibold text-foreground",children:r("出网代理")}),s.jsx("div",{className:"mt-1.5",children:s.jsxs(ut,{value:C.current,onValueChange:F=>{O(String(F))},children:[s.jsx(ft,{className:Ue("w-full",C.broken&&"border-destructive-bd"),title:C.title,"aria-label":r("更新出网代理"),children:s.jsx(dt,{className:"min-w-0 truncate",children:C.selected?.label||r("直连")})}),s.jsx(pt,{children:C.items.map(F=>s.jsx($e,{value:F.value,disabled:F.disabled,children:F.label},F.value))})]})})]}),s.jsx("div",{className:"h-px bg-hairline"}),s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center justify-between gap-2",children:[s.jsx("div",{className:"text-[13px] font-semibold text-foreground",children:r("GitHub 令牌")}),s.jsx(ne,{variant:"outline",size:"xs",title:r("在默认浏览器中打开 GitHub 的令牌创建页(备注已预设,无需勾选任何权限,直接点 Generate token)"),onClick:()=>{uD(Zee)},children:r("打开 GitHub 令牌页面")})]}),s.jsxs("div",{className:"mt-1.5 flex items-center gap-2",children:[H.badge,s.jsx("span",{className:"text-[12px] text-subtle",children:H.hint})]}),s.jsxs("div",{className:"mt-2 flex items-center gap-2",children:[s.jsx(Fe,{type:"password",className:"flex-1",placeholder:L,autoComplete:"new-password",spellCheck:!1,value:f,onChange:F=>p(F.currentTarget.value),onKeyDown:F=>{F.key==="Enter"&&(F.preventDefault(),_())}}),s.jsx(ne,{variant:"default",size:"sm",disabled:h||!f.trim(),onClick:()=>{_()},children:r("保存")}),B?s.jsx(ne,{variant:"outline",size:"sm",disabled:h,onClick:()=>{z()},children:r("清除")}):null]})]})]})]})})}function ete({open:e,onClose:t}){return s.jsx(Yt,{open:e,onOpenChange:a=>{a||t()},children:s.jsxs(Xt,{className:"w-[min(320px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("加入 QQ 群")})}),s.jsxs(Lt,{className:"items-center gap-3 text-center",children:[s.jsx("img",{className:"qq-qr",src:yX,alt:r("QQ 群二维码")}),s.jsxs("div",{className:"qq-no",children:[s.jsx("span",{className:"k",children:r("群号")}),s.jsx("code",{children:lx}),s.jsx(ne,{type:"button",size:"sm",variant:"ghost","data-copy":lx,children:r("复制")})]}),s.jsx("p",{className:"qq-hint",children:r("用手机 QQ 扫上面的二维码,或在 QQ 里搜索群号加入。")})]})]})})}const tte=1e3,BP=8,nte=10,ste=1e3,rte={"":"outline",ok:"success",warn:"warning",bad:"destructive"},ate={info:null,checkedAt:0,repository:"",badgeText:r("未检查"),badgeTone:"",stateText:r("点击「检查更新」查询最新发布版本。"),stateError:!1,percent:0,phase:"idle",readyPath:"",checking:!1,actionBusy:!1,restartSeconds:0,tokenFilled:null};function Ll(e){return String(e).padStart(2,"0")}function lte(e){const t=new Date(String(e??""));return!e||Number.isNaN(t.getTime())?"":`${t.getFullYear()}-${Ll(t.getMonth()+1)}-${Ll(t.getDate())} ${Ll(t.getHours())}:${Ll(t.getMinutes())}`}function HP(e){const t=new Date(e);if(!e||Number.isNaN(t.getTime()))return"";const a=new Date,o=t.getFullYear()===a.getFullYear()&&t.getMonth()===a.getMonth()&&t.getDate()===a.getDate(),c=`${Ll(t.getHours())}:${Ll(t.getMinutes())}:${Ll(t.getSeconds())}`;return o?c:`${Ll(t.getMonth()+1)}-${Ll(t.getDate())} ${c}`}function Hp(e){const t=e?.installerKind;if(t==="dmg"||t==="deb"||t==="appimage"||t==="nsis")return t;const a=navigator.userAgent||"";return/Mac|iPhone|iPad/.test(a)?"dmg":/Linux/.test(a)?"deb":"nsis"}function Ia(e){return e?.selfUpdate===!0}function UP(e){return e?Ia(e)?e.serverAsset??null:e.asset??null:null}function ote(e){if(Ia(e))return r("正在下载服务端更新包…(下载完成后由面板完成替换,重启容器内的服务后生效)");switch(Hp(e)){case"dmg":return r("正在下载安装包…(下载完成后会挂载磁盘映像,把应用拖进「应用程序」即可完成安装)");case"deb":return r("正在下载安装包…(下载完成后会交给系统安装器,按提示输入密码即可完成安装)");case"appimage":return r("正在下载安装包…(下载完成后会启动新的 AppImage;把它替换掉旧文件即完成升级)");default:return r("正在下载安装包…(下载完成后启动安装程序需要管理员权限,会弹出 UAC 确认框)")}}function VP(e,t){if(Ia(e))return r("更新包已就绪:{name}。点「安装并重启」后,面板会校验并替换容器内的程序与界面文件,然后重启服务(页面会自动刷新)。",{name:t});switch(Hp(e)){case"dmg":return r("安装包已就绪:{name}。点击「打开安装包」后会挂载磁盘映像,把应用拖进「应用程序」即可完成安装。",{name:t});case"deb":return r("安装包已就绪:{name}。点击「打开安装包」后会交给系统安装器,按提示输入密码即可完成安装(本程序无需退出)。",{name:t});case"appimage":return r("安装包已就绪:{name}。点击「安装并重启」后会启动新的 AppImage;把它移动到你的应用目录并替换旧文件即完成升级(本程序会先退出以释放文件占用)。",{name:t});default:return r("安装包已就绪:{name}。点击「安装并重启」后需要管理员权限,会弹出 UAC 确认框。",{name:t})}}function ite(e){if(Ia(e))return r("安装并重启");const t=Hp(e);return r(t==="dmg"||t==="deb"?"打开安装包":"安装并重启")}let Vr=ate;const FS=new Set;function $S(){return Vr}function cte(e){return FS.add(e),()=>{FS.delete(e)}}function zn(e){Vr={...Vr,...e};for(const t of FS)t()}async function qS(){try{const e=await nn().workbuddyDesktop?.getUpdateToken();zn({tokenFilled:e?.filled===!0})}catch{}}let Cr=!1,GS=null,tb=null;function ad(){tb!==null&&(window.clearInterval(tb),tb=null)}function Rs(e,t=""){zn({badgeText:e,badgeTone:t})}function Mn(e,t=!1){zn({stateText:e,stateError:t})}function nb(){const{info:e,checkedAt:t}=Vr;if(!e)return;const a=t?r("(检查于 {time})",{time:HP(t)}):"";if(e.pendingRestart===!0){Rs(r("待重启"),"warn"),Mn(r("更新已应用到容器内,重启服务后生效。{at}",{at:a}));return}if(e.hasUpdate===!0){if(Rs(r("有新版本"),"warn"),Ia(e)&&!e.serverAsset){Mn(r("发现新版本 {latest}(当前 {current}),但该版本没有提供容器内更新包;请在宿主机执行 docker compose pull && docker compose up -d 升级。{at}",{latest:String(e.latestVersion||""),current:String(e.currentVersion||""),at:a}));return}Mn(r("发现新版本 {latest}(当前 {current})。{at}",{latest:String(e.latestVersion||""),current:String(e.currentVersion||""),at:a}))}else e.hasUpdate===!1?(Rs(r("已是最新"),"ok"),Mn(r("当前已是最新版本({current})。{at}",{current:String(e.currentVersion||""),at:a}))):(Rs(r("无法比较"),"warn"),Mn(e.latestVersion?r("最新发布版本为 {latest},但当前版本号「{current}」无法解析,未做新旧判断。{at}",{latest:e.latestVersion,current:e.currentVersion||r("未知"),at:a}):r("仓库暂无发布版本。{at}",{at:a})))}function FP(e){!e||e.checked===!1||(zn({info:e,checkedAt:Number(e.checkedAt)||0}),e.repository&&KS(e.repository),Vr.phase==="idle"&&nb())}function KS(e){const t=String(e||"").trim();/^[\w.-]+\/[\w.-]+$/.test(t)&&zn({repository:t})}function YS(e){if(!e)return!1;if(e.active){const t=Math.max(0,Math.min(100,Number(e.percent)||0)),a=(Number(e.received)||0)/1024/1024,o=(Number(e.total)||0)/1024/1024;return zn({phase:"downloading",percent:t}),Rs(r("下载中"),"warn"),Mn(r("正在下载 {name}:{percent}%({received} / {total} MB)",{name:e.filename||r("安装包"),percent:t,received:a.toFixed(1),total:o.toFixed(1)})),!0}if(ad(),zn({percent:0}),e.error)return Rs(r("下载失败"),"bad"),Mn(r("下载失败:{error}",{error:e.error}),!0),zn({phase:"failed"}),!0;if(e.canceled)return Rs(r("已取消"),"warn"),Mn(Ia(Vr.info)?r("下载已取消,可重新点击「下载并更新」。"):r("下载已取消,可重新点击「下载并安装」。")),zn({phase:"idle"}),!0;if(e.done&&e.path){const t=e.path,a=e.filename||t;if(Rs(r("可安装"),"ok"),zn({phase:"ready",readyPath:t}),Ia(Vr.info))return Mn(VP(Vr.info,a)),!0;if(t!==GS){GS=t;const o=Hp(Vr.info);Mn(r(o==="dmg"?"安装包已下载完成,正在挂载磁盘映像…":o==="deb"?"安装包已下载完成,正在打开系统安装器…":o==="appimage"?"安装包已下载完成,正在启动新的 AppImage…":"安装包已下载完成,正在启动安装程序(需要管理员权限,会弹出 UAC 确认框)…")),qP(t)}else Mn(VP(Vr.info,a));return!0}return!1}async function ute(){try{const e=await nn().workbuddyDesktop?.updateProgress();if(!e){ad();return}YS(e)}catch(e){ad(),Mn(r("读取下载进度失败:{error}",{error:pr(e)}),!0)}}function $P(){ad(),tb=window.setInterval(()=>{ute()},tte)}async function qP(e){const t=nn().workbuddyDesktop;if(t)try{const o=(await t.runInstaller(e,!0))?.restart!==!1,c=Hp(Vr.info)==="deb"?r("已打开系统安装器,请在它弹出的窗口里完成安装。安装完成后重新打开本程序即可。"):r("安装包已挂载,请在弹出的窗口里把应用拖进「应用程序」完成安装。安装完成后重新打开本程序即可。");Mn(o?r("安装程序已启动,本程序将退出以便完成覆盖安装。安装程序需要管理员权限,会弹出 UAC 确认框,请选择「是」。"):c)}catch(a){Rs(r("启动失败"),"bad"),Mn(r("启动安装程序失败:{error}",{error:pr(a)}),!0)}}async function dte(){const e=nn().workbuddyDesktop;if(e?.installUpdate)try{Rs(r("安装中"),"warn"),Mn(r("正在校验并替换容器内的程序与界面文件…"));const t=await e.installUpdate(),a=String(t?.version||"").trim();Mn(a?r("已替换为 {version},正在重启服务…",{version:a}):r("替换完成,正在重启服务…")),await e.restartService?.().catch(()=>{}),XS(a)}catch(t){Rs(r("安装失败"),"bad"),Mn(r("安装失败:{error}",{error:pr(t)}),!0)}}async function fte(){const e=nn().workbuddyDesktop;if(!(!e?.rollbackUpdate||Cr)){Cr=!0,zn({actionBusy:!0});try{Rs(r("回滚中"),"warn"),Mn(r("正在回滚到上一版本…")),await e.rollbackUpdate(),Mn(r("已还原上一版本,正在重启服务…")),await e.restartService?.().catch(()=>{}),XS("")}catch(t){Rs(r("回滚失败"),"bad"),Mn(r("回滚失败:{error}",{error:pr(t)}),!0)}finally{Cr=!1,zn({actionBusy:!1})}}}function XS(e){ad(),zn({phase:"restarting",restartSeconds:BP,readyPath:""}),Rs(r("重启中"),"warn");let t=BP;const a=()=>{if(Mn(e?r("{version} 已就位,服务正在重启,页面会在恢复后自动刷新…({seconds}s)",{version:e,seconds:Math.max(0,t)}):r("服务正在重启,页面会在恢复后自动刷新…({seconds}s)",{seconds:Math.max(0,t)})),t<=0){window.clearInterval(o),pte();return}t-=1,zn({restartSeconds:t})},o=window.setInterval(a,1e3);a()}async function pte(){for(let e=0;e{window.setTimeout(t,ste)})}window.location.reload()}async function GP(){if(Cr)return null;Cr=!0,zn({checking:!0}),Rs(r("检查中"),"warn"),Mn(r("正在查询 GitHub 上的最新发布版本…"));let e=null;try{const t=nn().workbuddyDesktop;if(!t)throw new Error(r("后端桥不可用"));e=await t.checkUpdate()??null,zn({info:e,checkedAt:Number(e?.checkedAt)||Date.now()}),e?.repository&&KS(e.repository),nb()}catch(t){e=null,zn({info:null,checkedAt:0}),Rs(r("检查失败"),"bad"),Mn(r("检查更新失败:{error}",{error:pr(t)}),!0)}finally{Cr=!1,zn({checking:!1})}return nn().wbApp?.updateUpdateBadge?.(e),Jx(e,Up),e}async function KP(){let e=null;try{e=await nn().workbuddyDesktop?.getUpdateStatus()??null}catch{}if(e&&e.checked!==!1){FP(e),nn().wbApp?.updateUpdateBadge?.(e),Jx(e,Up);return}Vr.info||(Rs(r("未检查")),Mn(r("点击「检查更新」查询 GitHub 上的最新发布版本。")))}async function QS(){if(Cr)return;const e=$S();if(e.info?.pendingRestart===!0&&e.phase!=="downloading"){Cr=!0,zn({actionBusy:!0});try{await nn().workbuddyDesktop?.restartService?.().catch(()=>{}),XS("")}finally{Cr=!1,zn({actionBusy:!1})}return}if(e.phase!=="downloading"&&e.readyPath){Cr=!0,zn({actionBusy:!0});try{Ia(e.info)?await dte():await qP(e.readyPath)}finally{Cr=!1,zn({actionBusy:!1})}return}if(e.phase==="downloading"){try{await nn().workbuddyDesktop?.cancelUpdate(),Mn(r("正在取消下载…"))}catch(a){Es(r("取消失败:{error}",{error:pr(a)}),"err")}return}const t=UP(e.info);if(!t?.url){Es(Ia(e.info)?r("这一版没有提供容器内更新包"):r("没有可下载的安装包"),"err");return}if(XP(e)){Cr=!0,zn({actionBusy:!0});try{await nn().workbuddyDesktop?.downloadUpdate({url:t.url,name:t.name}),GS=null,zn({phase:"downloading",readyPath:"",percent:0}),Rs(r("下载中"),"warn"),Mn(ote(e.info)),$P()}catch(a){Rs(r("下载失败"),"bad"),Mn(r("下载失败:{error}",{error:pr(a)}),!0)}finally{Cr=!1,zn({actionBusy:!1})}}}async function YP(){nb(),qS(),await KP();try{const e=await nn().workbuddyDesktop?.updateProgress();if(e?.active){YS(e),$P();return}if(e?.done&&e.path){YS(e);return}}catch{}}async function Up(e){if(e?.pendingRestart===!0){await QS();return}e?.hasUpdate===!0&&(zn({info:e,checkedAt:Number(e.checkedAt)||Vr.checkedAt}),e.repository&&KS(e.repository),nb(),nn().wbApp?.updateUpdateBadge?.(e),Jx(e,Up)),await YP();const t=$S();if(!(t.phase==="downloading"||t.readyPath)&&t.info?.hasUpdate)for(let a=0;a<3;a+=1){if(Cr){await new Promise(o=>{window.setTimeout(o,400)});continue}await QS();return}}function XP(e){return e.phase==="restarting"?null:e.info?.pendingRestart===!0&&e.phase==="idle"?{label:r("立即重启"),disabled:e.actionBusy}:!(e.info?.hasUpdate===!0&&!!UP(e.info)?.url)&&e.phase!=="downloading"&&e.phase!=="ready"?null:{label:e.phase==="downloading"?r("取消下载"):e.phase==="failed"?r("重试下载"):e.phase==="ready"?ite(e.info):Ia(e.info)?r("下载并更新"):r("下载并安装"),disabled:e.actionBusy}}function mte(e,t){const a=e.info,o=String(a?.notes||"").trim();if(!o)return s.jsx("div",{className:"update-log-hint",children:r(a?"这个版本没有填写发布说明。":"点击「检查更新」后,这里会显示最新版本的更新说明。")});const c=dD(o),d=cD(a?.pageUrl),f=lte(a?.publishedAt);return s.jsxs("div",{className:"rel-note",children:[s.jsxs("div",{className:"rel-note-head",children:[s.jsx("span",{className:"rel-tag",children:String(a?.latestVersion||r("最新版本"))}),a?.prerelease===!0?s.jsx(ze,{shape:"tag",variant:"warning",children:r("预发布")}):null,f?s.jsx("span",{className:"rel-date",children:f}):null]}),s.jsxs("div",{className:"rel-note-body",children:[c?s.jsx("div",{className:"md-body",dangerouslySetInnerHTML:{__html:c}}):s.jsx("div",{className:"md-body",children:s.jsx("p",{className:"md-body-empty",children:r("这个版本没有填写发布说明。")})}),s.jsxs("div",{className:"rel-foot",children:[d?s.jsx("a",{href:d,"data-external":d,target:"_blank",rel:"noopener",children:r("在 GitHub 查看完整说明")}):null,s.jsx(ne,{type:"button",variant:"link",size:"sm",className:"h-auto border-0 px-0 text-[11.5px] font-semibold text-primary-fg underline-offset-auto",title:r("群号:{group}",{group:lx}),onClick:t,children:r("加入 QQ 群")})]})]})]})}function hte(){const e=x.useSyncExternalStore(cte,$S),t=XP(e),[a,o]=x.useState(!1),[c,d]=x.useState(!1);x.useEffect(()=>()=>{ad()},[]),x.useEffect(()=>{qS()},[]);const f=e.repository?`https://github.com/${e.repository}`:"",p=e.repository?`https://github.com/${e.repository.split("/")[0]}`:"",h=Ia(e.info),b=h&&e.info?.backupAvailable===!0&&e.phase!=="downloading"&&e.phase!=="ready"&&e.phase!=="restarting",y=e.info?.latestVersion?e.info.prerelease?r("{version}(预发布)",{version:e.info.latestVersion}):e.info.latestVersion:"—",v=String(e.info?.latestVersion||"").trim(),j=v?`${v}${e.checkedAt?r(" · 检查于 {time}",{time:HP(e.checkedAt)}):""}`:"";return s.jsxs("section",{className:"panel",onClick:Xu,children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("软件更新")}),s.jsx("span",{className:"tip-q","data-tip":r(h?"容器内更新:更新包从 GitHub 发布页下载,校验 sha256 后由面板替换容器内的程序与界面文件,再重启服务(容器由 restart 策略拉起,页面会自动刷新)。更新的是容器里的文件,compose 里的镜像标签不变 —— 之后执行 docker compose pull && up -d 会回到镜像里的版本;更新失败可一键回滚到上一版本。检查更新与下载的出网线路、GitHub 令牌都在「更新设置」里。":"更新包从 GitHub 发布页下载,下载完成后可直接启动安装程序并自动重启本程序。安装包会先校验来源域名与文件完整性。检查更新与下载安装包的出网线路、GitHub 令牌都在「更新设置」里:线路默认直连(直连失败时自动借 Clash Verge 的混合端口重试一次),选定指定出口后只走该出口;填写 GitHub 令牌可把检查限额从 60 次/小时提高到 5000 次/小时。")}),s.jsx(ze,{id:"update-badge",variant:rte[e.badgeTone],"data-tone":e.badgeTone,children:e.badgeText}),s.jsxs("div",{className:"head-actions",children:[e.tokenFilled===!1?s.jsx("span",{className:"text-[12px] font-semibold text-warning",title:r("填写后检查限额 60 → 5000 次/小时(创建令牌无需勾选任何权限)"),children:r("GitHub Token 未填写")}):null,s.jsx(ne,{id:"btn-update-settings",variant:"outline",title:r("出网线路与 GitHub 令牌设置"),onClick:()=>o(!0),children:r("更新设置")}),s.jsx(ne,{id:"btn-update-check",variant:"outline",disabled:e.checking||e.phase==="restarting",onClick:()=>{GP()},children:e.checking?r("检查中…"):r("检查更新")}),b?s.jsx(ne,{id:"btn-update-rollback",variant:"outline",disabled:e.actionBusy,title:r("把容器内的程序与界面文件还原到更新前的版本,并重启服务"),onClick:()=>{fte()},children:r("回滚到上一版本")}):null,t?s.jsx(ne,{id:"btn-update-download",variant:"default",disabled:t.disabled,onClick:()=>{QS()},children:t.label}):null]})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"update-version",children:[s.jsxs("span",{className:"version-pill",children:[s.jsx("span",{className:"k",children:r("当前版本")}),s.jsx("span",{className:"v",id:"update-current",children:e.info?.currentVersion||"—"})]}),s.jsx("span",{className:"version-arrow",children:"→"}),s.jsxs("span",{className:"version-pill new",children:[s.jsx("span",{className:"k",children:r("最新版本")}),s.jsx("span",{className:"v",id:"update-latest",children:y})]})]}),s.jsx("div",{className:"detail",id:"update-state",style:e.stateError?{color:"var(--danger)"}:void 0,children:e.stateText}),e.phase==="downloading"&&e.percent>0&&e.percent<100?s.jsx(cf,{value:e.percent}):null,p&&f?s.jsxs("div",{className:"update-author",id:"update-author",children:[s.jsxs("div",{className:"update-author-text",children:[s.jsx("strong",{children:r("关于作者")}),s.jsxs("span",{children:[r("本工具由")," ",s.jsx("a",{id:"update-author-link",href:p,"data-external":p,target:"_blank",rel:"noopener",children:e.repository.split("/")[0]})," ",r("个人开发并开源维护,免费使用,也不会收集你的账号数据。如果它帮到了你,欢迎到项目仓库点个 Star 支持一下。")]})]}),s.jsx("div",{className:"update-author-actions",children:s.jsx(ne,{id:"btn-update-favorite",type:"button",size:"sm",variant:"outline","data-external":f,title:r("在浏览器中打开项目仓库,点 Star 支持作者"),children:r("收藏项目")})})]}):null,s.jsxs("div",{className:"update-log",id:"update-notes",children:[s.jsxs("div",{className:"update-log-head",children:[s.jsx("span",{className:"update-log-title",children:r("更新日志")}),s.jsx("span",{className:"update-log-meta",id:"update-log-meta",children:j})]}),s.jsx("div",{className:"update-log-body",id:"update-log-body",children:mte(e,()=>d(!0))})]})]}),a?s.jsx(Jee,{open:!0,onClose:()=>{o(!1),qS()}}):null,c?s.jsx(ete,{open:!0,onClose:()=>d(!1)}):null]})}const QP='.settings-pane[data-cat="about"]';let ZS=null;function ZP(){if(ZS)return;const e=document.querySelector(QP);e&&(e.replaceChildren(),ZS=jn.createRoot(e),ZS.render(s.jsx(hte,{})))}document.querySelector(QP)?ZP():document.addEventListener("DOMContentLoaded",ZP,{once:!0}),window.wbUpdatePanel={load:YP,check:GP,syncFromCache:KP,openAndDownload:Up,applyStatus:FP,showUpdateModal:e=>Jx(e,Up)};const gte="zcode.z.ai/billing",xte={active:"success",pending:"warning",expired:"ghost",unknown:"outline"};function bte(e){const t=String(e||"").trim().toLowerCase();return t==="daily"?r("每日"):t==="weekly"?r("每周"):t==="monthly"?r("每月"):""}function vte(e){const t=Number(e);if(!Number.isFinite(t)||t<=0)return"";const a=window.wbUnits;return a?.formatTokens?a.formatTokens(t):String(t)}function mc(e){const t=Number(e);return!Number.isFinite(t)||t<=0?"":Pe().wbApp?.formatTime?.(t*1e3)||new Date(t*1e3).toLocaleString()}function yte(e){const t=vte(e.grantUnits),a=String(e.unitType||"").trim(),o=t?[t,a].filter(Boolean).join(" "):"",c=bte(e.period),d=[String(e.showName||"").trim(),o].filter(Boolean).join(" ");return d?c?r("{body}({period})",{body:d,period:c}):d:""}function WP(e){return(e.entitlements||[]).map(yte).filter(Boolean).join(r("、"))}function jte(e){const t=mc(e.startsAt),a=mc(e.endsAt);return t&&a?`${t} → ${a}`:a?r("到期 {time}",{time:a}):t?r("开始 {time}",{time:t}):""}function wte(e){const t=new Date(e*1e3);if(Number.isNaN(t.getTime()))return"";const a=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`,o=d=>Math.floor(Date.UTC(d.getFullYear(),d.getMonth(),d.getDate())/864e5),c=o(t)-o(new Date);return c===0?r("今天 {time}",{time:a}):c===1?r("明天 {time}",{time:a}):mc(e)}function Ste(e){const t=[],a=Number(e.pendingUntil);if(Number.isFinite(a)&&a>0){const c=wte(a);c&&t.push(r("待生效 {time}",{time:c}))}const o=mc(e.endsAt);if(o&&t.push(r("到期 {time}",{time:o})),t.length===0){const c=mc(e.startsAt);c&&t.push(r("开始 {time}",{time:c}))}return t.join(" · ")}function Nte({options:e,onClose:t}){const a=e.id,[,o]=x.useState(0);x.useEffect(()=>sR(()=>o(I=>I+1)),[]);const[c,d]=x.useState([]),[f,p]=x.useState({status:"loading"}),[h,b]=x.useState(""),y=Aa(a),v=String(y?.name||e.name||a),j=eg(y),w=[...new Set([...j,...c])],S=y?.claimPlans&&typeof y.claimPlans=="object"&&!Array.isArray(y.claimPlans)?y.claimPlans:{},N=y?Wa(y):void 0,k=N&&typeof N=="object"&&!Array.isArray(N)?N:null,A=k&&Array.isArray(k.plans)?k.plans:[],P=w.filter(I=>I&&!A.some(O=>String(O.planId||"")===I)),R=Gs().usageInflight.has(a),C=Pe().wbZcodeClaim,E=x.useCallback(async()=>{if(!C?.preview){p({status:"error",message:r("当前环境不支持领取(桥接方法缺失)")});return}p({status:"loading"});try{const I=await C.preview(a);p({status:"ready",result:I||{}})}catch(I){p({status:"error",message:mt(I)})}},[C,a]);x.useEffect(()=>{E();const I=Aa(a);I&&Wa(I)===void 0&&ig(a)},[a,E]);async function D(I){if(!(!C?.claim||h)){b(I);try{const O=await C.claim(a,I);if(O?.ok||O?.failure==="already_claimed"){const _=O.planId||I;_&&d(z=>z.includes(_)?z:[...z,_]),ig(a),Pe().wbApp?.refresh?.(),E()}}finally{b("")}}}return s.jsx(Yt,{open:!0,onOpenChange:(I,O)=>{if(!I){if(h){O.cancel();return}t()}},children:s.jsxs(Xt,{className:"w-[min(560px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("ZCode 套餐明细 — {name}",{name:v})})}),s.jsxs(Lt,{className:"space-y-4",children:[s.jsxs("section",{children:[s.jsxs("div",{className:"mb-1.5 flex items-center gap-2 text-[12px] font-semibold text-muted-foreground",children:[r("可领取的套餐"),s.jsx(ze,{variant:"outline",shape:"tag",children:r("官方限时活动")})]}),f.status==="loading"?s.jsxs("div",{className:"flex items-center gap-2 py-2 text-[12.5px] text-muted-foreground",children:[s.jsx(of,{className:"size-3"}),r("正在探测可领取的套餐…")]}):f.status==="error"?s.jsxs("div",{className:"py-1 text-[12.5px] text-destructive",children:[r("探测失败:{message}",{message:f.message}),s.jsx(ne,{variant:"outline",size:"xs",className:"ml-2",onClick:()=>{E()},children:r("重试")})]}):f.result.deployed?(f.result.plans||[]).length===0?s.jsx("p",{className:"py-1 text-[12.5px] text-muted-foreground",children:r("当前没有可领取的套餐(活动期内每天发一份,明天可再领)")}):s.jsx("ul",{className:"m-0 list-none p-0",children:(f.result.plans||[]).map(I=>{const O=String(I.planId||""),_=w.includes(O),z=WP(I),H=jte(I);return s.jsxs("li",{className:"flex items-start justify-between gap-3 border-b border-hairline py-2 last:border-b-0",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsxs("div",{className:"flex items-center gap-2 text-[13px] font-medium",children:[s.jsx("span",{className:"truncate",children:I.name||O||r("套餐")}),_?s.jsx(ze,{variant:"success",shape:"tag",children:r("今日已领")}):null]}),H?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:H}):null,z?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:z}):null,I.description?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:I.description}):null]}),s.jsx(ne,{variant:"outline",size:"xs",className:"flex-none",title:_?r("这一份今天已经领过了(重复领取上游会回「已领取过」)"):void 0,disabled:h!=="",onClick:()=>{D(O)},children:r(h===O?"领取中…":_?"再领一次":"领取")})]},O||I.name)})}):s.jsx("p",{className:"py-1 text-[12.5px] text-muted-foreground",children:r("当前没有可领取的套餐(活动尚未开始)")}),s.jsx("p",{className:"mt-1.5 text-[11.5px] text-muted-foreground",children:r("活动期内每天发一份新套餐;同一份当天重复领取会提示「已领取过」,次日可再领。领取要走一次人机验证(滑块)。")}),f.status==="ready"&&f.result.activationError?s.jsx("p",{className:"text-[11.5px] text-muted-foreground",children:r("(激活事件补报失败,可能影响领取资格:{message})",{message:f.result.activationError})}):null]}),s.jsxs("section",{children:[s.jsxs("div",{className:"mb-1.5 flex items-center gap-2 text-[12px] font-semibold text-muted-foreground",children:[r("我的套餐"),Array.isArray(k?.wallets)&&k.wallets.length>0&&k.availableView?s.jsx(ze,{variant:"outline",shape:"tag",children:String(k.walletsFrom||"")==="monitor"?String(k.availableView):r("可用 {value}",{value:String(k.availableView)})}):null,s.jsx("div",{className:"ml-auto",children:s.jsx(ne,{variant:"outline",size:"xs",disabled:R,title:r("重新读取该账号的余额与套餐(走余额查询那条链)"),onClick:()=>{ig(a)},children:r(R?"查询中…":"查询余额")})})]}),A.length>0?s.jsx("ul",{className:"m-0 list-none p-0",children:A.map(I=>{const O=String(I.planId||""),_=String(I.state||"unknown"),z=WP(I),H=Ste(I),B=O&&y?.claimPlans&&Number(y.claimPlans[O])||0;return s.jsxs("li",{className:"flex items-start justify-between gap-3 border-b border-hairline py-2 last:border-b-0",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsxs("div",{className:"flex items-center gap-2 text-[13px] font-medium",children:[s.jsx("span",{className:"truncate",children:I.name||O||r("套餐")}),s.jsx(ze,{variant:xte[_]||"outline",shape:"tag",children:qA(_)})]}),H?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:H}):null,z?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:z}):null]}),B>0?s.jsx("span",{className:"flex-none text-[11.5px] text-muted-foreground",children:r("本地领取于 {time}",{time:mc(B/1e3)})}):null]},O||I.name)})}):s.jsx("p",{className:"py-1 text-[12.5px] text-muted-foreground",children:N===void 0?r("还没有余额读数(已自动查询一次,稍候;也可以点右上角「查询余额」重读)"):k&&k.source&&k.source!==gte?r("这个账号的余额走窗口限额通道(只配了编码套餐 API Key):只有每 N 小时的剩余比例,读不到套餐清单"):r("读数里没有套餐清单(免费账号、或套餐的上游状态还没刷新;可点右上角「查询余额」重读)")}),P.length>0?s.jsx("p",{className:"mt-1.5 text-[11.5px] text-muted-foreground",children:r("本地台账里今天还领过这些,但上面的读数里还没有:{plans}(读数刷新可能有延迟)",{plans:P.map(I=>{const O=Number(S[I])||0,_=O>0?mc(O/1e3):"";return _?r("{plan}({time} 领取)",{plan:I,time:_}):I}).join(r("、"))})}):null]})]}),s.jsxs(tn,{children:[s.jsx("span",{className:"min-w-0 text-[11.5px] text-muted-foreground",children:w.length>0?r("今天(北京时间)已领取 {n} 份:{plans}",{n:w.length,plans:w.join(r("、"))}):r("今天还没有领过:上面「可领取的套餐」里逐份点「领取」即可")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")})]})]})})}let Vp=null,ld=null;function JP(){Vp&&(Vp.unmount(),Vp=null),ld&&(ld.remove(),ld=null)}function kte(e){e?.id&&(JP(),ld=document.createElement("div"),document.body.append(ld),Vp=jn.createRoot(ld),Vp.render(s.jsx(Nte,{options:e,onClose:JP})))}window.wbZcodePlans={open:kte};const e_="w-auto flex-auto";function t_({onInput:e,domRef:t,icon:a,className:o,inputClassName:c,...d}){const f=h=>{t.current=h},p=h=>{e?.(h.currentTarget.value)};return a?s.jsxs(Di,{className:Ue(e_,o),children:[s.jsx(Pi,{ref:f,className:c,onInput:p,...d}),s.jsx(Ii,{"aria-hidden":"true",children:a})]}):s.jsx(Fe,{ref:f,className:Ue(e_,c),onInput:p,...d})}function Cte(e,t){const a=jn.createRoot(e),o={current:null};return a.render(s.jsx(t_,{domRef:o,defaultValue:t.value,placeholder:t.placeholder,type:t.type??"search",icon:t.icon,"aria-label":t.ariaLabel,onInput:t.onInput})),{setValue(c){const d=o.current;d&&d.value!==c&&(d.value=c)},getValue(){return o.current?.value??""},focus(){o.current?.focus()},unmount(){a.unmount()}}}const Tte=[["id","id"],["type","type"],["name","name"],["title","title"],["placeholder","placeholder"],["min","min"],["max","max"],["step","step"],["autocomplete","autoComplete"]];function Ete(e){const t={defaultValue:e.value||void 0,inputClassName:e.className||void 0};for(const[f,p]of Tte){const h=e.getAttribute(f);h!=null&&(t[p]=h)}const a=e.getAttribute("maxlength");a!=null&&(t.maxLength=Number(a));const o=e.getAttribute("inputmode");o!=null&&(t.inputMode=o),e.hasAttribute("spellcheck")&&(t.spellCheck=e.spellcheck),e.disabled&&(t.disabled=!0),e.readOnly&&(t.readOnly=!0),e.hidden&&(t.hidden=!0);const c=e.getAttribute("aria-label");c!=null&&(t["aria-label"]=c);for(const f of e.getAttributeNames())!f.startsWith("data-")||f.startsWith("data-island-")||(t[f]=e.getAttribute(f)??"");const d=e.getAttribute("data-island-icon");return d!=null&&(t.icon=d),t}function n_(e){if(e.dataset.islandUpgraded)return;e.dataset.islandUpgraded="1";const t=Ete(e),a=e.parentElement?.classList.contains("input-affix")?e.parentElement:null;let o;a?(a.className=a.className.replace(/\binput-affix\b/,"").trim(),a.style.display="flex",a.style.alignItems="center",o=a):(o=document.createElement("span"),o.style.display="contents",e.replaceWith(o));const c={current:null},d=jn.createRoot(o);Ts.flushSync(()=>{d.render(s.jsx(t_,{...t,domRef:c}))})}function s_(e=document){if(e instanceof HTMLInputElement&&e.matches("[data-island-input]")){n_(e);return}e.querySelectorAll("input[data-island-input]").forEach(n_)}function Ate(){s_();const e=new MutationObserver(t=>{for(const a of t)for(const o of a.addedNodes)o instanceof Element&&s_(o)});return e.observe(document.body,{childList:!0,subtree:!0}),e}function Rte(e,t){const a=jn.createRoot(e);let o={options:t.options,value:t.value,ariaLabel:t.ariaLabel,className:t.className};const c=()=>{a.render(s.jsx(En,{options:o.options,value:o.value,onValueChange:t.onChange,"aria-label":o.ariaLabel,className:o.className}))};return c(),{setValue(d){d!==o.value&&(o={...o,value:d},c())},setOptions(d){o={...o,options:d},c()},unmount(){a.unmount()}}}window.wbSegmented={mount:Rte},window.wbInput={mount:Cte},Ate()})(); +`)}}const b=[...f.entries()].sort((y,v)=>y[0]-v[0]).map(([,y])=>y);b.length&&e.onEvent({type:"toolCalls",calls:b}),e.onEvent({type:"done",finishReason:p})}function iw(e){const t=String(e||"").trim();if(!t)return{};try{const a=JSON.parse(t);return a&&typeof a=="object"&&!Array.isArray(a)?a:{}}catch{return{}}}function el(){const e=window.workbuddyDesktop;if(!e)throw new Error(r("桌面桥不可用(本页需要在 Agent2API 客户端里打开)"));return e}function Du(){window.wbApp?.refresh?.()}function at(e,t=256){return typeof e=="string"?e.trim().slice(0,t):""}function Qi(e){return typeof e=="boolean"?e:void 0}function Kf(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function Iu(e){return Array.isArray(e)?e.filter(t=>!!t&&typeof t=="object"):[]}function Dl(e){return(e instanceof Error?e.message:String(e)).replace(/^Error:\s*/,"")}async function Ig(){const e=await el().getState?.();return(Array.isArray(e?.accounts)?e.accounts:[]).slice().sort((a,o)=>Number(a.priority??0)-Number(o.priority??0))}function Yf(e){return at(e.name)||at(e.nickname)||at(e.id)||r("未命名账号")}function cw(e,t){const a=t.trim();if(!a)throw new Error(r("没给账号名"));const o=e.find(p=>at(p.id)===a);if(o)return o;const c=e.filter(p=>Yf(p)===a);if(c.length===1)return c[0];const d=e.filter(p=>Yf(p).includes(a));if(d.length===1)return d[0];const f=(c.length?c:d).map(Yf).slice(0,6);throw f.length?new Error(r("「{name}」匹配到多个账号:{list},请用完整账号名重试",{name:a,list:f.join("、")})):new Error(r("没有找到账号「{name}」",{name:a}))}const A7={id:"list_models",label:r("获取模型列表"),kind:"read",desc:"读取各提供商的模型清单(模型 ID、所属提供商、是否启用、已挂的映射名)以及全部映射。回答「有哪些模型」「哪些模型在多家重复」「某个名字挂在哪」这类问题之前先调用它。",params:{type:"object",properties:{provider:{type:"string",description:"只看某一家(提供商 id,如 codearts / workbuddy);不填 = 全部"},keyword:{type:"string",description:"按模型 ID 或映射名做子串过滤;不填 = 不过滤"},enabledOnly:{type:"boolean",description:"true = 只看已启用的模型"}}},run:async e=>{const t=at(e.provider,64).toLowerCase(),a=at(e.keyword,128).toLowerCase(),o=Qi(e.enabledOnly)===!0,c=await el().getModelManage?.(),f=(Array.isArray(c?.models)?c.models:[]).filter(p=>!(t&&at(p.provider).toLowerCase()!==t||o&&p.enabled!==!0||a&&![at(p.id),at(p.name),...Array.isArray(p.aliases)?p.aliases.map(b=>at(b)):[]].join(" ").toLowerCase().includes(a))).map(p=>({provider:at(p.provider),id:at(p.id),enabled:p.enabled===!0,aliases:Array.isArray(p.aliases)?p.aliases.map(h=>at(h)):[]}));return{text:JSON.stringify({total:f.length,models:f.slice(0,400)}),summary:r("{n} 个模型",{n:f.length})}}},R7={id:"list_account_balance",label:r("查询账号余额"),kind:"read",desc:"查询各账号的余额 / 剩余额度(会向各上游发起真实的余额查询)。回答「还剩多少」「哪个账号快用完了」这类问题之前先调用它。",params:{type:"object",properties:{account:{type:"string",description:"只查某个账号(账号名或 id);不填 = 全部账号"}}},run:async e=>{const t=at(e.account,128),a=t?at(cw(await Ig(),t).id):"",o=await el().getAllBalances?.(a||void 0),c=Array.isArray(o?.results)?o.results:o,d=Array.isArray(c)?c:[];return{text:JSON.stringify({accounts:d.slice(0,60)}).slice(0,12e3),summary:r("{n} 个账号",{n:d.length})}}},O7={id:"set_model_enabled",label:r("启用 / 禁用模型"),kind:"write",desc:"开启或关闭某几个模型在网关上的可用性(粒度是「提供商 × 模型」)。禁用后下游请求不再路由到它。一次可以改多个。",params:{type:"object",properties:{items:{type:"array",description:"要改的模型列表",items:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},id:{type:"string",description:"模型 ID"},enabled:{type:"boolean",description:"true = 启用,false = 禁用"}},required:["provider","id","enabled"]}}},required:["items"]},plan:e=>{const t=Iu(e.items);return{lead:r("将修改 {n} 个模型的启停状态:",{n:t.length}),table:{head:[r("提供商"),r("模型"),r("改成")],rows:t.map(a=>[at(a.provider),at(a.id),Qi(a.enabled)===!1?r("禁用"):r("启用")])},note:r("改动立即生效;禁用后指向它的请求会落到下一个候选。")}},run:async e=>{const t=el(),a=Iu(e.items),o=[];for(const c of a){const d=at(c.provider),f=at(c.id),p=Qi(c.enabled);if(!d||!f||p===void 0)throw new Error(r("参数不完整(需要 provider / id / enabled)"));await t.setModelState?.({provider:d,id:f,enabled:p}),o.push(`${p?"启用":"禁用"} ${d}/${f}`)}return Du(),{text:JSON.stringify({ok:!0,changed:o}),summary:r("已修改 {n} 个模型",{n:o.length})}}},M7={id:"set_model_mapping",label:r("设置模型映射 ID"),kind:"write",desc:"给模型新增或删除映射名(对外名)。同一对外名可以在多个提供商各挂一条:下游用同一个名字请求,网关按账号优先级主备切换;也可以给不同家的同名模型各加前缀(如 ca/claude-sonnet-4.5)来精确指定某一家。一次可以改多条。删掉的映射名只是不再对外可用,不删任何模型。",params:{type:"object",properties:{items:{type:"array",description:"要改的映射列表",items:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},id:{type:"string",description:"上游模型 ID"},alias:{type:"string",description:"要新增 / 删除的映射名(对外名)"},action:{type:"string",enum:["add","remove"],description:"add = 新增映射,remove = 删除映射"}},required:["provider","id","alias","action"]}}},required:["items"]},plan:e=>{const t=Iu(e.items),a=t.filter(d=>at(d.action)!=="remove").length,o=t.length-a,c=[];return a&&c.push(r("新增 {n} 条",{n:a})),o&&c.push(r("删除 {n} 条",{n:o})),{lead:r("将改动 {n} 条映射({parts}):",{n:t.length,parts:c.join("、")}),table:{head:[r("提供商"),r("上游模型"),r("操作"),r("映射名")],rows:t.map(d=>[at(d.provider),at(d.id),at(d.action)==="remove"?r("删除"):r("新增"),at(d.alias)])},note:r("只改映射名,不动上游模型 ID;映射立即生效(新对话即可用)。")}},run:async e=>{const t=el(),a=Iu(e.items),o=[];for(const c of a){const d=at(c.provider),f=at(c.id),p=at(c.alias,128);if(!d||!f||!p)throw new Error(r("参数不完整(需要 provider / id / alias)"));at(c.action)==="remove"?(await t.removeModelMapping?.(p,f,d),o.push(`删除 ${p} → ${d}/${f}`)):(await t.addModelMapping?.(p,f,d),o.push(`新增 ${p} → ${d}/${f}`))}return Du(),{text:JSON.stringify({ok:!0,changed:o}),summary:r("已改动 {n} 条映射",{n:o.length})}}},JO=["maxInputTokens","maxOutputTokens","supportsToolCall","supportsImages","supportsVideo","supportsReasoning"],uw={maxInputTokens:r("上下文窗口"),maxOutputTokens:r("最大输出 Token"),supportsToolCall:r("工具调用"),supportsImages:r("图片识别"),supportsVideo:r("视频识别"),supportsReasoning:r("深度推理")},D7={id:"set_model_capability",label:r("修改模型能力"),kind:"write",desc:"修改某个模型对下游声明的能力位:上下文窗口、最大输出 Token、工具调用 / 图片 / 视频 / 深度推理四个布尔位。只传要改的键;布尔位给 null 表示恢复上游原值。",params:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},id:{type:"string",description:"模型 ID"},capabilities:{type:"object",description:"要改的能力位(只写要改的键)",properties:{maxInputTokens:{type:["number","null"],description:"上下文窗口(token 数)"},maxOutputTokens:{type:["number","null"],description:"最大输出 token 数"},supportsToolCall:{type:["boolean","null"],description:"是否支持工具调用;null = 恢复上游原值"},supportsImages:{type:["boolean","null"],description:"是否支持图片识别;null = 恢复上游原值"},supportsVideo:{type:["boolean","null"],description:"是否支持视频识别;null = 恢复上游原值"},supportsReasoning:{type:["boolean","null"],description:"是否支持深度推理;null = 恢复上游原值"}}}},required:["provider","id","capabilities"]},plan:e=>{const t=e.capabilities&&typeof e.capabilities=="object"?e.capabilities:{},a=JO.filter(o=>o in t);return{lead:r("将修改 {model} 的 {n} 项能力:",{model:`${at(e.provider)} / ${at(e.id)}`,n:a.length}),table:{head:[r("能力"),r("改成")],rows:a.map(o=>{const c=t[o],d=c===null?r("恢复上游原值"):typeof c=="boolean"?r(c?"支持":"不支持"):String(c);return[uw[o]||o,d]})},note:r("能力位决定下游看到的声明(能不能贴图、能塞多少上下文),不改上游的真实行为。")}},run:async e=>{const t=at(e.provider),a=at(e.id),o=e.capabilities&&typeof e.capabilities=="object"?e.capabilities:{},c={};for(const d of JO){if(!(d in o))continue;const f=o[d];if(f===null){c[d]=null;continue}if(d==="maxInputTokens"||d==="maxOutputTokens"){const p=Kf(f);if(p===void 0)throw new Error(r("{key} 需要数字",{key:uw[d]}));c[d]=Math.round(p)}else{const p=Qi(f);if(p===void 0)throw new Error(r("{key} 需要 true / false / null",{key:uw[d]}));c[d]=p}}if(!t||!a||!Object.keys(c).length)throw new Error(r("参数不完整(需要 provider / id / capabilities)"));return await el().setModelCapabilities?.(t,a,c),Du(),{text:JSON.stringify({ok:!0,provider:t,id:a,capabilities:c}),summary:r("已修改 {n} 项能力",{n:Object.keys(c).length})}}},I7={id:"test_model",label:r("发起模型测试"),kind:"run",desc:"对某个模型发一次真实的对话请求,回报连通性、耗时与首字延迟。会消耗该账号的额度。回答「这个模型通不通 / 快不快」时用它。",params:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},id:{type:"string",description:"模型 ID"},prompt:{type:"string",description:"测试用的用户提示词;不填 = 默认一句问候(最小请求)"}},required:["provider","id"]},plan:e=>({lead:r("将对 {model} 发起一次真实请求:",{model:`${at(e.provider)} / ${at(e.id)}`}),table:{head:[r("项"),r("值")],rows:[[r("提示词"),at(e.prompt)||r("(默认问候)")],[r("代价"),r("消耗该账号额度")]]},note:r("这是真实的上游请求,与生产走同一条链路(会记账,报表排除)。")}),run:async e=>{const t={provider:at(e.provider),model:at(e.id)},a=at(e.prompt,4e3);a&&(t.prompt=a);const o=await el().testModel?.(t),c=String(o?.status??""),d=o?.success===!0,f={ok:d,status:c,error:o?.error??null,reply:String(o?.reply??"").slice(0,1500),duration_ms:o?.duration_ms??null,ttfb_ms:o?.ttfb_ms??null,account:o?.account_name??null};return{text:JSON.stringify(f).slice(0,6e3),summary:d?r("连通 · {ms}ms",{ms:String(f.duration_ms??"")}):r("失败 · {status}",{status:c||"—"})}}},P7={id:"set_provider_order",label:r("调整提供商顺位"),kind:"write",desc:"调整某个提供商在账号全局队列里的**整组顺位**(第几组),决定路由时先试哪一家。这一家的所有账号会作为一整块移动。位置从 1 开始数。",params:{type:"object",properties:{provider:{type:"string",description:"提供商 id"},position:{type:"number",description:"目标组顺位(1 = 最前)"}},required:["provider","position"]},plan:e=>({lead:r("将把「{provider}」整组移到第 {position} 顺位:",{provider:at(e.provider)||r("(未指定)"),position:String(Kf(e.position)??"?")}),note:r("队列是一次性整表提交(后端按新顺序重编优先级),移动会连带调整其它组的相对次序。")}),run:async e=>{const t=at(e.provider).toLowerCase(),a=Kf(e.position);if(!t||a===void 0)throw new Error(r("参数不完整(需要 provider / position)"));const o=await Ig(),c=[];for(const h of o){const b=at(h.id),y=at(h.provider).toLowerCase();if(!b)continue;const v=c[c.length-1];v&&v.provider===y?v.ids.push(b):c.push({provider:y,ids:[b]})}const d=c.findIndex(h=>h.provider===t);if(d<0)throw new Error(r("没有找到提供商「{provider}」的账号",{provider:t}));const f=Math.max(0,Math.min(c.length-1,Math.round(a)-1)),[p]=c.splice(d,1);return c.splice(f,0,p),await el().reorderAccounts?.(c.flatMap(h=>h.ids)),Du(),{text:JSON.stringify({ok:!0,provider:t,from:d+1,to:f+1,moved:p.ids.length}),summary:r("已移到第 {n} 顺位",{n:f+1})}}},_7={id:"set_account_order",label:r("调整账号优先级"),kind:"write",desc:"把某个账号移动到账号全局队列的第 N 顺位(1 = 最前)。位置决定主备与切换顺序:越靠前越先被使用。",params:{type:"object",properties:{account:{type:"string",description:"账号名或账号 id"},position:{type:"number",description:"目标顺位(1 = 最前)"}},required:["account","position"]},plan:e=>({lead:r("将把账号「{account}」移到第 {position} 顺位:",{account:at(e.account)||r("(未指定)"),position:String(Kf(e.position)??"?")}),note:r("队列是一次性整表提交;位置越靠前,路由时越先被选中。")}),run:async e=>{const t=at(e.account,128),a=Kf(e.position);if(!t||a===void 0)throw new Error(r("参数不完整(需要 account / position)"));const o=await Ig(),c=cw(o,t),d=at(c.id),f=o.map(b=>at(b.id)).filter(Boolean),p=f.indexOf(d);if(p<0)throw new Error(r("账号不在当前队列里"));f.splice(p,1);const h=Math.max(0,Math.min(f.length,Math.round(a)-1));return f.splice(h,0,d),await el().reorderAccounts?.(f),Du(),{text:JSON.stringify({ok:!0,account:Yf(c),from:p+1,to:h+1}),summary:r("已移到第 {n} 顺位",{n:h+1})}}},L7={id:"set_account_enabled",label:r("启用 / 禁用账号"),kind:"write",desc:"开启或关闭某几个账号的转发资格。禁用只是把它移出队列(余额仍可查),但**如果某条线路只剩它**,禁用会直接断供。一次可以改多个。",params:{type:"object",properties:{items:{type:"array",description:"要改的账号列表",items:{type:"object",properties:{account:{type:"string",description:"账号名或账号 id"},enabled:{type:"boolean",description:"true = 启用,false = 禁用"}},required:["account","enabled"]}}},required:["items"]},plan:e=>{const t=Iu(e.items),a=t.filter(o=>Qi(o.enabled)===!1).length;return{lead:r("将修改 {n} 个账号的启用状态(其中禁用 {k} 个):",{n:t.length,k:a}),table:{head:[r("账号"),r("改成")],rows:t.map(o=>[at(o.account),Qi(o.enabled)===!1?r("禁用"):r("启用")])},note:r("禁用会把账号移出转发队列;若这条线路没有别的可用账号,请求会直接失败。")}},run:async e=>{const t=el(),a=Iu(e.items),o=await Ig(),c=[];for(const d of a){const f=Qi(d.enabled);if(f===void 0)throw new Error(r("参数不完整(需要 account / enabled)"));const p=cw(o,at(d.account,128));await t.updateAccount?.(at(p.id),{enabled:f}),c.push(`${f?"启用":"禁用"} ${Yf(p)}`)}return Du(),{text:JSON.stringify({ok:!0,changed:c}),summary:r("已修改 {n} 个账号",{n:c.length})}}},tl=[A7,R7,O7,M7,D7,I7,P7,_7,L7];function dw(e){return tl.find(t=>t.id===e)}function z7(e){return tl.filter(t=>e[t.id]).map(t=>({type:"function",function:{name:t.id,description:t.desc,parameters:t.params}}))}const eM=[{id:"list_models",label:r("获取模型列表"),desc:r("读各提供商的模型清单、映射名与启用状态。")},{id:"list_account_balance",label:r("查询账号余额"),desc:r("读各账号的额度 / 剩余用量。")},{id:"set_model_enabled",label:r("启用 / 禁用模型"),desc:r("开关模型的对外可用性,不改其它属性。")},{id:"set_model_mapping",label:r("设置模型映射 ID"),desc:r("新增 / 删除映射名,支持批量加前缀与同名合并到多家。")},{id:"set_model_capability",label:r("修改模型能力"),desc:r("改上下文窗口 / 最大输出 Token / 工具调用等能力位。")},{id:"test_model",label:r("发起模型测试"),desc:r("对指定模型发一次真实请求,回报连通性与耗时。"),tag:"cost"},{id:"set_provider_order",label:r("调整提供商顺位"),desc:r("改某一家的整组顺位(先试哪一家)。")},{id:"set_account_order",label:r("调整账号优先级"),desc:r("改账号在全局队列里的名次,决定主备与切换顺序。")},{id:"set_account_enabled",label:r("启用 / 禁用账号"),desc:r("禁用会把账号移出转发队列,线路可能因此断供。"),tag:"danger"}],tM=12;function Xf(e,t){return window.wbIcons?.icon?.(e,t)||""}function B7(e){const t=window.wbMarkdown;return t?.render?t.render(e):e.replace(/[&<>]/g,a=>({"&":"&","<":"<",">":">"})[a]||a)}function H7({tone:e}){return e==="plain"?s.jsx("span",{className:"asst-tc-ico",dangerouslySetInnerHTML:{__html:Xf("spark",13)}}):s.jsx("span",{className:Ue("asst-tc-ico",e),children:e==="warn"?"!":"✕"})}function U7({item:e,onConfirm:t}){const a=dw(e.call.name),o=a?.label||e.call.name,c=iw(e.call.arguments),d=Object.keys(c).length?JSON.stringify(c,null,2):"";return s.jsxs("div",{className:Ue("asst-tool-card",e.state==="confirm"&&"confirm",e.state==="confirm"&&a?.kind==="run"&&"danger",e.state==="failed"&&"failed",e.state==="running"&&"running"),children:[s.jsxs("div",{className:"asst-tc-head",children:[e.state==="running"?s.jsx("span",{className:"asst-tc-ico",children:s.jsx("span",{className:"spin"})}):s.jsx(H7,{tone:e.state==="failed"?"bad":e.state==="confirm"?"warn":"plain"}),s.jsx("span",{className:"asst-tc-name",children:o}),e.state==="confirm"&&s.jsx("span",{className:"badge tag warn",children:r("待确认")}),e.state==="done"&&s.jsxs("span",{className:"asst-tc-state",children:["✓ ",e.summary||r("完成")]}),e.state==="failed"&&s.jsx("span",{className:"asst-tc-state bad",children:r("失败")}),e.state==="cancelled"&&s.jsx("span",{className:"asst-tc-state plain",children:r("已取消")})]}),e.state==="confirm"&&e.plan&&s.jsxs("div",{className:"asst-tc-plan",children:[e.plan.lead,e.plan.table&&s.jsxs("table",{className:"asst-mini-table",children:[s.jsx("thead",{children:s.jsx("tr",{children:e.plan.table.head.map((f,p)=>s.jsx("th",{children:f},p))})}),s.jsx("tbody",{children:e.plan.table.rows.slice(0,20).map((f,p)=>s.jsx("tr",{children:f.map((h,b)=>s.jsx("td",{className:b===f.length-1?"mono hl":"",children:h},b))},p))})]}),e.plan.table&&e.plan.table.rows.length>20&&s.jsx("div",{className:"hint",children:r("(仅显示前 20 条,共 {n} 条)",{n:e.plan.table.rows.length})}),e.plan.note&&s.jsx("div",{className:"hint",children:e.plan.note})]}),e.state==="failed"&&e.error&&s.jsx("div",{className:"asst-tc-error",children:e.error}),e.state==="done"&&e.detail&&s.jsxs("details",{children:[s.jsx("summary",{className:"asst-tc-result",style:{cursor:"pointer"},children:r("查看结果")}),s.jsx("pre",{className:"asst-tc-json",children:e.detail})]}),e.state!=="confirm"&&d&&s.jsxs("details",{children:[s.jsx("summary",{className:"asst-tc-result",style:{cursor:"pointer"},children:r("查看参数")}),s.jsx("pre",{className:"asst-tc-json",children:d})]}),e.state==="confirm"&&s.jsxs("div",{className:"asst-tc-foot",children:[s.jsx("span",{className:Ue("hint",a?.kind==="run"&&"danger"),children:a?.kind==="run"?r("这会真实发起上游请求并消耗额度"):r("确认后立即生效")}),s.jsx(ne,{size:"sm",variant:a?.kind==="run"?"destructive":"default",onClick:()=>t(!0),children:r("执行")}),s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>t(!1),children:r("取消")})]})]})}function V7(){const[e,t]=x.useState(null),[a,o]=x.useState([]),[c,d]=x.useState([]),[f,p]=x.useState(!1),[h,b]=x.useState(!1),[y,v]=x.useState(""),[j,w]=x.useState(""),[k,S]=x.useState(!1),N=x.useRef([]),R=x.useRef([]),P=x.useRef(null),T=x.useRef(null),C=x.useRef(null),E=x.useRef(!1),D=x.useRef(0),I=x.useRef(null),O=x.useRef(0),_=x.useCallback(()=>{d(N.current.slice())},[]);x.useEffect(()=>{const M=C.current;if(!M)return;M.scrollHeight-M.scrollTop-M.clientHeight<160&&(M.scrollTop=M.scrollHeight)},[c]);const z=x.useCallback(async()=>{if(!E.current){E.current=!0;try{const M=await ZO();t(M),S(!1),D.current=0}catch(M){S(!0),w(r("加载助手设置失败:{message}",{message:Dl(M)})),D.current<3&&(D.current+=1,E.current=!1,setTimeout(()=>{z()},4e3))}try{o(await YO())}catch(M){w(U=>U||r("读取模型清单失败:{message}",{message:Dl(M)}))}}},[]);x.useEffect(()=>{const M=window;return M.wbAssistant={activate:()=>{z()}},z(),()=>{delete M.wbAssistant}},[z]);const H=x.useMemo(()=>{const M={};for(const U of tl)M[U.id]=e?.tools?.[U.id]??!1;return M},[e]),B=x.useMemo(()=>z7(H),[H]),L=Object.values(H).filter(Boolean).length,F=e?.model??null,$=x.useCallback(async(M,U,Z)=>{for(let ae=U;ae{if(O.current>=tM){N.current.push({kind:"notice",text:r("这一轮来回已达 {n} 次上限,我先停下等你指示(可以换个说法,或拆成几步让我做)。",{n:tM}),bad:!0}),_();return}O.current+=1,p(!0),w("");const M=new AbortController;T.current=M;const U=N.current.push({kind:"bot",text:"",streaming:!0})-1;_();let Z=[],ae=!1;try{await E7({messages:R.current,tools:B,signal:M.signal,onEvent:ue=>{if(ue.type==="delta"){const ve=N.current[U];ve&&ve.kind==="bot"&&(N.current[U]={...ve,text:ve.text+ue.text},_())}ue.type==="toolCalls"&&(Z=ue.calls)}})}catch(ue){ae=!0;const ve=Dl(ue),ee=N.current[U],he=ee&&ee.kind==="bot"?ee.text:"";he?N.current[U]={kind:"bot",text:he}:N.current.splice(U,1);const te=M.signal.aborted;N.current.push({kind:"notice",text:te?r("已停止这次回答。"):r("请求失败:{message}",{message:ve}),bad:!te}),_()}finally{T.current=null}if(ae){p(!1);return}const ce=N.current[U];ce&&ce.kind==="bot"&&(N.current[U]={...ce,streaming:!1});const W=ce&&ce.kind==="bot"?ce.text:"";if(R.current.push({role:"assistant",content:W,toolCalls:Z.length?Z:void 0}),_(),!Z.length){p(!1);return}await $(Z,0,[])},[B,$,_]);I.current=X;const K=x.useCallback(async M=>{const U=P.current;if(!U)return;P.current=null,b(!1);const Z=U.calls[U.index],ae=dw(Z.name),ce=iw(Z.arguments);if(!M||!ae)N.current[U.cardIndex]={kind:"tool",call:Z,state:"cancelled"},U.collected.push({toolCallId:Z.id,content:"用户取消了这次操作,没有做任何改动。"}),_();else{N.current[U.cardIndex]={kind:"tool",call:Z,state:"running"},p(!0),_();try{const W=await ae.run(ce);N.current[U.cardIndex]={kind:"tool",call:Z,state:"done",summary:W.summary,detail:W.text},U.collected.push({toolCallId:Z.id,content:W.text})}catch(W){const ue=Dl(W);N.current[U.cardIndex]={kind:"tool",call:Z,state:"failed",error:ue},U.collected.push({toolCallId:Z.id,content:`工具执行失败:${ue}`})}_()}await $(U.calls,U.index+1,U.collected)},[$,_]),q=x.useCallback(async M=>{const U=M.trim();if(!(!U||f||h)){if(O.current=0,N.current.push({kind:"user",text:U}),R.current.push({role:"user",content:U}),v(""),_(),!e){N.current.push({kind:"notice",text:r("助手设置没读出来,现在还不能发消息 —— 看输入框下方的提示。"),bad:!0}),_();return}if(!e.model){N.current.push({kind:"notice",text:r("还没有选择对话模型:先在下方选一个(或去「设置 → AI 助手」里选)。"),bad:!0}),_();return}await X()}},[h,f,e,X,_]),Q=x.useCallback(()=>{T.current?.abort()},[]),G=x.useCallback(()=>{T.current?.abort(),P.current=null,N.current=[],R.current=[],b(!1),p(!1),w(""),_()},[_]),J=x.useCallback(async M=>{if(!M)return;if(!e){w(r("助手设置没读出来,暂时存不了对话模型 —— 看输入框下方的提示。"));return}const U={...e,model:M};t(U);try{await WO(U)}catch(Z){w(r("保存对话模型失败:{message}",{message:Dl(Z)}))}},[e]),Y=f||h,re=x.useRef(null);return s.jsxs("div",{className:"asst-layout",children:[s.jsxs("div",{className:"asst-top",children:[s.jsxs(dt,{value:F??"",onValueChange:M=>{J(String(M))},children:[s.jsx(pt,{className:"asst-model-pick","aria-label":r("对话模型"),children:s.jsx(ft,{children:F?s.jsxs("span",{className:"flex items-center gap-2",children:[s.jsx("span",{className:Ue("dot","ok")}),s.jsx("span",{className:"mono",children:F})]}):r("选择模型…")})}),s.jsxs(mt,{children:[a.length===0&&s.jsx($e,{value:"none",disabled:!0,children:r("没有可用的模型")}),a.map(M=>s.jsx($e,{value:M,children:M},M))]})]}),s.jsx("span",{className:"asst-top-hint",children:r("助手走本地网关,消耗所选账号的额度")}),s.jsx("span",{className:"spacer"}),s.jsx(ne,{variant:"ghost",size:"sm",onClick:G,disabled:f||h||!c.length,children:r("新对话")})]}),s.jsxs("div",{className:"asst-scroll",ref:C,children:[c.length===0&&s.jsxs("div",{className:"asst-empty",children:[s.jsx("div",{className:"empty-logo",dangerouslySetInnerHTML:{__html:Xf("spark",26)||""}}),s.jsx("h3",{children:r("AI 助手")}),s.jsxs("p",{children:[r("用一句话让我查或改本机的模型转发配置。"),s.jsx("br",{}),r("我会在动手前把改动列给你确认。")]}),s.jsx("div",{className:"asst-suggests",children:[r("看看哪些模型在多家重复了"),r("测一下当前最快的模型通不通"),r("CodeArts 的账号余额还剩多少?"),r("把重复的模型加上家名前缀区分开")].map(M=>s.jsxs("button",{type:"button",onClick:()=>{q(M)},children:["“",M,"”"]},M))}),e!==null&&L===0&&s.jsx("div",{className:"asst-empty-warn",children:r("当前一个工具都没勾选,助手只能纯聊天。去「设置 → AI 助手 → 工具」里勾上需要的工具。")}),k&&s.jsx("div",{className:"asst-empty-warn bad",children:j||r("助手设置读取失败,工具可能已过时。")})]}),c.map((M,U)=>M.kind==="user"?s.jsx("div",{className:"asst-msg user",children:s.jsx("div",{className:"bubble",children:M.text})},U):M.kind==="bot"?!M.text&&M.streaming?s.jsxs("div",{className:"asst-msg bot",children:[s.jsxs("div",{className:"who",children:[s.jsx("span",{className:"ico",dangerouslySetInnerHTML:{__html:Xf("spark",14)||""}})," ",r("助手")]}),s.jsx("div",{className:"body",children:s.jsx("span",{className:"spin"})})]},U):s.jsxs("div",{className:"asst-msg bot",children:[s.jsxs("div",{className:"who",children:[s.jsx("span",{className:"ico",dangerouslySetInnerHTML:{__html:Xf("spark",14)||""}})," ",r("助手")]}),s.jsxs("div",{className:"body",children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:B7(M.text)}}),M.streaming&&s.jsx("span",{className:"asst-caret"})]})]},U):M.kind==="notice"?s.jsx("div",{className:"asst-msg bot",children:s.jsx("div",{className:Ue("asst-empty-warn",M.bad&&"bad"),style:{margin:0},children:M.text})},U):s.jsx(U7,{item:M,onConfirm:Z=>{K(Z)}},U))]}),s.jsxs("div",{className:"asst-composer",children:[s.jsxs("div",{className:"asst-ta-wrap",children:[s.jsx(Mi,{ref:re,rows:1,value:y,placeholder:r(Y?"等这一轮跑完…":"直接说要改什么 / 查什么…(Enter 发送,Shift+Enter 换行)"),disabled:Y,onChange:M=>{v(M.currentTarget.value);const U=M.currentTarget;U.style.height="auto",U.style.height=`${Math.min(U.scrollHeight,132)}px`},onKeyDown:M=>{M.key==="Enter"&&!M.shiftKey&&!M.nativeEvent.isComposing&&(M.preventDefault(),q(y))}}),f?s.jsx("button",{type:"button",className:"asst-send stop",title:r("停止"),onClick:Q,children:"■"}):s.jsx("button",{type:"button",className:"asst-send",title:r("发送"),disabled:Y||!y.trim(),onClick:()=>{q(y)},children:"➤"})]}),s.jsxs("div",{className:"asst-composer-foot",children:[s.jsxs("span",{className:"tools-state",children:[s.jsx("span",{className:"ico",dangerouslySetInnerHTML:{__html:Xf("settings",12)||""}}),r("已注入 {n} / {total} 个工具 · 系统提示词:{state}",{n:L,total:tl.length,state:e?.systemPromptEnabled?r("开"):r("关")})]}),s.jsx("span",{className:"spacer"}),j?s.jsxs("span",{className:"hint",children:[j,k&&s.jsx("button",{type:"button",className:"asst-tc-more",onClick:()=>{z()},children:r("重试")})]}):F?s.jsx("span",{className:"hint",children:r("回复由 {model} 生成 · 走本地网关",{model:F})}):null]})]})]})}const nM='.page[data-page="assistant"]';let fw=null;function sM(){if(fw)return;const e=document.querySelector(nM);e&&(e.replaceChildren(),fw=jn.createRoot(e),fw.render(s.jsx(V7,{})))}document.querySelector(nM)?sM():document.addEventListener("DOMContentLoaded",sM,{once:!0}),KO().catch(()=>{});function F7(e,t){return window.wbIcons?.icon?.(e,t)||""}function $7({id:e,label:t,checked:a,disabled:o,onCheckedChange:c}){return s.jsxs("label",{className:"switch",children:[s.jsx(Zn,{id:e,checked:a,disabled:o,onCheckedChange:d=>c(d)}),s.jsx("span",{children:t})]})}function q7(){const[e,t]=x.useState(null),[a,o]=x.useState([]),[c,d]=x.useState(""),[f,p]=x.useState(!1),[h,b]=x.useState(!1),[y,v]=x.useState(!1),[j,w]=x.useState("");x.useEffect(()=>{let C=!0;return(async()=>{try{const E=await ZO();if(!C)return;t(E)}catch(E){if(!C)return;p(!0),d(r("加载助手设置失败:{message}",{message:Dl(E)}))}try{const E=await YO();if(!C)return;o(E)}catch(E){if(!C)return;d(D=>D||r("读取模型清单失败:{message}",{message:Dl(E)}))}})(),()=>{C=!1}},[]);const k=x.useCallback(async(C,E)=>{t(C),b(!0);try{const D=await WO(C);t(D),p(!1),d(E||r("已保存"))}catch(D){p(!0),d(r("保存失败:{message}",{message:Dl(D)}))}finally{b(!1)}},[]),S=e!==null,N=x.useMemo(()=>{const C={};for(const E of tl)C[E.id]=e?.tools?.[E.id]??!1;return C},[e]),R=Object.values(N).filter(Boolean).length,P=!!e?.systemPrompt?.trim(),T=(C,E)=>{if(!e)return;const D=eM.find(O=>O.id===C)?.label||C,I={...e,tools:{...e.tools,[C]:E}};k(I,E?r("已勾选「{label}」",{label:D}):r("已取消「{label}」",{label:D}))};return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("对话模型")}),s.jsx("span",{className:"panel-sub",children:r("助手自己用哪个模型生成回复")})]}),s.jsx("div",{className:"panel-body",children:s.jsxs("div",{className:"asst-row",children:[s.jsx("label",{children:r("模型")}),s.jsxs(dt,{value:e?.model??"",disabled:!S||h,onValueChange:C=>{if(!e)return;const E=String(C);E&&k({...e,model:E},r("对话模型已切换"))},children:[s.jsx(pt,{className:"asst-model-pick","aria-label":r("对话模型"),children:s.jsx(ft,{children:e?.model??r("选择模型…")})}),s.jsxs(mt,{children:[a.length===0&&s.jsx($e,{value:"none",disabled:!0,children:r("没有可用的模型")}),a.map(C=>s.jsx($e,{value:C,children:C},C))]})]}),s.jsx("span",{className:"hint",children:r("列表 = 模型管理页里所有已启用的模型。助手走本地网关发起对话,消耗所选账号的额度。")})]})})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("系统提示词")}),s.jsx("span",{className:"panel-sub",children:r("作为 system 消息注入给助手")})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"asst-row",children:[s.jsx($7,{id:"settings-assistant-prompt",label:r("注入系统提示词"),checked:e?.systemPromptEnabled!==!1,disabled:!S||h,onCheckedChange:C=>{e&&k({...e,systemPromptEnabled:C},r(C?"系统提示词已开启":"系统提示词已关闭"))}}),s.jsxs(ne,{variant:"outline",size:"sm",disabled:!S,onClick:()=>{w(e?.systemPrompt?.trim()?e.systemPrompt:lw),v(!0)},children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:F7("settings",13)||""}}),r("编辑")]}),s.jsx("span",{className:"hint",children:r("点「编辑」弹窗改内容;开关关掉就整段不发。")})]}),s.jsx("div",{className:"settings-state",children:e?.systemPromptEnabled===!1?r("当前:已关闭(助手不收到任何系统提示词,工具定义照发)"):P?r("当前:已开启 · 自定义内容 {n} 字",{n:e?.systemPrompt.trim().length??0}):r("当前:已开启 · 使用内置默认提示词(还没自定义)")}),s.jsxs("div",{className:"asst-matrix",children:[s.jsx("div",{className:"mt-title",children:r("四种组合的实际效果")}),s.jsxs("table",{className:"asst-mini-table",children:[s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{children:r("提示词开关")}),s.jsx("th",{children:r("已勾选工具")}),s.jsx("th",{children:r("实际注入")})]})}),s.jsxs("tbody",{children:[s.jsxs("tr",{children:[s.jsx("td",{children:r("开")}),s.jsx("td",{children:r("有")}),s.jsx("td",{children:r("系统提示词 + 工具定义")})]}),s.jsxs("tr",{children:[s.jsx("td",{children:r("开")}),s.jsx("td",{children:s.jsx("b",{children:r("无")})}),s.jsx("td",{children:s.jsx("b",{children:r("都不注入(助手退化为纯聊天)")})})]}),s.jsxs("tr",{children:[s.jsx("td",{children:r("关")}),s.jsx("td",{children:r("有")}),s.jsx("td",{children:r("只注入工具定义")})]}),s.jsxs("tr",{children:[s.jsx("td",{children:r("关")}),s.jsx("td",{children:r("无")}),s.jsx("td",{children:r("都不注入")})]})]})]}),s.jsx("p",{className:"hint",children:r("「工具全不勾选 → 不注入系统提示词」:想当纯聊天用时,不必再去关上面的开关。")})]})]})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("工具")}),s.jsx("span",{className:"panel-sub",children:r("勾选即注入该工具;不勾选 = 助手看不到它")})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"asst-tools-bar",children:[s.jsx("span",{className:"badge brand",children:r("已勾选 {n} / {total}",{n:R,total:tl.length})}),s.jsx("span",{className:"spacer"}),s.jsx(ne,{variant:"ghost",size:"sm",disabled:!S||h,onClick:()=>{if(!e)return;const C={};for(const E of tl)C[E.id]=!1;k({...e,tools:C},r("已全部取消勾选"))},children:r("全不选")}),s.jsx(ne,{variant:"ghost",size:"sm",disabled:!S||h,onClick:()=>{if(!e)return;const C={};for(const E of tl)C[E.id]=E.kind==="read";for(const E of["set_model_enabled","set_model_mapping","set_model_capability","test_model"])C[E]=!0;k({...e,tools:C},r("已恢复推荐勾选"))},children:r("恢复推荐")})]}),["read","write"].map(C=>s.jsxs(x.Fragment,{children:[s.jsx("div",{className:"asst-tool-group",children:C==="read"?s.jsxs(s.Fragment,{children:[r("只读工具")," ",s.jsx("span",{className:"muted",children:r("· 不会改动任何配置")})]}):s.jsxs(s.Fragment,{children:[r("改动类工具")," ",s.jsx("span",{className:"muted",children:r("· 每次执行前列改动清单,等你确认")})]})}),eM.filter(E=>{const I=tl.find(O=>O.id===E.id)?.kind==="read";return C==="read"?I:!I}).map(E=>{const D=tl.find(O=>O.id===E.id),I=N[E.id]===!0;return s.jsxs("label",{className:"asst-tool",children:[s.jsx("input",{type:"checkbox",checked:I,disabled:!S||h,onChange:O=>T(E.id,O.currentTarget.checked)}),s.jsxs("span",{className:"tt",children:[s.jsxs("span",{className:"tt-name",children:[E.label,D?.kind==="read"&&s.jsx("span",{className:"badge tag plain",children:r("只读")}),E.tag==="cost"&&s.jsx("span",{className:"badge tag",children:r("消耗额度")}),E.tag==="danger"&&s.jsx("span",{className:"badge tag bad",children:r("高危")}),D?.kind==="write"&&!E.tag&&s.jsx("span",{className:"badge tag warn",children:r("影响转发")})]}),s.jsx("span",{className:"tt-desc",children:E.desc})]})]},E.id)})]},C)),s.jsx("div",{className:Ue("settings-state",f&&"text-destructive"),children:c})]})]}),s.jsx(Yt,{open:y,onOpenChange:C=>{C||v(!1)},children:s.jsxs(Xt,{className:"w-[min(680px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("编辑系统提示词")})}),s.jsxs(Lt,{children:[s.jsx(dn,{children:s.jsx("p",{children:r("这段文本作为 system 消息排在对话最前面。工具的定义与当前配置概览由网关自动附加,不用写在这里。")})}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"assistant-system-prompt",children:r("提示词正文")}),s.jsx(Mi,{id:"assistant-system-prompt",rows:14,className:"asst-prompt-ta min-h-[300px]",spellCheck:!1,value:j,onChange:C=>w(C.currentTarget.value)}),s.jsx("div",{className:"hint",children:r("清空 = 回到内置默认(与「恢复默认」等价)。")})]})]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",className:"mr-auto",onClick:()=>w(lw),children:r("恢复默认")}),s.jsx(ne,{variant:"outline",onClick:()=>v(!1),children:r("取消")}),s.jsx(ne,{variant:"default",onClick:()=>{if(!e)return;const C=j.trim()===lw.trim()?"":j;k({...e,systemPrompt:C},r("系统提示词已保存")),v(!1)},children:r("保存")})]})]})})]})}function zr(){return Pe().workbuddyDesktop??{}}function rM(){return window}const aM="workbuddy-desktop-checkin-tab",G7=["center","schedule","records"];function K7(){try{const e=localStorage.getItem(aM);return G7.includes(e)?e:"center"}catch{return"center"}}function lM(e){if(e!==bs.tab){try{localStorage.setItem(aM,e)}catch{}sr({tab:e})}}async function Pg(e){lM(e),bs.loaded||await Il()}let bs={version:0,tab:K7(),snapshot:null,loaded:!1,loadError:"",expanded:new Set,runningAll:!1,autoSaving:!1,autoTimeDraft:null,keepaliveSaving:!1,keepaliveDraft:null,signing:new Set,onboarding:new Map,growth:new Map};const pw=new Set;function Y7(){for(const e of pw)e()}function sr(e){bs={...bs,...e,version:bs.version+1},Y7()}function fr(){return bs}function oM(e){return pw.add(e),()=>pw.delete(e)}function X7(e){const t=typeof e?.key=="string"?e.key:"";return t?{key:t,title:typeof e.title=="string"&&e.title?e.title:t,group:typeof e.group=="string"&&e.group?e.group:"",points:Number(e.points)||0,done:e.done===!0,blocked:e.blocked===!0}:null}function mw(e){return(Array.isArray(e)?e:[]).map(X7).filter(a=>a!==null)}function ps(e){return Number(e)||0}async function Il(){try{const e=await zr().getCheckinCenter?.();if(!e)throw new Error(r("后端未返回签到中心数据"));sr({snapshot:e,loaded:!0,loadError:"",autoTimeDraft:null,keepaliveDraft:null}),Q7(e.extras?.onboarding??[])}catch(e){sr({loaded:!0,loadError:ut(e)})}}function Q7(e){for(const t of e){const a=t.settled;if(!a||typeof a!="object")continue;const o=bs.onboarding.get(t.id);if(o?.status==="loaded"&&o.unclaimed>0)continue;const c=mw(a.tasks),d=ps(a.at);Io(t.id,{status:"loaded",error:void 0,checkedAt:void 0,settled:!0,settledAt:d>0?d:void 0,tasks:c,unclaimed:0,earned:ps(a.earned),total:ps(a.total)})}}function iM(e){const t=new Set(bs.expanded);t.has(e)?t.delete(e):t.add(e),sr({expanded:t})}function hw(e){const t=`onb:${e}`,a=new Set(bs.expanded);a.has(t)?a.delete(t):a.add(t),sr({expanded:a})}function cM(e){return bs.expanded.has(`onb:${e}`)}async function Z7(){if(!bs.runningAll){sr({runningAll:!0});try{const e=await zr().runAutoCheckinNow?.();if(e){const t=ps(e.succeeded),a=ps(e.active),o=ps(e.total),c=ps(e.failedCount),d=a>0?r(",日活保活 {n} 个",{n:a}):"";c>0?_e(r("签到完成:{succeeded}/{total} 成功{active},{failed} 个失败",{succeeded:t,total:o,active:d,failed:c}),"err"):_e(r("✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}",{succeeded:t,total:o,active:d})),rM().wbAccountsView?.refreshUsageAfterCheckin?.(null)}}catch(e){_e(r("签到失败:{error}",{error:ut(e)}),"err")}finally{sr({runningAll:!1}),await Il(),uM(fr().snapshot?.extras.onboarding??[]),Pe().wbApp?.refresh?.()}}}async function _g(e,t="checkin"){const a=`${e}:${t}`;if(bs.signing.has(a))return;const o=new Set(bs.signing);o.add(a),sr({signing:o});try{let c;t==="checkin"?c=(await zr().checkinAllAccounts?.(e))?.results?.[0]:c=await zr().runCheckinActivity?.(e,t)??void 0;const d=c?.claim,f=c?.activity,p=f?.report?.succeeded===!0,h=f?.webConversation?.succeeded===!0;c?.error?_e(r("签到失败:{error}",{error:String(c.error)}),"err"):t==="keepalive"?f?.pokeSucceeded===!0||h||p?_e(r("✅ {message}",{message:d?.msg||r("活跃保活完成")})):_e(d?.msg||r("活跃保活失败"),"err"):d?.success===!0?_e(r("✅ {message}",{message:d.msg||r("签到成功")})):d?.alreadyCompleted===!0?_e(d?.msg||r("今日已领取"),"err"):p?_e(r("✅ {message}",{message:d?.msg||r("活跃上报完成,但活动未开启")})):f?.pokeSucceeded===!0||h?_e(r("✅ {message}",{message:d?.msg||r("活跃保活完成,但活动未开启")})):_e(d?.msg||r("未领取"),"err"),rM().wbAccountsView?.refreshUsageAfterCheckin?.(e)}catch(c){_e(r("签到失败:{error}",{error:ut(c)}),"err")}finally{const c=new Set(fr().signing);c.delete(a),sr({signing:c}),await Il();const d=(fr().snapshot?.extras.onboarding??[]).filter(f=>f.id===e);uM(d),Pe().wbApp?.refresh?.()}}function Lg(e){sr({keepaliveDraft:e.map(t=>t.trim()).filter(Boolean)})}async function W7(e){const t=e.map(a=>a.trim()).filter(Boolean);if(!fr().keepaliveSaving){sr({keepaliveSaving:!0});try{const a=await zr().saveCheckinKeepalive?.(t);if(a){const o=fr().snapshot;sr({snapshot:o&&{...o,keepalive:a},keepaliveDraft:null}),_e(r("已保存:保活模型链"))}}catch(a){_e(r("保存失败:{error}",{error:ut(a)}),"err")}finally{sr({keepaliveSaving:!1})}}}async function uM(e){for(const t of e)J7(t.id)||await gw(t.id);for(const t of e){const a=fr().onboarding.get(t.id);a?.status!=="loaded"||a.claiming||a.settled||(t.provider==="officeace"||a.unclaimed>0)&&await dM(t.id)}}function J7(e){return bs.onboarding.get(e)?.settled===!0}function Pu(e){return bs.onboarding.get(e)??{status:"idle",tasks:[],unclaimed:0,earned:0,total:0,claiming:!1}}function Io(e,t){const a=new Map(bs.onboarding);a.set(e,{...Pu(e),...t}),sr({onboarding:a})}async function gw(e,t){const a=Pu(e);if(!(a.status==="loading"||a.claiming)){Io(e,{status:"loading",error:void 0,settled:!1});try{const o=await zr().getOnboardingTasks?.(e,t?.refresh===!0),c=mw(o?.tasks),d=o?.settled===!0;Io(e,{status:"loaded",checkedAt:Date.now(),tasks:c,unclaimed:c.filter(f=>!f.done&&!f.blocked).length,earned:ps(o?.earned),total:ps(o?.total),settled:d,settledAt:d&&ps(o?.settledAt)||void 0}),t?.expand===!0&&c.length>0&&!cM(e)&&hw(e)}catch(o){Io(e,{status:"error",error:ut(o),settled:!1})}}}async function dM(e){const t=Pu(e);if(!(t.claiming||t.status!=="loaded")){Io(e,{claiming:!0});try{Io(e,{tasks:Pu(e).tasks.map(v=>v.done?v:{...v,claiming:!0,error:void 0})});const a=await zr().claimOnboardingTasks?.(e),o=new Map,c=Array.isArray(a?.results)?a.results:[];for(const v of c){const j=typeof v?.key=="string"?v.key:"";j&&v?.ok!==!0&&o.set(j,String(v?.error||r("领取失败")))}const d=mw(a?.tasks),f=(d.length?d:Pu(e).tasks).map(v=>({...v,claiming:!1,error:o.get(v.key)})),p=f.filter(v=>v.done&&!o.has(v.key)).length,h=a?.settled===!0;Io(e,{claiming:!1,checkedAt:Date.now(),tasks:f,unclaimed:f.filter(v=>!v.done&&!v.blocked).length,earned:ps(a?.earned),total:ps(a?.total),settled:h,settledAt:h&&ps(a?.settledAt)||void 0});const b=f.filter(v=>v.error&&!v.done).length,y=typeof a?.message=="string"?a.message.trim():"";b?_e(r("新手福利有 {n} 项领取失败,可重试",{n:b}),"err"):y?_e(y,"ok"):p&&_e(r("✅ 新手福利领取完成,累计 {n} 积分",{n:ps(a?.earned)}))}catch(a){const o=ut(a);Io(e,{claiming:!1,tasks:Pu(e).tasks.map(c=>({...c,claiming:!1,error:c.done?void 0:o}))}),_e(r("领取失败:{error}",{error:o}),"err")}finally{await Il()}}}function fM(e){return(Array.isArray(e)?e:[]).map(a=>{const o=a??{},c=typeof o.code=="string"?o.code:"";return c?{code:c,title:typeof o.title=="string"&&o.title?o.title:c,description:typeof o.description=="string"?o.description:"",status:typeof o.status=="string"?o.status:"",current:ps(o.current),target:ps(o.target),locked:o.locked===!0,unlockAt:o.unlockAt,supported:o.supported===!0,unforgeable:o.unforgeable===!0,unforgeableReason:typeof o.unforgeableReason=="string"?o.unforgeableReason:"",kind:typeof o.kind=="string"?o.kind:"",source:typeof o.source=="string"?o.source:""}:null}).filter(a=>a!==null)}function pM(e){return(Array.isArray(e)?e:[]).map(a=>{const o=a??{},c=typeof o.code=="string"?o.code:"";return c?{code:c,outcome:typeof o.outcome=="string"?o.outcome:"failed",message:typeof o.message=="string"?o.message:"",credit:ps(o.credit),energy:ps(o.energy)}:null}).filter(a=>a!==null)}function Zi(e){return bs.growth.get(e)??{status:"idle",energy:null,streak:null,tasks:[],travel:null,school:null,running:!1,runningSchool:!1,runningTravel:!1}}function Br(e,t){const a=new Map(bs.growth);a.set(e,{...Zi(e),...t}),sr({growth:a})}function e9(e){return bs.expanded.has(`growth:${e}`)}function mM(e){const t=`growth:${e}`,a=new Set(bs.expanded);a.has(t)?a.delete(t):a.add(t),sr({expanded:a})}async function zg(e){const t=Zi(e);if(!(t.status==="loading"||t.running)){Br(e,{status:"loading",error:void 0});try{const a=await zr().getGrowthStatus?.(e),o=a?.tasks??{},c=a?.travel??null,d=a?.school??null;Br(e,{status:"loaded",checkedAt:Date.now(),energy:a?.energy===null||a?.energy===void 0?null:ps(a.energy),streak:a?.streak===null||a?.streak===void 0?null:ps(a.streak),tasks:fM(o.tasks),travel:c,school:d?{...d,tasks:fM(d.tasks)}:null,error:typeof o.error=="string"?o.error:void 0})}catch(a){Br(e,{status:"error",error:ut(a)})}}}async function hM(e,t){const a=Zi(e);if(a.running)return;const o=(a.tasks??[]).filter(h=>!h.supported||h.unforgeable===!0||h.locked===!0?!1:t==="claim"?h.status==="completed"||h.current>=h.target&&h.status!=="claimed":h.status!=="claimed");if(o.length===0){_e(r("没有需要执行的任务"));return}Br(e,{running:!0,results:[],error:void 0});let c=0,d=0,f=0,p=0;for(const h of o)try{const b=await zr().runGrowthTask?.(e,h.code,t),y=pM([b])[0];y&&(Br(e,{results:[...Zi(e).results??[],y]}),c+=y.credit??0,d+=y.energy??0,(y.outcome==="done"||y.outcome==="already")&&(f+=1),y.outcome==="failed"&&(p+=1))}catch(b){p+=1,Br(e,{results:[...Zi(e).results??[],{code:h.code,outcome:"failed",message:ut(b),credit:0,energy:0}]})}Br(e,{running:!1}),p>0?_e(r("成长任务完成({done} 项成功、{failed} 项失败),积分 +{credit} 能量 +{energy}",{done:f,failed:p,credit:c,energy:d}),"err"):_e(r("✅ 成长任务执行完成:积分 +{credit} 能量 +{energy}",{credit:c,energy:d})),await zg(e)}async function t9(e,t){if(!Zi(e).runningSchool){Br(e,{runningSchool:!0,error:void 0});try{const o=await zr().runGrowthSchool?.(e,t),c=pM(o?.results),d=o?.lottery??null;Br(e,{runningSchool:!1,results:c,schoolText:c.length?c.map(f=>`${f.code}:${f.message}`).join(";"):void 0,lotteryText:d?String(d.message??r("已抽 {n} 次",{n:ps(d.drawn)})):void 0,checkedAt:Date.now()}),_e(d?r("开学季执行完成:{message}",{message:String(d.message??"")}):r("✅ 开学季任务执行完成")),await zg(e)}catch(o){Br(e,{runningSchool:!1,error:ut(o)}),_e(r("开学季执行失败:{error}",{error:ut(o)}),"err")}}}async function n9(e){if(!Zi(e).runningTravel){Br(e,{runningTravel:!0,error:void 0});try{const a=await zr().runGrowthTravel?.(e),o=String(a?.message??""),c=String(a?.outcome??"");Br(e,{runningTravel:!1,checkedAt:Date.now()}),c==="failed"?_e(r("猫猫旅行失败:{message}",{message:o}),"err"):_e(r("猫猫旅行:{message}",{message:o})),await zg(e)}catch(a){Br(e,{runningTravel:!1,error:ut(a)}),_e(r("猫猫旅行失败:{error}",{error:ut(a)}),"err")}}}function s9(e){return e.totalCount?e.doneCount>=e.totalCount?"done":e.doneCount>0?"part":"todo":"none"}function r9(e){const a=(Array.isArray(e?.schedules)?e.schedules:[]).filter(o=>o.enabled===!0).map(o=>Number(o.nextRunAt)).filter(o=>Number.isFinite(o)&&o>0);return a.length?Math.min(...a):null}let Pl={version:0,data:null,loaded:!1,loadError:"",saving:!1,runningId:null,editingId:null};const xw=new Set;function a9(){for(const e of xw)e()}function pr(e){Pl={...Pl,...e,version:Pl.version+1},a9()}function gM(){return Pl}function l9(e){return xw.add(e),()=>xw.delete(e)}function Wi(){return Pe().workbuddyDesktop??{}}async function xM(){try{const e=await Wi().getCheckinSchedules?.();if(!e)throw new Error(r("后端未返回定时签到数据"));pr({data:e,loaded:!0,loadError:""})}catch(e){pr({loaded:!0,loadError:ut(e)})}}function Qf(e){e&&pr({data:e,loadError:""}),Il()}async function o9(e){if(!Pl.saving){pr({saving:!0});try{const t=await Wi().saveAutoCheckin?.({enabled:e});Qf(t),_e(r(e?"✅ 定时签到已开启":"定时签到已关闭"))}catch(t){_e(r("保存失败:{error}",{error:ut(t)}),"err")}finally{pr({saving:!1})}}}async function bM(e){if(!Pl.saving){pr({saving:!0});try{const t=await Wi().saveCheckinSchedule?.(e);Qf(t),pr({editingId:null}),_e(r("已保存:定时条目"))}catch(t){_e(r("保存失败:{error}",{error:ut(t)}),"err")}finally{pr({saving:!1})}}}async function i9(e,t){await bM({id:e.id,label:e.label??"",enabled:t,time:e.time??"",jitterMinutes:Number(e.jitterMinutes)||0,providers:Array.isArray(e.providers)?e.providers:[]})}async function c9(e){if(!Pl.saving){pr({saving:!0});try{const t=await Wi().saveAutoCheckin?.({startupCatchUp:e});Qf(t),_e(r(e?"启动补签已开启":"启动补签已关闭"))}catch(t){_e(r("保存失败:{error}",{error:ut(t)}),"err")}finally{pr({saving:!1})}}}async function u9(e){if(!Pl.saving){pr({saving:!0});try{await Wi().deleteCheckinSchedule?.(e),Qf(await Wi().getCheckinSchedules?.()),_e(r("已删除定时条目"))}catch(t){_e(r("删除失败:{error}",{error:ut(t)}),"err")}finally{pr({saving:!1})}}}async function d9(e){if(!Pl.runningId){pr({runningId:e});try{const t=await Wi().runCheckinSchedule?.(e)??void 0,a=o=>Number(o)||0;if(t){const o=a(t.succeeded),c=a(t.active),d=a(t.total),f=a(t.failedCount),p=c>0?r(",日活保活 {n} 个",{n:c}):"";f>0?_e(r("签到完成:{succeeded}/{total} 成功{active},{failed} 个失败",{succeeded:o,total:d,active:p,failed:f}),"err"):_e(r("✅ 签到完成:{succeeded}/{total} 个账号成功领取{active}",{succeeded:o,total:d,active:p})),Qf(t)}}catch(t){_e(r("执行失败:{error}",{error:ut(t)}),"err")}finally{pr({runningId:null}),await Il()}}}function bw(e){pr({editingId:e})}const f9=r("到点后自动签到勾选提供商的可用账号(WorkBuddy 国内版走每日签到接口,国际版走每日活跃任务:探测活动、领日活奖励、再用免费模型保活并在网页通道建会话点亮日活;小浣熊走桌面端每日积分链路;AutoClaw 走官方客户端的每日签到任务;Qoder 中国版走活动领取,没被下发活动的账号会得到中性提示;Qoder 国际版要先带设备风控身份(本机 Qoder 客户端 / qodercli 的 UMID 组件生成)才能看到「每日 100 Credits」活动,缺组件时会得到明确的说明而不是报错;Trae 领 SOLO 的每日签到积分(按自然日 0 点重置),上游没对该账号开活动、或凭据里没有设备号时得到的是「未领取 + 具体原因」而不是报错;Loomy 每天替账号打一次首次登录积分;KukuAI 领「免费领积分」的每日任务;CodeArts 领当日的运营福利(领取 → 确认 → 回读核实,自动执行受每天 6 次 / 间隔 10 分钟的写请求限流);OfficeAce 果办一次领当天全部奖励(每日签到 + 新人礼))。设了「随机前后 N 分钟」时,本轮账号在各自窗口内分散执行(窗口夹在当天 0 点到 23:59 之间),不再全部挤在同一分钟;窗口已过则立即全部执行。错过时点开机后会自动补签,不会因为当时没开机而漏掉(可在「启动补签」关掉,改为等到窗口起点)。各家签到接口都是幂等的,重复执行不会重复领取。");function p9(){const[e,t]=x.useState(gM());return x.useEffect(()=>l9(()=>t(gM())),[]),e}function m9(){const[e,t]=x.useState(fr());return x.useEffect(()=>oM(()=>t(fr())),[]),e}function vM(e,t){const a=Array.isArray(e.providers)?e.providers:[];return t.filter(o=>a.includes(o.id)).map(o=>o.label)}function yM(e,t){const a=vM(e,t);return a.length?t.length>0&&a.length>=t.length?r("全部 {n} 家",{n:t.length}):a.join(r("、")):r("未勾选提供商")}function h9(e,t){const a=vM(e,t);return a.length?a.join(r("、")):r("未勾选提供商")}function g9(e){const t=e.lastResult;if(!t)return r("还没执行过");const a=f=>Number(f)||0,o=[r("成功 {n}",{n:a(t.succeeded)})],c=a(t.active);c>0&&o.push(r("保活 {n}",{n:c}));const d=a(t.failedCount);return d>0&&o.push(r("失败 {n}",{n:d})),`${t.at?Ls(t.at):"—"}${t.reason?` · ${t.reason}`:""} —— ${o.join(r(" · "))}`}function jM({entry:e,store:t}){const a=Array.isArray(t.data?.providerOptions)?t.data.providerOptions:[],o=e===null,[c,d]=x.useState(e?.label??""),[f,p]=x.useState(e?.time??"00:01"),[h,b]=x.useState(String(e?.jitterMinutes??0)),[y,v]=x.useState(new Set(o?a.map(T=>T.id):e?.providers??[]));x.useEffect(()=>{o&&a.length>0&&v(new Set(a.map(T=>T.id)))},[]);const j=h.trim(),w=j===""?0:Number(j),k=(j===""||/^\d+$/.test(j))&&Number.isInteger(w)&&w>=0&&w<=120,S=f.trim()!==""&&y.size>0&&k,N=()=>v(new Set(a.map(T=>T.id))),R=()=>v(new Set),P=async()=>{S&&await bM({id:e?.id,label:c.trim(),enabled:e?.enabled??!0,time:f.trim(),jitterMinutes:w,providers:a.map(T=>T.id).filter(T=>y.has(T))})};return s.jsxs("div",{className:"ck-sched-editor",children:[s.jsxs("div",{className:"ck-set-line",children:[s.jsx("span",{className:"ck-set-k",children:r("名称")}),s.jsx("span",{className:"ck-set-v",children:s.jsx(Fe,{type:"text",className:"max-w-[220px]",placeholder:r("可选 · 缺省显示时刻"),value:c,disabled:t.saving,onChange:T=>d(T.currentTarget.value)})})]}),s.jsxs("div",{className:"ck-set-line",children:[s.jsx("span",{className:"ck-set-k",children:r("每天时刻")}),s.jsxs("span",{className:"ck-set-v flex items-center gap-2",children:[s.jsx(Fe,{type:"time",className:"w-[96px] max-w-[96px] font-mono tabular-nums",value:f,disabled:t.saving,onChange:T=>p(T.currentTarget.value)}),s.jsx("span",{className:"text-subtle text-xs",children:r("北京时间 · 错过时点开机后会自动补签")})]})]}),s.jsxs("div",{className:"ck-set-line",children:[s.jsx("span",{className:"ck-set-k",children:r("随机前后")}),s.jsxs("span",{className:"ck-set-v flex items-center gap-2",children:[s.jsx(Fe,{type:"number",min:0,max:120,step:1,inputMode:"numeric",className:"w-[96px] max-w-[96px] text-center font-mono tabular-nums",value:h,disabled:t.saving,onChange:T=>b(T.currentTarget.value)}),s.jsx("span",{className:"text-subtle text-xs",children:r("分钟 · 窗口内逐个账号随机执行,0 = 到点立即执行")})]})]}),s.jsxs("div",{className:"ck-set-line ck-set-line-top",children:[s.jsx("span",{className:"ck-set-k",children:r("签到范围")}),s.jsxs("span",{className:"ck-set-v",children:[s.jsxs("div",{className:"ck-mini-row",children:[s.jsx("span",{className:"ck-mini-note",children:r("到点时逐个签到,已勾 {n} / {total} 家",{n:y.size,total:a.length})}),s.jsx("button",{type:"button",className:"ck-mini-btn",disabled:t.saving,onClick:N,children:r("全选")}),s.jsx("button",{type:"button",className:"ck-mini-btn",disabled:t.saving||y.size===0,onClick:R,children:r("清空")})]}),s.jsx("div",{className:"ck-range",children:a.map(T=>s.jsxs("label",{className:"ck-range-item",children:[s.jsx(_r,{checked:y.has(T.id),disabled:t.saving,onCheckedChange:C=>{const E=new Set(y);C===!0?E.add(T.id):E.delete(T.id),v(E)}}),s.jsx("span",{className:"ck-range-name",title:T.label,children:T.label})]},T.id))}),y.size===0?s.jsx("div",{className:"ck-mini-warn",children:r("至少勾一家才能保存(不勾等于这条条目不签到)")}):null]})]}),s.jsxs("div",{className:"ck-sched-actions",children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:t.saving,onClick:()=>bw(null),children:r("取消")}),s.jsx(ne,{size:"sm",variant:"default",disabled:!S||t.saving,onClick:()=>{P()},children:t.saving?r("保存中…"):r("保存")})]})]})}function x9({store:e}){return s.jsxs("div",{className:"ck-sched-row open ck-sched-row-new",children:[s.jsxs("div",{className:"ck-sched-main",children:[s.jsx("span",{className:"ck-new-dot","aria-hidden":!0,children:"+"}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:r("新建定时条目")}),s.jsx("div",{className:"ck-prov-desc",children:r("填好时刻与签到范围后点「保存」;名称可以留空(界面显示时刻)")})]})]}),s.jsx(jM,{entry:null,store:e})]})}function b9({entry:e,store:t}){const a=Array.isArray(t.data?.providerOptions)?t.data.providerOptions:[],o=t.editingId===e.id,c=t.runningId===e.id,d=t.data?.enabled===!0,f=Number(e.nextRunAt),p=async()=>{const h=Pe().wbConfirm?.ask;if(!h)return;const y=(e.displayLabel||e.time||e.id).replace(/&/g,"&").replace(//g,">");await h({title:r("删除定时条目"),html:r("确定删除「{name}」?删除后到点不再执行。",{name:y}),okText:r("删除"),okClass:"danger"})&&await u9(e.id)};return s.jsxs("div",{className:o?"ck-sched-row open":"ck-sched-row",children:[s.jsxs("div",{className:"ck-sched-main",children:[s.jsx(Zn,{checked:e.enabled===!0,disabled:t.saving,onCheckedChange:h=>{i9(e,h===!0)}}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsxs("div",{className:"ck-prov-name",children:[e.displayLabel||e.time||e.id,e.enabled===!0?null:s.jsx(ze,{variant:"outline",shape:"tag",children:r("已停用")})]}),s.jsx("div",{className:"ck-prov-desc ck-sched-scope",title:h9(e,a),children:Number(e.jitterMinutes)>0?r("每天 {time} · 随机前后 {n} 分钟 · {scope}",{time:e.time??"—",n:Number(e.jitterMinutes),scope:yM(e,a)}):r("每天 {time} · {scope}",{time:e.time??"—",scope:yM(e,a)})}),s.jsx("div",{className:"ck-prov-desc",children:r("上次执行:{line}",{line:g9(e)})})]}),s.jsxs("div",{className:"ck-prov-right",children:[s.jsx("span",{className:"ck-sched-next",children:d&&e.enabled===!0&&Number.isFinite(f)&&f>0?r("下次 {date}",{date:Ls(f)}):"—"}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:c||t.runningId!==null,onClick:()=>{d9(e.id)},children:r(c?"执行中…":"立即执行")}),s.jsx(ne,{size:"sm",variant:"ghost",onClick:()=>bw(o?null:e.id),children:r(o?"收起":"编辑")}),s.jsx(ne,{size:"sm",variant:"ghost",className:"text-destructive",disabled:t.saving,onClick:()=>{p()},children:r("删除")})]})]}),o?s.jsx(jM,{entry:e,store:t}):null]})}function v9(e,t){return e.length===t.length&&e.every((a,o)=>a===t[o])}let Zf=null;function y9(e,t){for(let a=0;ah!==t.row),d=y9(c,e.clientY);if(d===t.from)return;const f=[...t.list],[p]=f.splice(t.from,1);f.splice(d,0,p),t.list=f,t.from=d,t.onChange(f)}function Wf(){const e=Zf;Zf=null,window.removeEventListener("pointermove",wM),window.removeEventListener("pointerup",Wf),window.removeEventListener("pointercancel",Wf),document.body.classList.remove("ck-chain-dragging"),e?.row.classList.remove("dragging")}function j9(e,t,a,o){if(e.button!==0||Zf||a.length<2)return;const c=e.currentTarget.closest(".ck-chain-row");c&&(e.preventDefault(),Zf={list:[...a],from:t,row:c,onChange:o},c.classList.add("dragging"),document.body.classList.add("ck-chain-dragging"),window.addEventListener("pointermove",wM),window.addEventListener("pointerup",Wf),window.addEventListener("pointercancel",Wf))}function w9({models:e,defaultModels:t,dirty:a,saving:o}){const[c,d]=x.useState(""),f=()=>{const p=c.trim();if(p){if(e.includes(p)){_e(r("清单里已经有「{name}」",{name:p}),"err");return}Lg([...e,p]),d("")}};return s.jsxs("section",{className:"panel ck-chain-panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("保活模型链")}),s.jsx("span",{className:"panel-sub",children:r("WorkBuddy 国际版日活任务的免费模型 · 全局一份,与条目无关")}),s.jsx(ne,{size:"sm",variant:"default",className:"ml-auto",disabled:!a||o,onClick:()=>{W7(e)},children:r(o?"保存中…":"保存")})]}),s.jsxs("div",{className:"p-4",children:[s.jsxs("div",{className:"ck-set-line ck-set-line-top",children:[s.jsx("span",{className:"ck-set-k",children:r("模型清单")}),s.jsxs("span",{className:"ck-set-v",children:[s.jsxs("div",{className:"ck-mini-row",children:[s.jsx("span",{className:"ck-mini-note",children:r("按序逐个尝试,共 {n} 个",{n:e.length})}),s.jsx("button",{type:"button",className:"ck-mini-btn",disabled:o||t.length===0,title:r("把缺省链填进清单,再点「保存」生效"),onClick:()=>Lg([...t]),children:r("填入缺省链")})]}),s.jsxs("div",{className:"ck-chain",children:[e.map((p,h)=>s.jsxs("div",{className:"ck-chain-row",children:[s.jsx("span",{className:"ck-chain-grip",role:"button",tabIndex:-1,"aria-label":r("按住拖动调整顺序"),title:r("按住拖动,调整这个模型在链里的顺序"),onPointerDown:b=>j9(b,h,e,Lg),dangerouslySetInnerHTML:{__html:Pe().wbIcons?.icon?.("gripVertical",14)||""}}),s.jsx("span",{className:"ck-chain-name",title:p,children:p}),s.jsxs("span",{className:"ck-chain-index",children:["#",h+1]}),s.jsx("button",{type:"button",className:"ck-chain-del",disabled:o,"aria-label":r("移除 {name}",{name:p}),title:r("从清单里移除"),onClick:()=>Lg(e.filter((b,y)=>y!==h)),children:"×"})]},p)),e.length===0?s.jsx("div",{className:"ck-chain-empty",children:r("清单为空 —— 保存后恢复缺省链")}):null]}),s.jsxs("div",{className:"ck-chain-add",children:[s.jsx(Fe,{type:"text",className:"max-w-[260px] font-mono text-xs",placeholder:r("WorkBuddy 国际版保活模型,按顺序回退"),value:c,disabled:o,onChange:p=>d(p.currentTarget.value),onKeyDown:p=>{p.key==="Enter"&&(p.preventDefault(),f())}}),s.jsx(ne,{size:"sm",variant:"outline",disabled:o||c.trim()==="",onClick:f,children:r("添加模型")}),a?s.jsx("span",{className:"ck-chain-dirty",children:r("有未保存的改动")}):null]})]})]}),s.jsx("div",{className:"ck-note",children:r("「保活模型链」是 WorkBuddy 国际版领日活时用来保活的免费模型,按顺序逐个尝试、 第一个成功即止;清空清单并保存 = 恢复缺省链(当前缺省:{defaults})。 当天去重 + 幂等领取:重复执行只会拿到「已领取」,不会重复加分。",{defaults:t.join(r("、"))})})]})]})}function S9(){const e=p9(),t=m9();if(x.useEffect(()=>{xM()},[]),!e.loaded)return s.jsxs("div",{className:"ck-loading",children:[s.jsx(of,{className:"size-5"}),s.jsx("span",{children:r("正在读取定时签到数据…")})]});const a=e.data,o=a?.enabled===!0,c=a?.startupCatchUp!==!1,d=Array.isArray(a?.schedules)?a.schedules:[],f=t.snapshot?.keepalive,p=Array.isArray(f?.models)?f.models:[],h=Array.isArray(f?.defaultModels)?f.defaultModels:[],b=t.keepaliveDraft,y=b??p,v=b!==null&&!v9(b,p);return s.jsxs("div",{children:[e.loadError?s.jsxs("div",{className:"ck-page-error",children:[s.jsx("span",{children:r("读取定时签到数据失败:{error}",{error:e.loadError})}),s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>{xM()},children:r("重试")})]}):null,s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("定时签到")}),s.jsx("span",{className:"tip-q","data-tip":f9}),s.jsx("span",{className:"panel-sub",children:r("每条条目各有时刻与范围 · 各自当天去重 · 错过时点开机自动补签")}),s.jsx(ne,{size:"sm",variant:"outline",className:"ml-auto flex-none",disabled:e.saving,onClick:()=>bw(e.editingId==="new"?null:"new"),children:e.editingId==="new"?r("收起新建"):r("添加条目")})]}),s.jsxs("div",{className:"p-4",children:[s.jsxs("div",{className:"ck-set-line",children:[s.jsx("span",{className:"ck-set-k",children:r("总开关")}),s.jsxs("span",{className:"ck-set-v flex items-center gap-2",children:[s.jsx(Zn,{checked:o,disabled:e.saving,onCheckedChange:j=>{o9(j===!0)}}),s.jsx("span",{className:"text-subtle text-xs",children:r(o?"开着:启用的条目按各自时刻执行":"关着:所有条目都不执行")})]})]}),s.jsxs("div",{className:"ck-set-line",children:[s.jsx("span",{className:"ck-set-k",children:r("启动补签")}),s.jsxs("span",{className:"ck-set-v flex items-center gap-2",children:[s.jsx(Zn,{checked:c,disabled:e.saving,onCheckedChange:j=>{c9(j===!0)}}),s.jsx("span",{className:"text-subtle text-xs",children:r(c?"开着:开机后今天没签过的条目立刻补签,不看随机窗口":"关着:开机后等到窗口起点再签,随机窗口当天生效")})]})]})]}),s.jsxs("div",{children:[e.editingId==="new"?s.jsx(x9,{store:e}):null,d.map(j=>s.jsx(b9,{entry:j,store:e},j.id)),d.length===0?s.jsx("div",{className:"ck-empty",children:r("还没有定时条目 —— 点「添加条目」建一条,或到「签到中心」手动签到。")}):null]})]}),s.jsx(w9,{models:y,defaultModels:h,dirty:v,saving:t.keepaliveSaving})]})}const Bg="checkin-records",SM=["today","7","30","month","all"],_u="all",N9=[{value:"today",label:r("今天")},{value:"7",label:r("7 天")},{value:"30",label:r("30 天")},{value:"month",label:r("本月")},{value:"all",label:r("全部")}],NM="workbuddy-desktop-checkin-records-range";function Hg(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function kM(e){const t=new Date;switch(e){case"today":return Hg(t);case"7":return Hg(new Date(t.getFullYear(),t.getMonth(),t.getDate()-6));case"30":return Hg(new Date(t.getFullYear(),t.getMonth(),t.getDate()-29));case"month":return Hg(new Date(t.getFullYear(),t.getMonth(),1));default:return null}}function k9(){try{const e=localStorage.getItem(NM);return e!==null&&SM.includes(e)?e:_u}catch{return _u}}function CM(e){try{localStorage.setItem(NM,e)}catch{}}function TM(e){return typeof e=="number"&&e>0?e:bu}const vw={success:{label:"成功领取",variant:"success"},already:{label:"今日已领",variant:"brand"},pending:{label:"等待窗口",variant:"warning"},failed:{label:"失败",variant:"destructive"}},C9={schedule:"定时",startup:"补签",manual:"手动",single:"单签",activity:"活动"},yw=[{key:"time",label:r("时间")},{key:"account",label:r("账号")},{key:"provider",label:r("提供商")},{key:"source",label:r("来源")},{key:"outcome",label:r("结果")},{key:"detail",label:r("说明")}];let jw=null;function EM(){return jw?jw.apply([...yw]):yw.map(e=>({...e,align:e.align??"left"}))}function AM(){window.wbTableColumns?.repaint?.(Bg)}function RM(e){return(fr().snapshot?.auto?.providerOptions??[]).find(a=>a.id===e)?.label??e}function T9(e,t){const a=`ck-col-${t.key} ta-${t.align}`;switch(t.key){case"time":return s.jsxs("td",{className:a,children:[e.ts?Ls(e.ts):"—",s.jsx("span",{className:"ck-record-date",children:e.date||""})]},t.key);case"account":return s.jsx("td",{className:a,children:e.accountName||e.accountId||"—"},t.key);case"provider":return s.jsx("td",{className:a,children:e.provider?RM(e.provider):"—"},t.key);case"source":return s.jsxs("td",{className:a,children:[s.jsx("span",{className:"ck-record-source",children:C9[e.source??""]??e.source??"—"}),e.reason?s.jsx("span",{className:"ck-record-reason",children:e.reason}):null]},t.key);case"outcome":{const o=vw[e.outcome??""]??{label:e.outcome||"—",variant:"outline"};return s.jsxs("td",{className:a,children:[s.jsx(ze,{variant:o.variant,shape:"tag",children:o.label}),e.keptActive?s.jsx(ze,{variant:"outline",shape:"tag",className:"ml-1",children:r("保活")}):null]},t.key)}case"detail":return s.jsx("td",{className:e.error?`${a} ck-record-detail-fail`:a,children:e.error||e.message||"—"},t.key);default:return null}}function E9(){const[e,t]=x.useState([]),[a,o]=x.useState(0),[c,d]=x.useState(1),[f,p]=x.useState(()=>k9()),[h,b]=x.useState(()=>TM(mg(Bg,fg))),[y,v]=x.useState({outcome:"",provider:"",keyword:""}),[j,w]=x.useState(""),[k,S]=x.useState(!1),[N,R]=x.useState(""),[P,T]=x.useState(0),C=x.useRef(null),E=x.useRef(0),[,D]=x.useReducer(Q=>Q+1,0),I=fr().snapshot?.auto?.providerOptions??[],O=EM(),_=Math.max(1,Math.ceil(a/h)),z=Math.min(c,_),H=y.outcome!==""||y.provider!==""||y.keyword!==""||f!==_u,B=a?{start:(z-1)*h+1,end:Math.min(a,z*h)}:null,L=x.useCallback(async Q=>{const G=E.current+1;E.current=G,S(!0),R("");try{const Y=await Pe().workbuddyDesktop?.getCheckinRecords?.({limit:Q.size,offset:(Q.page-1)*Q.size,outcome:Q.filters.outcome,provider:Q.filters.provider,keyword:Q.filters.keyword,start:kM(Q.range)});if(G!==E.current)return;t(Array.isArray(Y?.records)?Y.records:[]),o(Number(Y?.total)||0)}catch(J){if(G!==E.current)return;R(J instanceof Error?J.message:String(J))}finally{G===E.current&&S(!1)}},[]);x.useEffect(()=>{L({page:c,size:h,range:f,filters:y})},[L,c,h,f,y]),x.useEffect(()=>{c>_&&d(_)},[c,_]),x.useLayoutEffect(()=>{const Q=Pe().wbColSettings;if(!Q?.register){const G=window.setTimeout(()=>T(J=>J+1),50);return()=>window.clearTimeout(G)}jw=Q.register({id:Bg,label:r("签到记录表"),columns:yw.map(G=>({key:G.key,label:G.label,align:G.align??"left"})),mount:()=>C.current,onChange:()=>{Ts.flushSync(()=>D()),AM()}}),D()},[P]),x.useLayoutEffect(()=>{AM()}),x.useEffect(()=>()=>{Pe().wbColSettings?.close()},[]);const F=Q=>{v(Q),d(1)},$=Q=>{const G=SM.includes(Q)?Q:_u;G!==f&&(CM(G),p(G),d(1))},X=Q=>{b(TM(Q)),hg(Bg,Q),d(1)},K=()=>{w(""),CM(_u),p(_u),F({outcome:"",provider:"",keyword:""})},q=async()=>{const Q=Pe().wbConfirm?.ask;if(!Q)return;const G=r(H?"确定清空当前筛选出的签到记录?清空后无法恢复。":"确定清空全部签到记录?清空后无法恢复。");if(await Q({title:r("清空签到记录"),html:G,okText:r("清空"),okClass:"danger"}))try{await Pe().workbuddyDesktop?.clearCheckinRecords?.(H?{outcome:y.outcome,provider:y.provider,keyword:y.keyword,start:kM(f)}:{all:"1"}),OM("签到记录已清空"),await L({page:1,size:h,range:f,filters:y}),d(1)}catch(J){OM(r("清空失败:{error}",{error:J instanceof Error?J.message:String(J)}),"err")}};return s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("签到记录")}),s.jsx("span",{className:"panel-sub",children:r("每执行一次签到 · 每个账号一条明细 · 结果与收益以后端落账为准")}),s.jsxs("div",{ref:C,className:"ml-auto flex items-center gap-2",children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:k,onClick:()=>{L({page:c,size:h,range:f,filters:y})},children:r(k?"刷新中…":"刷新")}),s.jsx(ne,{size:"sm",variant:"ghost",className:"text-destructive",onClick:()=>{q()},children:r("清空")})]})]}),s.jsxs("div",{className:"ck-records-filters",children:[s.jsx(En,{options:N9,value:f,onValueChange:$,"aria-label":r("签到记录时间范围"),className:"shrink-0"}),s.jsxs(dt,{value:y.outcome,onValueChange:Q=>F({...y,outcome:Q??""}),children:[s.jsx(pt,{className:"w-[128px] shrink-0","aria-label":r("按结果筛选"),children:s.jsx(ft,{children:y.outcome?vw[y.outcome]?.label??y.outcome:r("全部结果")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"",children:r("全部结果")}),Object.entries(vw).map(([Q,G])=>s.jsx($e,{value:Q,children:G.label},Q))]})]}),s.jsxs(dt,{value:y.provider,onValueChange:Q=>F({...y,provider:Q??""}),children:[s.jsx(pt,{className:"w-[148px] shrink-0","aria-label":r("按提供商筛选"),children:s.jsx(ft,{children:y.provider?RM(y.provider):r("全部提供商")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"",children:r("全部提供商")}),I.map(Q=>s.jsx($e,{value:Q.id,children:Q.label},Q.id))]})]}),s.jsx("div",{className:"spacer"}),s.jsx(Fe,{type:"search",className:"ck-records-search w-[200px] basis-[200px] min-w-[150px] grow-0 shrink",placeholder:r("搜账号 / 收益 / 错误 / 触发原因"),value:j,onChange:Q=>w(Q.currentTarget.value),onBlur:()=>{j!==y.keyword&&F({...y,keyword:j.trim()})},onKeyDown:Q=>{Q.key==="Enter"&&Q.currentTarget.blur(),Q.key==="Escape"&&(w(y.keyword),Q.currentTarget.blur())}}),H?s.jsx(ne,{size:"sm",variant:"ghost",onClick:K,children:r("清除筛选")}):null,s.jsx("span",{className:"panel-sub",children:k?r("读取中…"):r("{n} 条",{n:a})})]}),N?s.jsxs("div",{className:"ck-page-error",children:[s.jsx("span",{children:r("读取签到记录失败:{error}",{error:N})}),s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>{L({page:c,size:h,range:f,filters:y})},children:r("重试")})]}):null,e.length===0&&!k?s.jsx("div",{className:"ck-empty",children:r(H?"没有符合筛选条件的签到记录":"还没有签到记录 —— 手动签到或等定时条目执行后,明细会出现在这里。")}):s.jsx("div",{className:"ck-records-scroll",children:s.jsxs("table",{className:"ck-table ck-records-table",children:[s.jsx("colgroup",{children:O.map(Q=>s.jsx("col",{"data-col":Q.key,className:`ck-col-${Q.key}`},Q.key))}),s.jsx("thead",{children:s.jsx("tr",{children:O.map(Q=>s.jsx("th",{"data-col":Q.key,className:`ck-col-${Q.key} ta-${Q.align}`,children:Q.label},Q.key))})}),s.jsx("tbody",{children:e.map(Q=>s.jsx("tr",{children:O.map(G=>T9(Q,G))},Q.rowId))})]})}),s.jsx($i,{total:a,range:B,page:z,pageCount:_,size:h,sizes:fg,onSizeChange:X,onPageChange:d,disabled:k})]})}function OM(e,t){Pe().wbApp?.toast?.(e,t)}window.wbCheckinRecords={visibleColumns:()=>EM().map(e=>({key:e.key}))};const MM={workbuddy:r("腾讯每日签到接口 · 仅国内版"),"workbuddy-intl":r("每日活跃任务 · 网页会话保活点亮日活,领取才加积分 · 两者可分开执行"),raccoon:r("桌面端每日积分链路"),autoclaw:r("官方客户端的每日签到任务"),"autoclaw-intl":r("与国内版同一套任务接口 · 站点不同"),qoder:r("活动(campaign)领取 · 每天 10:00 刷新"),"qoder-intl":r("带设备风控身份领取「每日 100 Credits」 · 需要 UMID 组件"),trae:r("SOLO 的 checkin_credits 领取 · 按自然日 0 点刷新"),loomy:r("无独立签到接口 · 每天替账号打一次首次登录积分"),kuku:r("「免费领积分」的每日任务 · 逐个领取"),officeace:r("一次领当天全部奖励(每日签到 + 新人礼) · 幂等由上游保证"),codearts:r("每日福利 · 领取 → 确认 → 回读核实 · 按北京时间自然日重置"),modelscope:r("无独立签到接口 · 每天替账号打一次登录信息(即当日魔粒)"),"modelscope-intl":r("与国内版同一套链路 · 站点不同、令牌不通用"),chatglm:r("每日登录积分 · 顺带领取会员活动 · 访客账号无积分体系(跳过)")},A9=[{value:"center",label:r("签到中心")},{value:"schedule",label:r("定时签到")},{value:"records",label:r("签到记录")}];function R9(e){return r(e==="raccoon"?"小浣熊":e==="loomy"?"Loomy":e==="codearts"?"CodeArts":e==="officeace"?"OfficeAce 果办":e)}function O9(){const[e,t]=x.useState(fr());return x.useEffect(()=>oM(()=>t(fr())),[]),e}function M9({group:e}){const t=s9(e);return t==="none"?s.jsx(ze,{variant:"outline",shape:"tag",children:r("无账号")}):t==="done"?s.jsx(ze,{variant:"success",shape:"tag",children:r("已签")}):t==="part"?s.jsx(ze,{variant:"warning",shape:"tag",children:r("部分")}):s.jsx(ze,{variant:"brand",shape:"tag",children:r("待签")})}function Jf({id:e,label:t}){const a=Cg[e==="workbuddy-intl"?"workbuddy":e];return s.jsx("span",{className:"ck-prov-logo",children:a?s.jsx("img",{src:a,alt:""}):t.slice(0,1)||"·"})}function D9({group:e}){const t=fr().signing,a=(o,c)=>t.has(`${o}:${c}`);return s.jsxs("table",{className:"ck-table",children:[s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{children:r("账号")}),s.jsx("th",{children:r("今日签到")}),s.jsx("th",{children:r("上次签到时间")}),s.jsx("th",{"aria-label":r("操作")})]})}),s.jsx("tbody",{children:e.accounts.map(o=>{const c=e.id==="workbuddy-intl";return s.jsxs("tr",{children:[s.jsx("td",{children:o.name||o.id}),s.jsx("td",{children:o.checkedInToday?s.jsx(ze,{variant:"success",shape:"tag",children:r("已签")}):s.jsx(ze,{variant:"brand",shape:"tag",children:r("待签")})}),s.jsx("td",{className:"text-subtle",children:o.checkinAt?Ls(o.checkinAt):"—"}),s.jsx("td",{className:"text-right",children:c?s.jsxs("span",{className:"inline-flex items-center gap-1",children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:a(o.id,"keepalive"),title:r("用免费模型与网页会话维持账号活跃 · 不领取奖励"),onClick:()=>{_g(o.id,"keepalive")},children:a(o.id,"keepalive")?r("保活中…"):r("保活")}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:a(o.id,"claim"),title:r("探测活动并领取日活奖励 · 不做保活"),onClick:()=>{_g(o.id,"claim")},children:a(o.id,"claim")?r("领取中…"):r("领取")}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:a(o.id,"full"),title:r("探测 + 领取 + 保活 · 与定时签到同一套组合"),onClick:()=>{_g(o.id,"full")},children:a(o.id,"full")?r("执行中…"):r("保活+领取")})]}):s.jsx(ne,{size:"sm",variant:"ghost",disabled:a(o.id,"checkin"),onClick:()=>{_g(o.id)},children:a(o.id,"checkin")?r("签到中…"):o.checkedInToday?r("重签"):r("签到")})})]},o.id)})})]})}function I9({group:e,expanded:t}){const a=e.totalCount>0;return s.jsxs("div",{className:t?"ck-prov-row open":"ck-prov-row",children:[s.jsxs("div",{className:"ck-prov-main",onClick:()=>a&&iM(e.id),onKeyDown:o=>{a&&(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),iM(e.id))},role:a?"button":void 0,tabIndex:a?0:-1,"aria-expanded":a?t:void 0,children:[s.jsx(Jf,{id:e.id,label:e.label}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:e.label}),s.jsx("div",{className:"ck-prov-desc",children:MM[e.id]??""})]}),s.jsxs("div",{className:"ck-prov-right",children:[s.jsx("span",{className:"ck-prov-count",children:a?r("{total} 账号 · {done} 已签",{total:e.totalCount,done:e.doneCount}):"—"}),s.jsx(M9,{group:e}),a?s.jsx("span",{className:"ck-chev","aria-hidden":!0,children:"›"}):null]})]}),e.id==="qoder-intl"?s.jsx(DM,{}):null,t?s.jsx("div",{className:"ck-prov-detail",children:s.jsx(D9,{group:e})}):null]})}function DM(){const[e,t]=x.useState(null),a=x.useCallback(async()=>{try{t(await zr().getQoderUmid?.()??null)}catch{}},[]);x.useEffect(()=>{a()},[a]);const o=e?.installing===!0&&e.available!==!0;if(x.useEffect(()=>{if(!o)return;const d=window.setInterval(()=>{a()},3e3);return()=>{window.clearInterval(d)}},[o,a]),!e||e.available)return null;const c=async()=>{try{t(d=>d&&{...d,installing:!0}),await zr().installQoderUmid?.(),Pe().wbApp?.toast?.(r("✅ UMID 组件已安装,下轮签到即可领取国际版积分"))}catch(d){Pe().wbApp?.toast?.(r("UMID 组件安装失败:{error}",{error:d instanceof Error?d.message:String(d)}),"err")}finally{a()}};return s.jsxs("div",{className:"flex flex-wrap items-center gap-2 pb-2.5 pl-[58px] pr-4 text-[12px] text-muted-foreground",children:[s.jsx("span",{children:r("国际版签到需要 UMID 组件生成设备风控身份(本机未检测到)。")}),e.installSupported?s.jsx(ne,{variant:"outline",size:"sm",disabled:e.installing===!0,onClick:()=>{c()},children:e.installing?r("安装中…"):r("一键安装组件")}):s.jsx("span",{children:r("安装 Qoder 客户端或 qodercli 后即可(无需重启网关)。")})]})}function P9({row:e}){const t=e.provider??"loomy",a=fr().onboarding.get(e.id),o=a?.tasks??[],c=a?.unclaimed??0,d=a?.status==="loaded"&&o.length>0,f=d&&cM(e.id);return s.jsxs("div",{className:f?"ck-prov-row open":"ck-prov-row",children:[s.jsxs("div",{className:"ck-prov-main",onClick:d?()=>hw(e.id):void 0,onKeyDown:p=>{d&&(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),hw(e.id))},role:d?"button":void 0,tabIndex:d?0:-1,"aria-expanded":d?f:void 0,children:[s.jsx(Jf,{id:t,label:R9(t)}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:e.name||e.id}),s.jsxs("div",{className:"ck-prov-desc",children:[a?.status==="loaded"?r("已领 {claimed}/{total} · 累计 {earned} 积分",{claimed:o.length-c,total:o.length,earned:a.total?`${a.earned} / ${a.total}`:a.earned}):r("尚未查询任务状态"),a?.settled&&a.settledAt?` · ${r("结算于 {time}",{time:Ls(a.settledAt)})}`:a?.checkedAt?` · ${r("查询于 {time}",{time:Ls(a.checkedAt)})}`:""]})]}),s.jsxs("div",{className:"ck-prov-right",onClick:p=>p.stopPropagation(),children:[a?.status==="loaded"&&c>0?s.jsx(ze,{variant:"warning",shape:"tag",children:r("{n} 项待领",{n:c})}):a?.status==="loaded"?s.jsx(ze,{variant:"success",shape:"tag",children:r("全部领取")}):a?.status==="error"?s.jsx(ze,{variant:"destructive",shape:"tag",children:r("查询失败")}):null,s.jsx(ne,{size:"sm",variant:"outline",disabled:a?.status==="loading"||a?.claiming===!0,onClick:()=>{gw(e.id,{expand:!0,refresh:!0})},children:a?.status==="loading"?r("查询中…"):r("查询任务")}),s.jsx(ne,{size:"sm",variant:"outline",disabled:a?.status!=="loaded"||t!=="officeace"&&c===0||a?.claiming===!0,onClick:()=>{dM(e.id)},children:a?.claiming?r("领取中…"):c>0?r("一键领取({n})",{n:c}):r("领取")}),d?s.jsx("span",{className:"ck-chev","aria-hidden":!0,children:"›"}):null]})]}),a?.status==="error"?s.jsx("div",{className:"ck-fold-note",children:r("查询失败:{error}",{error:a.error??""})}):null,f?s.jsx("div",{className:"ck-prov-detail",children:o.map(p=>s.jsxs("div",{className:"ck-task-line",children:[s.jsx("span",{className:p.done?"ck-task-tick done":"ck-task-tick",children:p.done?"✓":"·"}),s.jsx("span",{children:p.title}),s.jsxs("span",{className:"ck-task-pts",children:["+",p.points]}),s.jsx("span",{className:"ck-task-st",children:p.claiming?s.jsx(ze,{variant:"warning",shape:"tag",children:r("领取中")}):p.done?s.jsx(ze,{variant:"success",shape:"tag",children:r("已领取")}):p.blocked?s.jsx(ze,{variant:"outline",shape:"tag",children:r("暂不可领")}):p.error?s.jsx(ze,{variant:"destructive",shape:"tag",children:p.error}):s.jsx(ze,{variant:"brand",shape:"tag",children:r("可领取")})})]},p.key))}):null]})}function _9({row:e}){const t=tg({claimPlans:e.claimPlans}),a=t.length>0;return s.jsxs("div",{className:"ck-welfare-row",children:[s.jsx(Jf,{id:"zcode",label:"ZCode"}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsxs("div",{className:"ck-prov-name",children:[e.name||e.id,a?s.jsx(ze,{variant:"success",shape:"tag",title:r("本地台账里今天(北京时间)领过的套餐:{plans}",{plans:t.join(r("、"))}),children:r("今天已领 {n} 份",{n:t.length})}):s.jsx(ze,{variant:"outline",shape:"tag",title:r("本地台账里今天还没领过;活动期内每天发一份新套餐"),children:r("今天未领")})]}),s.jsx("div",{className:"ck-prov-desc",children:a?r("点「套餐明细」看领到了哪几份、什么时候生效;活动期内每天可再领"):e.claimAt?r("上次领取 {time} · 领取需通过滑块验证码",{time:Ls(e.claimAt)}):r("限时体验套餐(start-plan),活动期内每天一份 · 领取需滑块验证码")})]}),s.jsx("div",{className:"ck-prov-right",children:s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>RR(e.id,e.name),children:r(a?"套餐明细":"去领取")})})]})}function L9({row:e}){const t=fr().growth.get(e.id),a=t?.tasks??[],o=a.filter(v=>v.supported&&!v.unforgeable),c=o.filter(v=>v.status!=="claimed"&&v.current0,f=d&&e9(e.id),p=t?.travel,h=t?.school,b=t?.results??[],y=v=>b.find(j=>j.code===v);return s.jsxs("div",{className:f?"ck-prov-row open":"ck-prov-row",children:[s.jsxs("div",{className:"ck-prov-main",onClick:d?()=>mM(e.id):void 0,onKeyDown:v=>{d&&(v.key==="Enter"||v.key===" ")&&(v.preventDefault(),mM(e.id))},role:d?"button":void 0,tabIndex:d?0:-1,"aria-expanded":d?f:void 0,children:[s.jsx(Jf,{id:"workbuddy",label:"WorkBuddy"}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:e.name||e.id}),s.jsxs("div",{className:"ck-prov-desc",children:[t?.status==="loaded"?r("{total} 项任务 · {pending} 项可完成",{total:o.length,pending:c.length}):r("查询任务树并一键点亮 / 领奖(含开学季与猫猫旅行)"),t?.checkedAt?` · ${r("查询于 {time}",{time:Ls(t.checkedAt)})}`:""]})]}),s.jsxs("div",{className:"ck-prov-right",onClick:v=>v.stopPropagation(),children:[t?.status==="loaded"?c.length>0?s.jsx(ze,{variant:"warning",shape:"tag",children:r("{n} 项可完成",{n:c.length})}):s.jsx(ze,{variant:"success",shape:"tag",children:r("全部完成")}):t?.status==="error"?s.jsx(ze,{variant:"destructive",shape:"tag",children:r("查询失败")}):null,s.jsx(ne,{size:"sm",variant:"outline",disabled:t?.status==="loading"||t?.running===!0,onClick:()=>{zg(e.id)},children:t?.status==="loading"?r("查询中…"):r("查询任务")}),s.jsx(ne,{size:"sm",variant:"outline",disabled:t?.status!=="loaded"||t?.running===!0,title:r("接单 + 点亮 + 领奖(只处理已实测沉淀的任务)"),onClick:()=>{hM(e.id,"full")},children:t?.running?r("执行中…"):r("一键完成")}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:t?.status!=="loaded"||t?.running===!0,title:r("只领取已完成任务的奖励(幂等,重复点不会重复入账)"),onClick:()=>{hM(e.id,"claim")},children:r("领取")}),d?s.jsx("span",{className:"ck-chev","aria-hidden":!0,children:"›"}):null]})]}),t?.status==="error"?s.jsx("div",{className:"ck-fold-note",children:r("查询失败:{error}",{error:t.error??""})}):null,f?s.jsxs("div",{className:"ck-prov-detail",children:[s.jsxs("div",{className:"ck-fold-note",children:[t?.energy!==null&&t?.energy!==void 0?r("能量 {n}",{n:t.energy}):"",t?.streak!==null&&t?.streak!==void 0?` · ${r("连登 {n} 天",{n:t.streak})}`:"",t?.energy===null&&t?.streak===null?r("(能量 / 连登读数本次未取到)"):""]}),a.map(v=>{const j=y(v.code);return s.jsxs("div",{className:"ck-task-line",children:[s.jsx("span",{className:v.status==="claimed"?"ck-task-tick done":"ck-task-tick",children:v.status==="claimed"?"✓":"·"}),s.jsxs("span",{title:v.description||v.source||v.code,children:[v.title||v.code,v.target>1?` (${v.current}/${v.target})`:""]}),j?s.jsx("span",{className:"ck-task-pts",children:j.message}):null,s.jsx("span",{className:"ck-task-st",children:v.unforgeable?s.jsx(ze,{variant:"outline",shape:"tag",children:r("需真实操作")}):v.supported?v.status==="claimed"?s.jsx(ze,{variant:"success",shape:"tag",children:r("已领取")}):v.status==="completed"?s.jsx(ze,{variant:"brand",shape:"tag",children:r("可领取")}):v.locked?s.jsx(ze,{variant:"outline",shape:"tag",children:r("未解锁")}):s.jsx(ze,{variant:"warning",shape:"tag",children:r("可完成")}):s.jsx(ze,{variant:"outline",shape:"tag",children:r("暂不支持")})})]},v.code)}),s.jsxs("div",{className:"ck-task-line",children:[s.jsx("span",{className:"ck-task-tick",children:"🐾"}),s.jsxs("span",{children:[r("猫猫旅行"),p&&p.hasBuddy===!0?`:${p.buddyName||r("已领养")} · ${p.state==="traveling"?r("在途"):p.state==="arrived"?r("可领奖"):p.state==="idle"?p.dailyLimitReached?r("今日已派出"):r("可派出"):p.state??""}`:p&&p.hasBuddy===!1?`:${r("未领养(领养需先完成当日对话量)")}`:":"+(p?.error?String(p.error):r("尚未查询"))]}),s.jsx("span",{className:"ck-task-st",children:s.jsx(ne,{size:"sm",variant:"ghost",disabled:t?.runningTravel===!0||t?.status!=="loaded",onClick:()=>{n9(e.id)},children:t?.runningTravel?r("执行中…"):r("巡检一次")})})]}),s.jsxs("div",{className:"ck-task-line",children:[s.jsx("span",{className:"ck-task-tick",children:"🎓"}),s.jsxs("span",{children:[r("开学季活动"),h&&h.inPeriod===!0?`:${r("进行中")}${h.lottery?.balance!==void 0&&h.lottery?.balance!==null?` · ${r("抽奖机会 {n} 次",{n:h.lottery.balance})}`:""}`:h&&h.inPeriod===!1?`:${r("非活动期")}`:":"+(h?.error?String(h.error):r("尚未查询"))]}),s.jsx("span",{className:"ck-task-st",children:s.jsx(ne,{size:"sm",variant:"ghost",disabled:t?.runningSchool===!0||t?.status!=="loaded",title:r("执行开学季任务并抽空抽奖机会(分享 / 对话 / 专家事件)"),onClick:()=>{t9(e.id,!0)},children:t?.runningSchool?r("执行中…"):r("执行并抽奖")})})]}),t?.schoolText?s.jsx("div",{className:"ck-fold-note",children:t.schoolText}):null,t?.lotteryText?s.jsx("div",{className:"ck-fold-note",children:t.lotteryText}):null]}):null]})}function z9({group:e}){return s.jsxs("div",{className:"ck-prov-row",children:[s.jsxs("div",{className:"ck-prov-main",style:{cursor:"default"},children:[s.jsx(Jf,{id:e.id,label:e.label}),s.jsxs("div",{className:"ck-prov-info",children:[s.jsx("div",{className:"ck-prov-name",children:e.label}),s.jsx("div",{className:"ck-prov-desc",children:MM[e.id]??""})]}),s.jsx("div",{className:"ck-prov-right",children:s.jsx(ze,{variant:"outline",shape:"tag",children:r("无账号")})})]}),e.id==="qoder-intl"?s.jsx(DM,{}):null]})}function B9({store:e}){const t=e.snapshot,[a,o]=x.useState(null);x.useEffect(()=>{let S=!0;return(async()=>{try{const R=await Pe().workbuddyDesktop?.getCheckinRecords?.({limit:1});S&&o(Number(R?.total)||0)}catch{}})(),()=>{S=!1}},[e.version]);const c=t?.daily,d=t?.auto,f=(c?.outOfScope??[]).reduce((S,N)=>S+(Number(N.count)||0),0),p=t?.extras.onboarding??[],h=p.filter(S=>e.onboarding.get(S.id)?.status==="loaded"),b=p.reduce((S,N)=>S+(e.onboarding.get(N.id)?.unclaimed??0),0),y=t?.extras.plans??[],v=t?.extras.growth??[],j=Array.isArray(d?.schedules)?d.schedules:[],w=j.filter(S=>S.enabled===!0).length,k=r9(d);return s.jsxs("div",{children:[s.jsxs("div",{className:"ck-stats",children:[s.jsxs("div",{className:"ck-stat",children:[s.jsx("div",{className:"ck-stat-label",children:r("今日签到进度")}),s.jsx("div",{className:"ck-stat-value",children:c?s.jsxs(s.Fragment,{children:[" ",c.todayDone,s.jsxs("small",{children:[" / ",c.todayEligible]})]}):s.jsx("span",{className:"ck-pending",children:"—"})}),s.jsx(cf,{className:"ck-stat-bar",value:c&&c.todayEligible>0?c.todayDone/c.todayEligible*100:0}),s.jsx("div",{className:"ck-stat-foot",children:f>0?r("另有 {n} 个账号不参与每日签到",{n:f}):r("全部账号均可签到")})]}),s.jsxs("div",{className:"ck-stat ck-stat-link",onClick:()=>{Pg("schedule")},role:"button",tabIndex:0,onKeyDown:S=>{S.key==="Enter"&&Pg("schedule")},children:[s.jsx("div",{className:"ck-stat-label",children:r("定时签到")}),s.jsx("div",{className:"ck-stat-value",children:d?s.jsxs(s.Fragment,{children:[w,s.jsxs("small",{children:[" / ",j.length," ",r("条启用")]})]}):s.jsx("span",{className:"ck-pending",children:"—"})}),s.jsx("div",{className:"ck-stat-foot",children:d?.enabled!==!0?r("总开关已关闭 · 在「定时签到」页打开"):k?r("下次 {date} · 点此管理条目",{date:Ls(k)}):r("暂无启用的条目 · 点此添加")})]}),s.jsxs("div",{className:"ck-stat",children:[s.jsx("div",{className:"ck-stat-label",children:r("待领新手福利")}),s.jsx("div",{className:"ck-stat-value",children:p.length?s.jsxs(s.Fragment,{children:[b,s.jsxs("small",{children:[" ",r("项")]})]}):s.jsx("span",{className:"ck-pending",children:r("无")})}),s.jsx("div",{className:"ck-stat-foot",children:p.length?r("已有结果 {checked} / 共 {total} 个账号",{checked:h.length,total:p.length}):r("没有支持新手福利的账号")})]}),s.jsxs("div",{className:"ck-stat ck-stat-link",onClick:()=>{Pg("records")},role:"button",tabIndex:0,onKeyDown:S=>{S.key==="Enter"&&Pg("records")},children:[s.jsx("div",{className:"ck-stat-label",children:r("累计签到记录")}),s.jsx("div",{className:"ck-stat-value",children:a===null?s.jsx("span",{className:"ck-pending",children:"—"}):a}),s.jsx("div",{className:"ck-stat-foot",children:r("每账号一条明细 · 点此查看「签到记录」")})]})]}),s.jsxs("div",{className:"ck-main",children:[s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("每日签到")}),s.jsx("span",{className:"panel-sub",children:r("点击行展开账号明细 · 单账号签到不受范围限制")}),s.jsx(ne,{size:"sm",variant:"default",className:"ml-auto",disabled:e.runningAll||d?.running===!0,onClick:()=>{Z7()},children:e.runningAll||d?.running===!0?r("签到中…"):r("立即全部签到")})]}),s.jsxs("div",{children:[(c?.providers??[]).map(S=>S.totalCount>0?s.jsx(I9,{group:S,expanded:e.expanded.has(S.id)},S.id):s.jsx(z9,{group:S},S.id)),(c?.outOfScope??[]).length>0?s.jsx("div",{className:"ck-fold-note",children:r("不参与每日签到:{list}。CodeArts 的一次性奖励在下方「新手福利」,它的每日福利就在上方「每日签到」里;ZCode 的套餐领取见「活动福利」。",{list:c.outOfScope.map(S=>r("{label} ×{count}({reason})",{label:S.label,count:S.count,reason:S.reason})).join(r(";"))})}):null]})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("新手福利")}),s.jsx("span",{className:"panel-sub",children:r("一次性福利 · 签到后自动查询并领取,领完记在本机不再查上游 · 点击行展开任务清单")}),p.length>0?s.jsx(ne,{size:"sm",variant:"outline",className:"ml-auto",onClick:()=>{for(const S of p)S.settled&&typeof S.settled=="object"||gw(S.id)},children:r("全部查询")}):null]}),p.length?s.jsx("div",{children:p.map(S=>s.jsx(P9,{row:S},S.id))}):s.jsx("div",{className:"ck-empty",children:r("没有支持新手福利的账号 —— 目前有 Loomy、小浣熊、CodeArts 三家。")})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("活动福利")}),s.jsx("span",{className:"panel-sub",children:r("限时体验套餐 · 领取需滑块验证码 · 逐份查看与领取")})]}),y.length>0?s.jsx("div",{children:y.map(S=>s.jsx(_9,{row:S},S.id))}):s.jsx("div",{className:"ck-empty",children:r("没有可领套餐的账号(ZCode 未添加)。")})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("成长任务")}),s.jsx("span",{className:"panel-sub",children:r("WorkBuddy 国内版 · 查询任务树后一键点亮 / 领奖 · 含开学季与猫猫旅行 · 点击行展开明细")})]}),v.length>0?s.jsx("div",{children:v.map(S=>s.jsx(L9,{row:S},S.id))}):s.jsx("div",{className:"ck-empty",children:r("没有支持成长任务的账号(需要 WorkBuddy 国内版)。")})]})]})]})}function H9(){const e=O9(),t=e.snapshot;if(x.useEffect(()=>{Il()},[]),x.useEffect(()=>{window.wbApp?.renderTopbarStatus?.()},[e.version]),!e.loaded)return s.jsxs("div",{className:"ck-loading",children:[s.jsx(of,{className:"size-5"}),s.jsx("span",{children:r("正在读取签到数据…")})]});const a=t?.auto,o=a?.enabled===!0;return s.jsxs("div",{children:[e.loadError?s.jsxs("div",{className:"ck-page-error",children:[s.jsx("span",{children:r("读取签到数据失败:{error}",{error:e.loadError})}),s.jsx(ne,{size:"sm",variant:"outline",onClick:()=>{Il()},children:r("重试")})]}):null,s.jsxs("div",{className:"ck-tabs",children:[s.jsx(En,{options:A9,value:e.tab,onValueChange:c=>lM(c),"aria-label":r("签到中心分区")}),s.jsx(ze,{id:"checkin-badge",className:"ml-auto",variant:a?o?"success":"outline":"destructive","data-tone":a?o?"ok":"":"bad",children:a?o?a?.lastFiredToday?r("今日已执行"):r("已开启"):r("已关闭"):r("不可用")})]}),e.tab==="center"?s.jsx(B9,{store:e}):null,e.tab==="schedule"?s.jsx(S9,{}):null,e.tab==="records"?s.jsx(E9,{}):null]})}const IM='.page[data-page="checkin"]';let PM=!1;function _M(){if(PM)return;const e=document.querySelector(IM);e&&(PM=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(H9,{})))}const LM=()=>Il();window.wbCheckinPanel={load:LM},document.querySelector(IM)?_M():document.addEventListener("DOMContentLoaded",_M,{once:!0}),Pe().wbApp?.currentPage==="checkin"&&LM();function U9(e){return String(e??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function V9({options:e,onSettle:t}){const{title:a="确认操作",html:o="",text:c="",okText:d="确定",okClass:f="primary",bodyClass:p="danger-zone",cancelText:h="取消"}=e,b=x.useRef(null);return x.useEffect(()=>{function y(v){v.key==="Escape"&&t(!1)}return document.addEventListener("keydown",y),()=>document.removeEventListener("keydown",y)},[t]),x.useEffect(()=>{function y(v){v.target?.dataset.slot==="alert-dialog-overlay"&&t(!1)}return document.addEventListener("click",y),()=>document.removeEventListener("click",y)},[t]),s.jsx(LV,{open:!0,onOpenChange:y=>{y||t(!1)},children:s.jsxs(UV,{initialFocus:b,showCloseButton:!0,children:[s.jsx(VV,{className:"pr-10",children:s.jsx(BV,{children:a})}),s.jsx(FV,{children:s.jsx(qV,{tone:p==="danger-zone"?"danger":"neutral",dangerouslySetInnerHTML:{__html:o||U9(c).replace(/\n/g,"
    ")}})}),s.jsxs($V,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:b,variant:"outline",onClick:()=>t(!1),children:h}),s.jsx(ne,{variant:f==="danger"?"destructive":"default",onClick:()=>t(!0),children:d})]})]})})}let ep=null,Lu=null,Ug=null;function F9(){ep&&(ep.unmount(),ep=null),Lu&&(Lu.remove(),Lu=null)}function zM(e){const t=Ug;Ug=null,F9(),t?.(e)}function $9(e={}){return new Promise(t=>{Ug&&zM(!1),Ug=t,Lu=document.createElement("div"),document.body.append(Lu),ep=jn.createRoot(Lu),ep.render(s.jsx(V9,{options:e,onSettle:zM}))})}window.wbConfirm={ask:$9};const q9=r("Base URL 填进客户端的「API 地址 / Base URL」栏;对话协议按客户端支持的类型三选一(Chat Completions / Responses / Anthropic Messages),三者共用同一套模型与账号池,可随时切换;鉴权用「网关 Key」页里任一启用 Key。");function tp({id:e,name:t,note:a}){return s.jsxs("div",{className:"ep-row",children:[s.jsxs("div",{className:"ep-head",children:[s.jsx("span",{className:"ep-name",children:t}),s.jsx("span",{className:"ep-note",children:a})]}),s.jsxs("div",{className:"ep-line",children:[s.jsx("code",{className:"ep-value",id:e,children:"—"}),s.jsx(ne,{variant:"ghost",size:"icon-xs",className:"copy-btn size-[21px] rounded-[var(--r-xs)]","data-copy-from":e,title:r("复制地址"),children:"⧉"})]})]})}function G9(){return s.jsxs("section",{className:"panel ep-panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("接口地址")}),s.jsx("span",{className:"tip-q","data-tip":q9})]}),s.jsxs("div",{className:"ep-list",children:[s.jsx(tp,{id:"api-base",name:"Base URL",note:r("填进客户端的「API 地址 / Base URL」")}),s.jsx("div",{className:"ep-group",children:r("对话协议(按客户端支持的类型选一行)")}),s.jsx(tp,{id:"api-chat",name:"OpenAI Chat Completions",note:r("多数 OpenAI 兼容客户端的默认协议")}),s.jsx(tp,{id:"api-responses",name:"OpenAI Responses",note:r("OpenAI 新协议(Codex、新版 SDK)")}),s.jsx(tp,{id:"api-messages",name:"Anthropic Messages",note:r("Claude Code / Anthropic SDK(token 计数:/v1/messages/count_tokens)")}),s.jsx("div",{className:"ep-group",children:r("模型清单")}),s.jsx(tp,{id:"api-models",name:r("模型列表"),note:r("客户端自动拉取可用模型;不受鉴权限制,配 Key 之前就能拉")})]}),s.jsx("div",{className:"panel-foot",children:s.jsxs("span",{children:[r("鉴权用「网关 Key」页里任一"),s.jsx("b",{children:r("启用")}),r("的 Key:请求带 "),s.jsx("code",{children:"Authorization: Bearer "}),r(" 或 "),s.jsx("code",{children:"x-api-key: "}),r("。一把启用的 Key 都没有时不鉴权(默认网关只监听 127.0.0.1;在设置页开启「局域网访问」后监听所有网卡,鉴权与安全闸门随之启用)。")]})})]})}const BM='.page[data-page="docs"]';let HM=!1;function UM(){if(HM)return;const e=document.querySelector(BM);e&&(HM=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(G9,{})))}document.querySelector(BM)?UM():document.addEventListener("DOMContentLoaded",UM,{once:!0});function da(){return window}function ww(e){return e instanceof Error?e.message:String(e)}function np(e,t){da().wbApp?.toast?.(e,t)}function K9(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t]??t)}const Sw=[{key:"name",label:r("名称")},{key:"key",label:"Key"},{key:"time",label:r("创建时间")},{key:"state",label:r("启用")},{key:"act",label:r("操作"),align:"right"}],Y9={name:"cell-name",key:"cell-key",time:"cell-time",state:"cell-state state",act:"cell-act r"},VM='.page[data-page="keys"]';let Vg=null,Nw=null;function FM(){return Vg?Vg.apply([...Sw]):Sw.map(e=>({...e,align:e.align??"left"}))}function $M(){da().wbColSettings?.syncStaticHead?.("keys",document.querySelector("table.keys-table"))}function X9(){if(Vg)return;const e=da().wbColSettings?.register({id:"keys",label:r("网关 Key 表"),columns:Sw,mount:()=>document.querySelector('.page[data-page="keys"] .panel-head .head-actions'),onChange:()=>{$M(),Nw?.()}});e&&(Vg=e,$M())}function Q9(e){return Array.isArray(e?.keys)?e.keys:[]}function Z9(e){return Array.isArray(e?.providers)?e.providers:[]}function W9(e){const t=e?.modelsByProvider;return t&&typeof t=="object"?t:{}}function kw(e){return r(da().wbProviders?.labelOf?.(e)||e)}function J9(e,t,a){const o=new Map,c=f=>{const p=String(f??"").trim();if(!p)return;const h=p.toLowerCase();o.has(h)||o.set(h,p)};t.forEach(f=>{const p=e[f]??e[String(f).toLowerCase()];Array.isArray(p)&&p.forEach(c)}),a.forEach(c);const d=[...o.values()].map(f=>({value:f,label:r(f)}));return d.sort((f,p)=>f.value.toLowerCase()String(t)):[]}function GM(e,t){const a=new Map(t.map(c=>[c.value.toLowerCase(),c.value])),o=new Set;return e.forEach(c=>{const d=a.get(String(c).toLowerCase());d&&o.add(d)}),t.filter(c=>o.has(c.value)).map(c=>c.value)}function sK({target:e,providers:t,modelsByProvider:a,onClose:o,onSaved:c}){const d=e?.id??null,f=!!d,[p,h]=x.useState(e?.name??""),[b,y]=x.useState(""),[v,j]=x.useState(""),[w,k]=x.useState(!1),S=x.useRef(!1),[N,R]=x.useState(()=>qM(e?.allowedProviders)),[P,T]=x.useState(()=>qM(e?.allowedModels)),C=x.useMemo(()=>t.map(H=>({value:String(H.id),label:r(String(H.label??H.id))})),[t]),E=x.useMemo(()=>GM(N,C),[N,C]),D=x.useMemo(()=>J9(a,E,P),[a,E,P]),I=x.useMemo(()=>GM(P,D),[P,D]),O=D.length?r("没有匹配的选项"):E.length?r("这几家当前没有可用模型(账号未登录或清单为空)"):r("请先在上面选择可用提供商");function _(){S.current=!1,k(!1)}async function z(){if(!S.current){S.current=!0,k(!0),j(r("保存中…"));try{const H=da().workbuddyDesktop;if(!H)throw new Error(r("后端桥不可用"));if(d){const F=await H.updateKey(d,{allowedProviders:E,allowedModels:I});_(),c(F),o(),np(r("✅ 可用范围已保存"));return}const B=b.trim();if(B&&B.length<8){j(r("Key 至少需要 8 个字符"));return}const L=await H.createKey({name:p.trim(),key:B||void 0,allowedProviders:E,allowedModels:I});_(),c(L,L?.created?.id),o(),np(r("✅ Key 已创建,记得复制给客户端"))}catch(H){j(r("保存失败:{reason}",{reason:ww(H)}))}finally{_()}}}return s.jsx(Yt,{open:!0,onOpenChange:(H,B)=>{if(!H){if(S.current){B.cancel();return}o()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:f?r("可用范围 · {name}",{name:e?.name||r("未命名")}):r("新建 API Key")})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{htmlFor:"key-name",className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("名称")}),s.jsx(Fe,{id:"key-name",type:"text",maxLength:60,placeholder:r("例如 Cursor / 公司电脑"),autoComplete:"off",value:p,disabled:f,onChange:H=>h(H.currentTarget.value)})]}),!f&&s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{htmlFor:"key-value",className:"text-[12.5px] whitespace-nowrap text-subtle",children:"Key"}),s.jsx(Fe,{id:"key-value",type:"text",placeholder:r("留空自动生成;手填至少 8 个字符"),autoComplete:"off",spellCheck:!1,value:b,onChange:H=>y(H.currentTarget.value),onKeyDown:H=>{H.key==="Enter"&&z()}})]}),s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("可用提供商")}),s.jsx(Kh,{value:E,onValueChange:R,options:C,placeholder:r("留空 = 不限制"),searchPlaceholder:r("搜索提供商…"),"aria-label":r("可用提供商"),className:"flex-auto min-w-[180px] max-w-[260px]"})]}),s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("可用模型")}),s.jsx(Kh,{value:I,onValueChange:T,options:D,placeholder:r("留空 = 不限制"),emptyHint:O,searchPlaceholder:r("搜索模型…"),"aria-label":r("可用模型"),className:"flex-auto min-w-[180px] max-w-[260px]"})]}),s.jsx("p",{children:r("留空表示不限制;同时设置时请求需同时满足两个条件(模型在白名单内且路由到允许的提供商)。 「可用模型」的候选跟着上面勾选的提供商走:没勾提供商时它是空的(还没有约束范围), 勾了几家就列出这几家能收的全部对外名。")}),s.jsx("p",{id:"key-restrict-summary",children:nK(E,I)})]}),s.jsx("div",{className:"min-h-[18px] text-[11.5px] text-muted-foreground",children:v})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:o,disabled:w,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:w,onClick:()=>{z()},children:r(f?"保存范围":"创建")})]})]})})}let Fg=null;async function rK(){await Fg?.load()}function aK(){Fg?.render()}function lK(){const[e,t]=x.useState(null),[a,o]=x.useState(()=>new Set),[c,d]=x.useState(()=>new Set),[f,p]=x.useState(null),[,h]=x.useState(0),b=x.useRef(new Set),y=x.useRef(!1),v=x.useCallback(z=>{t(z)},[]),j=x.useCallback(z=>{z&&Array.isArray(z.keys)&&v(z)},[v]),w=x.useCallback(async()=>{if(!y.current){y.current=!0;try{const z=da().workbuddyDesktop;if(!z)throw new Error(r("后端桥不可用"));v(await z.getKeys()??null)}catch(z){np(r("读取 Key 列表失败:{reason}",{reason:ww(z)}),"err")}finally{y.current=!1}}},[v]);async function k(z,H,B){if(!b.current.has(z)){b.current.add(z),d(new Set(b.current));try{j(await H()),B&&np(B)}catch(L){np(r("操作失败:{reason}",{reason:ww(L)}),"err")}finally{b.current.delete(z),d(new Set(b.current))}}}function S(z){o(H=>{const B=new Set(H);return B.has(z)?B.delete(z):B.add(z),B})}async function N(z){const H=da().workbuddyDesktop,B=da().wbConfirm?.ask;if(!H||!B)return;const L=K9(z.name||z.masked||z.id);await B({title:r("删除网关 Key"),html:r("确定删除 Key「{name}」?使用它的客户端会立刻无法访问。",{name:L}),okText:r("删除"),okClass:"danger"})&&k(z.id,()=>H.deleteKey(z.id),r("Key 已删除"))}function R(z,H){const B=da().workbuddyDesktop;B&&k(z.id,()=>B.updateKey(z.id,{enabled:H}),r(H?"Key 已启用":"Key 已停用"))}x.useLayoutEffect(()=>(Fg={load:w,render:()=>h(z=>z+1)},Nw=()=>h(z=>z+1),X9(),h(z=>z+1),()=>{Fg=null,Nw=null}),[w]),x.useEffect(()=>{da().wbApp?.currentPage==="keys"&&w()},[w]),x.useEffect(()=>{da().wbApp?.renderTopbarStatus?.()},[e]);const P=Q9(e),T=gg(P.length,"keys"),C=T.paged?T.slice(P):P,E=FM(),D=e?.authRequired===!0,I=C.filter(z=>z.enabled).length,O=D?r("已启用鉴权 · {n} 把 Key 生效",{n:I}):r("未启用鉴权");function _(z,H,B){switch(z){case"name":return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"mid",children:s.jsx("span",{className:"t",children:H.name||r("未命名")})}),s.jsx("div",{className:"mname",title:tK(H),children:eK(H)})]});case"key":{const L=a.has(H.id);return s.jsxs("div",{className:"keycell",children:[s.jsx("code",{className:"kv",children:L?H.key:H.masked}),s.jsx(ne,{size:"sm",variant:"ghost",onClick:()=>S(H.id),children:r(L?"隐藏":"显示")}),s.jsx(ne,{size:"sm",variant:"ghost","data-copy":H.key,title:r("复制 Key"),children:r("复制")})]})}case"time":return s.jsx("span",{className:"muted",children:H.createdAt?da().wbApp?.formatTime?.(H.createdAt):"—"});case"state":return s.jsx(Zn,{checked:H.enabled===!0,disabled:B,"aria-label":r("启用「{name}」",{name:H.name||r("未命名")}),onCheckedChange:L=>R(H,L)});case"act":return s.jsxs("div",{className:"row-actions",children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:B,onClick:()=>p({key:H}),children:r("可用范围")}),s.jsx(ne,{size:"sm",variant:"destructive",disabled:B,onClick:()=>{N(H)},children:r("删除")})]});default:return null}}return s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("API Key 列表")}),s.jsx(ze,{id:"keys-status",variant:D?"success":"warning","data-tone":D?"ok":"warn",children:O}),s.jsx("div",{className:"head-actions",children:s.jsx(ne,{variant:"default",onClick:()=>p({key:null}),children:r("+ 新建 Key")})})]}),s.jsx("div",{className:"models-table-wrap",children:s.jsxs("table",{className:"models-table keys-table",children:[s.jsxs("colgroup",{children:[s.jsx("col",{className:"k-name","data-col":"name"}),s.jsx("col",{className:"k-key","data-col":"key"}),s.jsx("col",{className:"k-time","data-col":"time"}),s.jsx("col",{className:"k-state","data-col":"state"}),s.jsx("col",{className:"k-act","data-col":"act"})]}),s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{"data-col":"name",children:r("名称")}),s.jsx("th",{"data-col":"key",children:"Key"}),s.jsx("th",{"data-col":"time",children:r("创建时间")}),s.jsx("th",{"data-col":"state",children:r("启用")}),s.jsx("th",{className:"r","data-col":"act",children:r("操作")})]})}),s.jsx("tbody",{children:C.length?C.map(z=>{const H=c.has(z.id);return s.jsx("tr",{className:z.enabled?"":"off","data-id":z.id,children:E.map(B=>s.jsx("td",{className:`${Y9[B.key]??""} ta-${B.align}`,children:_(B.key,z,H)},B.key))},z.id)}):s.jsx("tr",{children:s.jsx("td",{colSpan:E.length,className:"empty",children:r(e?"还没有 Key,当前不鉴权":"加载中…")})})})]})}),s.jsx($i,{leading:s.jsxs("span",{children:[r("客户端请求需带 "),s.jsx("code",{children:"Authorization: Bearer "}),r(" 或 "),s.jsx("code",{children:"x-api-key: "}),r("; 修改后立即生效,本程序自身会自动使用第一把启用的 Key。每把 Key 可单独限制"),s.jsx("b",{children:r("可用提供商")}),r("与"),s.jsx("b",{children:r("可用模型")}),r("(行内「可用范围」):留空 = 不限制,两个都设时 按交集生效 —— 被限制的模型对这把 Key 表现为「不存在」(拉 /v1/models 也看不到它), 提供它的家不在可用列表里时请求同样被拒。")]}),total:P.length,range:T.paged?{start:T.rangeStart,end:T.rangeEnd}:null,page:T.page,pageCount:T.pageCount,size:T.size,onSizeChange:T.setSize,onPageChange:T.goto}),f?s.jsx(sK,{target:f.key,providers:Z9(e),modelsByProvider:W9(e),onClose:()=>p(null),onSaved:(z,H)=>{H&&o(B=>new Set(B).add(H)),j(z)}}):null]})}let KM=!1;function YM(){if(KM)return;const e=document.querySelector(VM);e&&(KM=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(lK,{})))}document.querySelector(VM)?YM():document.addEventListener("DOMContentLoaded",YM,{once:!0}),window.wbKeysPanel={load:rK,render:aK,visibleColumns:FM};const oK="login-app",iK=x.createElement("panel-captcha",{id:"captcha"});function cK(){return s.jsxs("div",{className:"w-[min(400px,100%)] rounded-lg border border-border bg-card p-[36px_34px_30px] shadow-3",children:[s.jsxs("div",{className:"mb-[26px] flex flex-col items-center gap-3 text-center",children:[s.jsxs("svg",{viewBox:"0 0 24 24",role:"img","aria-label":"Agent2API",className:"size-[52px] rounded-[12px] shadow-[0_6px_18px_rgba(0,122,255,0.35)]",children:[s.jsx("rect",{width:"24",height:"24",rx:"5.4",fill:"#007AFF"}),s.jsxs("g",{fill:"none",stroke:"#fff",strokeWidth:"2.2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M5.23 9.24h10.71"}),s.jsx("path",{d:"M15.94 6.72 18.77 9.24 15.94 11.76"}),s.jsx("path",{d:"M18.77 14.76H8.06"}),s.jsx("path",{d:"M8.06 12.24 5.23 14.76 8.06 17.28"})]})]}),s.jsxs("div",{children:[s.jsx("h1",{className:"m-0 text-[21px] font-bold tracking-[0.2px]",children:"Agent2API"}),s.jsx("div",{className:"text-[12.5px] text-muted-foreground",children:r("OpenAI 兼容网关 · 管理面板")})]})]}),s.jsx("div",{id:"mode-tip",className:"mb-[18px] text-center text-[13px] text-muted-foreground"}),s.jsxs("form",{id:"form",autoComplete:"on",children:[s.jsx(Je,{htmlFor:"username",className:"mt-3.5 mb-[5px] text-[12.5px]",children:r("账号")}),s.jsx(Fe,{id:"username",autoComplete:"username",placeholder:r("管理员账号")}),s.jsx(Je,{htmlFor:"password",className:"mt-3.5 mb-[5px] text-[12.5px]",children:r("密码")}),s.jsx(Fe,{id:"password",type:"password",autoComplete:"new-password",placeholder:r("至少 8 位")}),iK,s.jsx(ne,{id:"submit",type:"submit",size:"lg",className:"w-full",children:r("继续")}),s.jsx("div",{id:"error",className:"mt-3 min-h-5 text-center text-[13px] whitespace-pre-wrap text-destructive"})]}),s.jsx("div",{className:"mt-[22px] text-center text-[12px] text-muted-foreground",children:r("登录后可在「网关 Key」页为 API 客户端创建密钥")})]})}function uK(){const e=document.getElementById(oK);e&&Ts.flushSync(()=>{jn.createRoot(e).render(s.jsx(cK,{}))})}uK();function Hr(){return window}function Cw(e){return e instanceof Error?e.message:String(e)}function $g(e,t){Hr().wbApp?.toast?.(e,t)}const XM=1e3,dK=pg,fK=500,QM="workbuddy-desktop-logs-range",Tw="workbuddy-desktop-logs-filters",pK=300,mK="~/.agent2api/logs.jsonl",Ew=["today","7","30","month","all"],Aw="all",hK={today:r("今天"),7:r("7 天"),30:r("30 天"),month:r("本月"),all:r("全部")},gK=Ew.map(e=>({value:e,label:hK[e]})),Rw=[{value:"",label:r("全部级别")},{value:"debug",label:r("debug 及以上")},{value:"info",label:r("info 及以上")},{value:"warn",label:r("warn 及以上")},{value:"error",label:r("仅 error")}],xK=r("全部级别"),ZM=r("全部分类"),bK={debug:r("调试"),info:r("信息"),warn:r("警告"),error:r("错误")};let qg=XM,Gg=!0,Ow=!1,Mw=!1,Dw=!1,Iw=null,Po=null,Pw=null,Kg=null,_w=!1,Lw=!1;const zw={level:"",category:"",keyword:""};function vK(){const e=Hr().wbFilterMemory;if(!e)return{...zw};_w=!0;const t=e.load(Tw,{...zw});return{level:Rw.some(a=>a.value===t.level)?t.level:"",category:t.category,keyword:t.keyword}}function Yg(e){Hr().wbFilterMemory?.save(Tw,{level:e.level||"",category:e.category||"",keyword:e.keyword.trim()||""})}function yK(){try{const e=localStorage.getItem(QM);return e!==null&&Ew.includes(e)?e:Aw}catch{return Aw}}function jK(e){try{localStorage.setItem(QM,e)}catch{}}function Xg(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function wK(e){const t=new Date;switch(e){case"today":return Xg(t);case"7":return Xg(new Date(t.getFullYear(),t.getMonth(),t.getDate()-6));case"30":return Xg(new Date(t.getFullYear(),t.getMonth(),t.getDate()-29));case"month":return Xg(new Date(t.getFullYear(),t.getMonth(),1));default:return null}}function SK(e){if(!e)return"—";const t=new Date(e),a=d=>String(d).padStart(2,"0"),o=`${a(t.getHours())}:${a(t.getMinutes())}:${a(t.getSeconds())}`,c=`${a(t.getMonth()+1)}-${a(t.getDate())}`;return t.getFullYear()===new Date().getFullYear()?`${c} ${o}`:`${t.getFullYear()}-${c} ${o}`}function NK(e){const t=e.data;if(!t)return"";const a=[];return(t.from||t.to)&&a.push([t.from,t.to].filter(Boolean).join(" → ")),t.model&&a.push(r("模型 {model}",{model:t.model})),t.resetAtText?a.push(r("{time} 恢复",{time:t.resetAtText})):t.status&&!t.from&&!t.to&&a.push(`HTTP ${t.status}`),a.length?a.join(" · "):""}function Bw(e){return Array.isArray(e?.entries)?e.entries:[]}function Qg(e,t,a){const o=Math.max(1,a==="all"?1:Math.ceil(t.length/a));return Math.min(Math.max(1,e),o)}function Hw(e,t){return Object.hasOwn(e,t)}function kK(e){const t={};if(e&&typeof e=="object")for(const[a,o]of Object.entries(e))typeof o=="string"&&(t[a]=o);return t}function WM(e,t){const a=new URLSearchParams,o=e.keyword.trim(),c=wK(t);return e.level&&a.set("level",e.level),e.category&&a.set("category",e.category),o&&a.set("keyword",o),c!==null&&a.set("start",String(c)),a}function CK(e,t){const a=WM(e,t);return a.set("limit",String(fK)),a.toString()}function TK(e,t){return WM(e,t).toString()}function EK(e){Iw=e||null,Hr().wbApp?.updateLogsBadge?.(Iw)}async function AK(){if(!Ow)try{const e=await Hr().workbuddyDesktop?.getScheduledTasks(),t=(e?.tasks||[]).find(a=>a.id==="logsAutoRefresh");Uw(t||null),Ow=Array.isArray(e?.tasks)}catch(e){console.warn("读取日志自动刷新间隔失败,按默认 10 秒:",Cw(e)),Uw(null)}}function Uw(e){Ow=!0;const t=Number(e?.interval);!!e&&typeof e=="object"&&Number.isFinite(t)&&t>0&&(e.unit==="seconds"||e.unit==="minutes")?(Gg=e.enabled!==!1,qg=e.unit==="minutes"?t*6e4:t*1e3):(Gg=!0,qg=XM),Po?.applyAutoConfig(qg,Gg)}async function RK(e={}){await Po?.load(e)}function OK(e){if(!Po){Kg={data:e??null};return}Po.render(e)}function MK(){return Iw}async function DK(e){if(!Po){Pw=e;return}await Po.showCategory(e)}const IK={entries:[],total:0,matched:0,file:mK,categories:{},loaded:!1};function Vw(e,t){return{entries:Bw(e),total:Number(e?.total)||0,matched:Number(e?.matched)||0,file:e?.file||t.file,categories:Object.keys(t.categories).length?t.categories:kK(e?.categories),loaded:!0}}function PK(e){return e.loaded?e.total?r("没有符合筛选条件的日志"):r("暂无日志"):r("正在加载日志…")}function _K(){const[e,t]=x.useState(IK),[a,o]=x.useState(vK),[c,d]=x.useState(yK),[f,p]=x.useState(1),[h,b]=x.useState(()=>mg("logs")),[y,v]=x.useState(null),[j,w]=x.useState(()=>({ms:qg,enabled:Gg})),k=x.useRef(null),S=x.useRef(null),N=x.useRef(null),R=x.useRef(null),P=x.useRef(a),T=x.useRef(c),C=x.useRef(f),E=x.useRef(h),D=x.useRef(e),I=x.useCallback(le=>{const de={...P.current,...le};return P.current=de,o(de),de},[]),O=x.useCallback(le=>{T.current=le,d(le)},[]),_=x.useCallback(le=>{C.current=le,p(le)},[]),z=x.useCallback(le=>{E.current=le,b(le),hg("logs",le)},[]),H=x.useCallback(le=>{D.current=le,t(le)},[]),B=x.useCallback(()=>{if(_w)return;const le=Hr().wbFilterMemory;if(!le||(_w=!0,Lw))return;const de=le.load(Tw,{...zw});I({level:de.level,category:de.category,keyword:de.keyword})},[I]),L=x.useCallback(async(le={})=>{const{silent:de=!1,resetPage:Se=!1}=le;Se&&_(1),AK(),B();const Te=CK(P.current,T.current),Le=C.current;try{const Ae=Hr().workbuddyDesktop;if(!Ae)throw new Error(r("后端桥不可用"));const[oe,me]=await Promise.all([Ae.getLogs(Te),Ae.getLogStats()]),pe=Se?0:k.current?.scrollTop??0,Ce=Vw(oe,D.current);H(Ce),_(Qg(C.current,Bw(oe),E.current)),S.current=C.current===Le?pe:0,EK(me),Object.keys(Ce.categories).length&&P.current.category&&!Hw(Ce.categories,P.current.category)&&(Yg(I({category:""})),L({resetPage:!0}))}catch(Ae){de||(console.warn("读取运行日志失败:",Cw(Ae)),H(Vw(null,D.current)),_(Qg(C.current,[],E.current)))}},[H,_,B]),F=x.useCallback(le=>{le!==void 0&&(H(Vw(le,D.current)),_(Qg(C.current,Bw(le),E.current)))},[H,_]),$=x.useCallback(async le=>{if(Hw(D.current.categories,le)||await L({silent:!0}),!Hw(D.current.categories,le))return;const de=I({category:le});Yg(de),_(1),await L({resetPage:!0}),Hr().wbApp?.showPage?.("logs",{persist:!0})},[I,_,L]);x.useEffect(()=>{if(Po={load:L,render:F,showCategory:$,applyAutoConfig:(de,Se)=>w({ms:de,enabled:Se})},Kg){const de=Kg;Kg=null,F(de.data)}const le=Pw;return le!==null?(Pw=null,$(le)):L({silent:!0}),()=>{Po=null,N.current!==null&&window.clearTimeout(N.current),N.current=null}},[L,F,$]),x.useEffect(()=>{if(!j.enabled||j.ms<=0)return;const le=window.setInterval(()=>{document.hidden||Hr().wbApp?.currentPage!=="logs"||Mw||(Mw=!0,L({silent:!0}).finally(()=>{Mw=!1}))},j.ms);return()=>{window.clearInterval(le)}},[j,L]),x.useLayoutEffect(()=>{const le=S.current;if(le===null)return;S.current=null;const de=k.current;de&&(de.scrollTop=le)});async function X(le,de,Se){if(!Dw){Dw=!0,v({which:le,label:de});try{await Se()}catch(Te){$g(r("操作失败:{error}",{error:Cw(Te)}),"err")}finally{Dw=!1,v(null)}}}async function K(){const le=TK(P.current,T.current),de=le.length>0,Se=de?r("确定清空当前筛选出的 {count} 条日志?清空后无法恢复。",{count:Number(D.current.matched)||0}):r("确定清空全部运行日志?清空后无法恢复。"),Te=Hr().wbConfirm?.ask;Te&&await Te({title:r("清空运行日志"),html:Se,okText:r("清空"),okClass:"danger"})&&await X("clear",r("清空中…"),async()=>{const Le=Hr().workbuddyDesktop;if(!Le)throw new Error(r("后端桥不可用"));await Le.clearLogs(de?le:"all=1"),await L({resetPage:!0}),$g(r("运行日志已清空"))})}async function q(){await X("export",r("导出中…"),async()=>{const le=Hr().workbuddyDesktop;if(!le)throw new Error(r("后端桥不可用"));const de=await le.exportLogs();if(!(!de||de.canceled)){if(de.count===0){$g(r("暂无日志可导出"),"err");return}$g(r("✅ 已导出 {count} 条日志到 {file}",{count:String(de.count),file:String(de.file)}))}})}function Q(le){const de=Qg(le,D.current.entries,E.current);de!==C.current&&(_(de),S.current=0)}function G(le){if(le===E.current)return;const de=D.current.entries.length,Se=de?(C.current-1)*(E.current==="all"?de:E.current):0;z(le),_(le==="all"?1:Math.floor(Se/le)+1),S.current=0}function J(le){Lw=!0,Yg(I(le)),L({resetPage:!0})}function Y(le){Lw=!0,I({keyword:le}),N.current!==null&&window.clearTimeout(N.current),N.current=window.setTimeout(()=>{N.current=null,Yg(P.current),L({resetPage:!0})},pK)}function re(le){const de=Ew.includes(le)?le:Aw;de!==T.current&&(O(de),jK(de),L({resetPage:!0}))}const M=e.entries,U=h!=="all",Z=Math.max(1,U?Math.ceil(M.length/h):1),ae=Math.min(Math.max(1,f),Z),ce=U?M.slice((ae-1)*h,ae*h):M,W=M.length?U?(ae-1)*h+1:1:0,ue=M.length?U?W+ce.length-1:M.length:0,ve=e.categories,ee=e.matched===e.total?r("{n} 条",{n:e.total}):r("{matched} / {total} 条",{matched:e.matched,total:e.total});x.useEffect(()=>{const le=e.loaded?ee:"—";R.current!==le&&(R.current=le,Hr().wbApp?.renderTopbarStatus?.())},[e.loaded,ee]);function he(le,de){const Se=le.level||"",Te=NK(le);return s.jsxs("div",{className:`log-row ${Se}`,children:[s.jsx("span",{className:"log-rail",children:s.jsx("span",{className:`log-dot ${Se}`})}),s.jsxs("div",{className:"log-main",children:[s.jsxs("div",{className:"log-line",children:[s.jsx("span",{className:"log-cat",children:ve[le.category||""]||le.category}),s.jsx("span",{className:`log-lvl ${Se}`,children:bK[Se]||le.level}),s.jsx("span",{className:"msg",children:le.message})]}),Te?s.jsx("div",{className:"log-extra-wrap",children:s.jsx("span",{className:"extra",children:Te})}):null]}),s.jsx("span",{className:"time",children:SK(le.ts)})]},le.id??de)}const te=y?.which==="export",ke=y?.which==="clear";return s.jsxs("section",{className:"panel",id:"logs-panel-events",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("系统事件")}),s.jsx(ze,{id:"logs-badge",variant:"outline","data-tone":"",children:e.loaded?ee:"—"}),s.jsxs("div",{className:"head-actions",children:[s.jsx(ne,{id:"btn-logs-export",variant:"outline",disabled:y!==null,onClick:()=>{q()},children:te?y?.label:r("导出")}),s.jsx(ne,{id:"btn-logs-clear",variant:"destructive",disabled:y!==null,onClick:()=>{K()},children:ke?y?.label:r("清空")})]})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"log-filters",children:[s.jsx(En,{options:gK,value:c,onValueChange:re,"aria-label":r("事件日志时间范围"),className:"shrink-0"}),s.jsxs(dt,{value:a.level,onValueChange:le=>J({level:String(le??"")}),children:[s.jsx(pt,{id:"logs-level",className:"min-w-[120px]",title:r("按最低级别筛选"),"aria-label":r("按最低级别筛选"),children:s.jsx(ft,{children:Rw.find(le=>le.value===a.level)?.label??xK})}),s.jsx(mt,{children:Rw.map(le=>s.jsx($e,{value:le.value,children:le.label},le.value))})]}),s.jsxs(dt,{value:a.category,onValueChange:le=>J({category:String(le??"")}),children:[s.jsx(pt,{id:"logs-category",className:"min-w-[120px]",title:r("按分类筛选"),"aria-label":r("按分类筛选"),children:s.jsx(ft,{children:a.category?ve[a.category]||a.category:ZM})}),s.jsxs(mt,{children:[s.jsx($e,{value:"",children:ZM}),Object.entries(ve).map(([le,de])=>s.jsx($e,{value:le,children:de},le))]})]}),s.jsxs(Di,{className:"w-auto flex-auto",children:[s.jsx(Pi,{id:"logs-keyword",type:"search",placeholder:r("搜索消息关键词…"),autoComplete:"off","aria-label":r("搜索消息关键词"),value:a.keyword,onChange:le=>Y(le.currentTarget.value)}),s.jsx(Ii,{"aria-hidden":"true",children:"⌕"})]})]}),s.jsx("div",{className:"log-list",id:"log-list",ref:k,children:ce.length?ce.map((le,de)=>he(le,de)):s.jsx("div",{className:"log-empty",children:PK(e)})})]}),s.jsx($i,{total:M.length,range:U?{start:W,end:ue}:null,page:ae,pageCount:Z,size:h,sizes:dK,onSizeChange:G,onPageChange:Q})]})}const JM='.page[data-page="logs"]';let e2=!1;function t2(){if(e2)return;const e=document.querySelector(JM);e&&(e2=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(_K,{})))}document.querySelector(JM)?t2():document.addEventListener("DOMContentLoaded",t2,{once:!0}),window.wbLogsPanel={load:RK,render:OK,lastStats:MK,applyAutoRefresh:Uw,showCategory:DK};const zu=["maxInputTokens","maxOutputTokens","supportsToolCall","supportsImages","supportsVideo","supportsReasoning"],sp=["maxInputTokens","maxOutputTokens"],n2=["supportsToolCall","supportsImages","supportsVideo","supportsReasoning"],Bu={maxInputTokens:r("上下文窗口"),maxOutputTokens:r("最大输出 Token"),supportsToolCall:r("工具调用"),supportsImages:r("图片识别"),supportsVideo:r("视频识别"),supportsReasoning:r("支持思考")};r("工具"),r("图片"),r("视频"),r("思考");const LK=1e8;function Fw(e){return sp.includes(e)}function $w(e,t){if(Fw(e)){const a=typeof t=="number"?t:Number(t);return!Number.isFinite(a)||a<1||a>LK?null:Math.trunc(a)}return typeof t=="boolean"?t:null}function s2(e){const t={};if(!e||typeof e!="object")return t;const a=e;for(const o of zu){const c=$w(o,a[o]);c!==null&&(t[o]=c)}return t}function qw(e){return Array.isArray(e)?zu.filter(t=>e.some(a=>a===t)):[]}function Gw(e){return s2(e?.capabilities)}function r2(e){const t=Number(e);if(!Number.isFinite(t)||t<=0)return"—";const a=o=>o.toFixed(1).replace(/\.0$/,"");return t>=1e6?`${a(t/1e6)}M`:t>=1e3?`${a(t/1e3)}K`:String(Math.round(t))}function rp(e){const t=Number(e);return!Number.isFinite(t)||t<=0?r("未声明"):Math.round(t).toLocaleString("en-US")}function Kw(e){return e===!0?"on":e===!1?"off":"unset"}function zK(e){const t=e?.reasoningLevels;if(!Array.isArray(t))return null;const a=t.filter(c=>typeof c=="string"&&c.trim()!=="");if(!a.length)return null;const o=e?.reasoningDefaultLevel;return{levels:a,defaultLevel:typeof o=="string"?o.trim():""}}function BK(e,t,a,o=""){const c=Bu[e],d=a?r("(已被手动覆盖,弹窗里可恢复继承)"):"",f=HK(o);if(Fw(e))return t==null?r("{label}:上游未声明{suffix}",{label:c,suffix:d}):r("{label}:{value}(对下游声明的精确值){origin}{suffix}",{label:c,value:rp(t),origin:f,suffix:d});const p=Kw(t);return p==="on"?r("{label}:支持{origin}{suffix}",{label:c,origin:f,suffix:d}):p==="off"?r("{label}:不支持{origin}{suffix}",{label:c,origin:f,suffix:d}):r("{label}:上游未声明(下游会按不支持处理){suffix}",{label:c,suffix:d})}function Hu(e,t){const a=e?.capSources?.[t];return a==="upstream"||a==="modelsdev"||a==="user"?a:""}function HK(e){return e==="modelsdev"?r("(由 models.dev 补齐)"):e==="user"?r("(手动设定)"):""}function UK(e){const t={};for(const a of zu){const o=e[a];Fw(a)?t[a]=$w(a,o.trim()):t[a]=o==="on"?!0:o==="off"?!1:null}return t}function ap(){return window}const a2=e=>String(e??"").trim().toLowerCase(),Ks=(e,t)=>a2(e)===a2(t);function as(e){return typeof e=="string"&&e.startsWith("custom-")}function Ji(){return(ap().wbProviders?.customList?.()||[]).filter(e=>as(e?.id))}function l2(){return ap().wbProviders?.customList?.()||[]}function _o(e){return Ji().find(t=>t.id===e)||null}function VK(e){const t=s2(e),a={};for(const o of zu){const c=t[o];(typeof c=="number"||typeof c=="boolean")&&(a[o]=c)}return Object.keys(a).length?a:void 0}function o2(e){const t=(Array.isArray(e?.models)?e.models:[]).map(c=>{const d={id:String(c?.id??"").trim(),enabled:c?.enabled!==!1,reasoning:typeof c?.reasoning=="string"?c.reasoning:""};return d.capabilities=VK(c?.capabilities),d}).filter(c=>c.id),a=(Array.isArray(e?.mappings)?e.mappings:[]).map(c=>({alias:String(c?.alias??"").trim(),target:String(c?.target??"").trim(),enabled:c?.enabled!==!1,reasoning:typeof c?.reasoning=="string"?c.reasoning:""})).filter(c=>c.alias&&c.target);for(const c of t){const d=a.find(f=>Ks(f.alias,c.id)&&Ks(f.target,c.id));d&&(c.enabled=c.enabled&&d.enabled,c.reasoning=d.reasoning||c.reasoning)}const o=a.filter(c=>!(Ks(c.alias,c.target)&&t.some(d=>Ks(d.id,c.target))));return{models:t,mappings:o}}function i2(e){const t=_o(e);if(!t)return null;const a=o2(t),o=t.name||e,c=[],d=[];for(const f of a.models)c.push({id:f.id,name:"",provider:e,providerLabel:o,source:"",enabled:f.enabled,aliases:[],capabilities:f.capabilities||{},capOverrides:[]}),d.push({alias:f.id,target:f.id,provider:e,enabled:f.enabled,reasoning:f.reasoning,isDefault:!0,dangling:!1,carried:!0});for(const f of a.mappings){const p=c.find(h=>Ks(h.id,f.target));d.push({alias:f.alias,target:f.target,provider:e,enabled:f.enabled,reasoning:f.reasoning,isDefault:!1,dangling:!p,carried:!!p}),p&&p.aliases.push(f.alias)}return{models:c,mappings:d}}async function ec(e,t){const a=ap().wbProviders;if(!a?.customRequest)throw new Error(r("目录模块未就绪"));const o=_o(e);if(!o)throw new Error(r("该自定义提供商已不存在(可能已被删除),请刷新后重试"));const c=o2(o),d=t(c);return await a.customRequest("POST","/api/custom-providers/models",{providerId:e,models:c.models,mappings:c.mappings}),await a.refreshCustom?.(),d}async function c2(e,t,a,o={}){const{enabled:c,reasoning:d}=o;await ec(e,f=>{if(Ks(t,a)){const h=f.models.find(b=>Ks(b.id,a));if(!h)throw new Error(r("该提供商的清单里没有模型「{name}」",{name:a}));return c!==void 0&&(h.enabled=!!c),d!==void 0&&(h.reasoning=String(d??"")),null}const p=f.mappings.find(h=>Ks(h.alias,t)&&Ks(h.target,a));if(p)return c!==void 0&&(p.enabled=!!c),d!==void 0&&(p.reasoning=String(d??"")),null;if(c===!1)throw new Error(r("映射「{alias} → {target}」不存在",{alias:t,target:a}));return f.mappings.push({alias:t,target:a,enabled:c??!0,reasoning:String(d??"")}),null})}async function u2(e,t,a){await ec(e,o=>{const c=o.mappings.length;if(o.mappings=o.mappings.filter(d=>!(Ks(d.alias,t)&&Ks(d.target,a))),o.mappings.length===c)throw new Error(r("映射「{alias} → {target}」不存在",{alias:t,target:a}));return null})}async function d2(e,t){const a=String(t??"").trim();if(!a)throw new Error(r("请填写模型 ID"));await ec(e,o=>{if(o.models.some(c=>Ks(c.id,a)))throw new Error(r("模型「{name}」已存在(忽略大小写判重)",{name:a}));return o.models.push({id:a,enabled:!0,reasoning:""}),null})}async function FK(e,t){const a=(Array.isArray(t)?t:[]).map(o=>String(o??"").trim()).filter(Boolean);if(!a.length)throw new Error(r("没有选中任何模型"));return ec(e,o=>{let c=0;for(const d of a)o.models.some(f=>Ks(f.id,d))||(o.models.push({id:d,enabled:!0,reasoning:""}),c++);return c})}async function f2(e,t,a){await ec(e,o=>{const c=o.models.find(f=>Ks(f.id,t));if(!c)throw new Error(r("该提供商的清单里没有模型「{name}」",{name:t}));const d={...c.capabilities||{}};for(const[f,p]of Object.entries(a))p==null?delete d[f]:d[f]=p;return c.capabilities=Object.keys(d).length?d:void 0,null})}async function p2(e,t){return ec(e,a=>{const o=a.mappings.length;a.mappings=a.mappings.filter(d=>!Ks(d.target,t));const c=o-a.mappings.length;return a.models=a.models.filter(d=>!Ks(d.id,t)),{removedMappings:c}})}async function $K(e){const t=ap().wbProviders;if(!t?.customRequest)throw new Error(r("目录模块未就绪"));const a=await t.customRequest("POST","/api/custom-providers/fetch-models",{providerId:e}),o=(Array.isArray(a?.models)?a.models:[]).map(d=>String(d??"").trim()).filter(Boolean),c=await ec(e,d=>{let f=0;for(const p of o)d.models.some(h=>Ks(h.id,p))||(d.models.push({id:p,enabled:!0,reasoning:""}),f++);return f});return{total:o.length,added:Number(c)||0}}ap().wbModelsCustom={isCustom:as,list:Ji,listSource:l2,record:_o,buildView:i2,setBinding:c2,removeMapping:u2,addModel:d2,addModels:FK,removeModel:p2,setCapabilities:f2,fetchModels:$K};const fa="__custom__",qK=["off","none","minimal","low","medium","high","xhigh","max"];function lp(e,t){const a=m2(t);if(a.length)return a;const o=e?.reasoningLevels;return Array.isArray(o)&&o.length?o.filter(c=>typeof c=="string"):[...qK]}function m2(e){const t=e?.reasoningLevels;return Array.isArray(t)?t.filter(a=>typeof a=="string"&&a.trim()!==""):[]}function GK(e,t){const a=t.map(m2).filter(f=>f.length>0);if(!a.length||a.length!==t.length)return lp(e);const[o,...c]=a,d=o.filter(f=>c.every(p=>p.includes(f)));return d.length?d:lp(e)}function h2(e,t,a){return`${String(e??"").trim().toLowerCase()}${String(t??"").trim().toLowerCase()}${String(a??"").trim().toLowerCase()}`}function KK(e){const t=new Map;for(const a of Array.isArray(e)?e:[]){const o=typeof a?.reasoning=="string"?a.reasoning.trim():"";o&&t.set(h2(a.alias,a.target,a.provider),o)}return(a,o,c)=>t.get(h2(a,o,c))||""}function Wt(){return window}function Lo(e){return e instanceof Error?e.message:String(e)}function kr(e,t){Wt().wbApp?.toast?.(e,t)}function Yw(e){const t=Wt().wbApp?.esc;return t?t(e):String(e??"").replace(/[&<>"']/g,a=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[a]||a)}function YK(e){const t=Wt().formatTime??Wt().wbApp?.formatTime;return String(t?.(e)??"")}const g2=e=>String(e??"").trim().toLowerCase(),zo=(e,t)=>g2(e)===g2(t),x2=8,b2="workbuddy-desktop-models-filters",Xw=["all","enabled","disabled","mapped"],XK={all:r("全部"),enabled:r("已启用"),disabled:r("已禁用"),mapped:r("有映射")},QK=Xw.map(e=>({value:e,label:XK[e]})),Qw=["default","rate-asc","rate-desc"],ZK={default:r("默认"),"rate-asc":r("倍率升序"),"rate-desc":r("倍率降序")},WK=Qw.map(e=>({value:e,label:ZK[e]})),Zw=[{key:"check",label:r("选择"),align:"center"},{key:"model",label:r("上游模型")},{key:"rate",label:r("倍率")},{key:"source",label:r("来源")},{key:"budget",label:r("上下文 / 输出")},{key:"caps",label:r("能力")},{key:"alias",label:r("模型映射")},{key:"act",label:r("操作"),align:"right"}],v2=new Set(["rate","source"]),op="custom-all",Ww={models:[],mappings:[]},y2={provider:"all",state:"all",search:"",sort:"default"};function j2(){const e=Wt().wbFilterMemory;if(!e)return{...y2};const t=e.load(b2,{...y2});return{provider:String(t.provider||"all"),state:Xw.includes(t.state)?t.state:"all",search:String(t.search||""),sort:Qw.includes(t.sort)?t.sort:"default"}}const Zg=j2();let w2=!!Wt().wbFilterMemory,Wg=!1,ls={provider:Zg.provider,stateFilter:Zg.state,search:Zg.search,sort:Zg.sort,data:null,expanded:new Set,pending:new Set,mapping:null,customModel:null,capability:null};const Jw=new Set;function ip(){return ls}function JK(e){return Jw.add(e),()=>{Jw.delete(e)}}function zs(e){const t={...ls,...e},a=ex(t),o=ex(ls)!==a;ls=a===t.provider?t:{...t,provider:a},tY(),o&&tx();for(const c of Jw)c()}function Jg(e){Wt().wbFilterMemory?.save(b2,e)}function S2(){if(w2||Wg||!Wt().wbFilterMemory)return;w2=!0;const e=j2();(e.provider!==ls.provider||e.state!==ls.stateFilter||e.search!==ls.search||e.sort!==ls.sort)&&zs(e)}function ex(e){const t=e.provider;return t==="all"||t===op||Ji().some(a=>a.id===t)||Array.isArray(e.data?.models)&&e.data.models.some(a=>(a.provider||"")===t)||!e.data||!e0()?t:"all"}function Uu(){return ex(ls)}function e0(){return!!Wt().wbProviders}function Vu(){return Uu()===op}function N2(){return Vu()||as(Uu())}let cp=null;function t0(e){const t=_o(e);return(!cp||cp.id!==e||cp.record!==t)&&(cp={id:e,record:t,view:i2(e)||Ww}),cp.view}let up=null;function eY(){const e=l2();if(up&&up.directory===e)return up.view;const t=[],a=[];for(const o of Ji()){const c=t0(String(o.id||""));t.push(...c.models||[]),a.push(...c.mappings||[])}return up={directory:e,view:t.length||a.length?{models:t,mappings:a}:Ww},up.view}function n0(){const e=Uu();return as(e)?t0(e):e===op?eY():ls.data||Ww}function dp(){const e=n0();return Array.isArray(e.models)?e.models:[]}function k2(){const e=n0();return Array.isArray(e.mappings)?e.mappings:[]}let C2=(e,t,a)=>"";function tY(){C2=KK(k2())}function s0(){const e=new Map,t=Array.isArray(ls.data?.models)?ls.data.models:[];for(const a of t){const o=a.provider||"";if(!o)continue;const c=e.get(o)||{label:a.providerLabel||o,n:0};c.n++,e.set(o,c)}return e}function nY(){const e=new Map;for(const t of Ji()){const a=String(t.id||"");if(!a)continue;const o=t0(a);e.set(a,{label:String(t.name||a),n:(o.models||[]).length})}return e}function sY(){return[...s0().keys()]}function rY(e){const a=(Array.isArray(ls.data?.models)?ls.data.models:[]).find(o=>o.provider===e);return Number(a?.refreshedAt)||0}function r0(){const e=new Map;for(const t of dp()){const a=t.provider||"";a&&!e.has(a)&&e.set(a,r(t.providerLabel||a))}return[...e].map(([t,a])=>({id:t,label:a}))}function T2(e){return e?dp().filter(t=>(t.provider||"")===e).sort((t,a)=>+(t.enabled===!1)-+(a.enabled===!1)).map(t=>({id:t.id,label:t.name&&t.name!==t.id?r("{id}({name})",{id:t.id,name:t.name}):t.id,off:t.enabled===!1})):[]}function aY(){const e=[],t=Wt().wbProviders?.all?.();if(Array.isArray(t))for(const a of t){const o=String(a?.id||"");o&&e.push({id:o,label:r(String(a?.label||o))})}for(const a of Ji()){const o=String(a.id||"");o&&e.push({id:o,label:String(a.name||o)})}return e.length?e:r0()}let fp=null,a0=null;function E2(){const e=fp?fp.apply(Zw):Zw;return N2()?e.filter(t=>!v2.has(t.key)):e}function tx(){Wt().wbColSettings?.syncStaticHead("models",a0,N2()?v2:null)}function lY(){if(fp)return;fp=Wt().wbColSettings?.register({id:"models",label:r("模型管理表"),columns:Zw,mount:()=>document.querySelector('.page[data-page="gateway"] .panel-head .head-actions'),buttonPlacement:"last",onChange:()=>{tx(),tc()}})||null,fp&&tc()}let nx=0,l0=!1;async function sx({force:e=!1}={}){if(l0&&!e)return;const t=++nx;l0=!0,S2();try{const a=await Wt().workbuddyDesktop?.getModelManage();if(t!==nx)return;zs({data:a&&Array.isArray(a.models)?a:null})}catch(a){if(t!==nx)return;tc(),kr(r("读取模型清单失败:{message}",{message:Lo(a)}),"err")}finally{t===nx&&(l0=!1)}}async function A2(){try{await Wt().wbProviders?.refreshCustom?.()}catch{}await sx({force:!0})}function tc(){zs({})}function nc(e){const t=e;if(t&&Array.isArray(t.models)){zs({data:t});return}tc()}async function rx(e,t,a,o){if(as(e))return c2(e,t,a,o);const c=Wt().workbuddyDesktop;if(!c)throw new Error(r("后端桥不可用"));return c.addModelMapping(t,a,e,o.reasoning,o.enabled)}async function oY(e,t,a){if(as(e))return u2(e,t,a);const o=Wt().workbuddyDesktop;if(!o)throw new Error(r("后端桥不可用"));return o.removeModelMapping(t,a,e)}async function iY(e,t){if(as(e))return d2(e,t);const a=Wt().workbuddyDesktop;if(!a)throw new Error(r("后端桥不可用"));return a.addCustomModel(e,t)}async function R2(e,t){if(as(e))return p2(e,t);const a=Wt().workbuddyDesktop;if(!a)throw new Error(r("后端桥不可用"));return a.removeCustomModel(e,t)}async function cY(e,t,a){if(as(e))return f2(e,t,a);const o=Wt().workbuddyDesktop;if(!o)throw new Error(r("后端桥不可用"));return o.setModelCapabilities(e,t,a)}async function o0(e,t,a){if(!ls.pending.has(e)){zs({pending:new Set(ls.pending).add(e)});try{nc(await t()),a&&kr(a)}catch(o){kr(r("操作失败:{message}",{message:Lo(o)}),"err")}finally{const o=new Set(ls.pending);o.delete(e),zs({pending:o})}}}function pp(e){return Fu(e).some(t=>t.enabled!==!1)}function Fu(e){const t=e.provider||"",a=k2().filter(p=>zo(p.target,e.id)&&(!p.provider||zo(p.provider,t))),o=new Map;for(const p of a){const h=String(p.alias).toLowerCase();(!o.has(h)||p.provider)&&o.set(h,p)}const c=String(e.id).toLowerCase(),d=o.get(c);o.delete(c);const f=[{alias:e.id,target:e.id,provider:t,enabled:e.enabled!==!1&&d?.enabled!==!1,isDefault:!0}];return f.push(...o.values()),f}const sc=e=>`${e.provider||""}:${e.id}`,i0=(e,t,a)=>`${e}:${t}:${a||""}`;function uY(e){zs({expanded:new Set(ls.expanded).add(e)})}function dY(e){const t=new Set(ls.expanded);t.delete(e),zs({expanded:t})}function fY(e){const t=Xw.includes(e)?e:"all";t!==ls.stateFilter&&(Wg=!0,zs({stateFilter:t}),Jg({state:t}))}function pY(e){const t=Qw.includes(e)?e:"default";t!==ls.sort&&(Wg=!0,zs({sort:t}),Jg({sort:t}))}function mY(e){Wg=!0,zs({search:e}),Jg({search:e})}function mp(e){zs({provider:String(e??"").trim()||"all"}),Jg({provider:ls.provider}),tx()}async function hY(e){const t=Wt().wbCustomProvidersUi;if(!t?.remove){kr(r("删除入口未就绪,请重试或重启应用"),"err");return}await t.remove(e)&&await sx({force:!0})}function gY(){Wt().wbAccountAddForms?.openNewCustomForm?.()}function O2(e){zs({mapping:e})}function xY(){zs({mapping:null})}function bY(){const e=Uu(),t=as(e);zs({customModel:{provider:t||e!=="all"&&e!==op?e:"",locked:t}})}function vY(){zs({customModel:null})}function M2(e,t){zs({capability:{provider:e,id:t}})}function yY(){zs({capability:null})}function D2(e,t){return dp().find(a=>(a.provider||"")===e&&zo(a.id,t))||null}function c0(e){if(as(e)){const t=_o(e)?.name;return typeof t=="string"&&t||e}return r(Wt().wbProviders?.labelOf?.(e)||e)}function I2(){const e=Uu(),t=as(e),a=t?_o(e)?.name||e:r("内置提供商");Wt().wbModelsFetchModal?.open({providerId:e===op?"":e,custom:t,name:a,onDone:()=>tc(),onRefreshed:()=>{sx({force:!0})}})}window.wbModelsPanel={render:tc,load:sx,refreshAll:A2,refreshModels:I2,visibleColumns:E2,selectProvider:mp,builtinProviders:sY,providerRefreshedAt:rY};function u0(e,t,a){return C2(e,t,a)}function jY(e){a0=e}function wY(){const e=a0;if(!e)return;const t=o=>Object.keys(o).some(c=>c.startsWith("__reactFiber$")||c.startsWith("__reactInternalInstance$"));for(const o of[...e.children])o.tagName==="TBODY"?o.id!=="models"&&o.remove():o.tagName==="TR"&&!t(o)&&o.remove();const a=e.querySelector("tbody#models");if(a)for(const o of[...a.children])t(o)||o.remove()}const SY=e=>[{value:"inherit",label:e},{value:"on",label:r("支持")},{value:"off",label:r("不支持")}];function NY(e){const t=Kw(e);return r(t==="on"?"支持":t==="off"?"不支持":"未声明")}function P2(e,t,a,o,c=""){const d=t!=null,f=sp.includes(e)?rp(t):NY(t);return a?o?r("已填写:对下游声明 {value}",{value:f}):r("已覆盖:对下游声明 {value}",{value:f}):o?r("未填写(下游按未声明处理)"):d?c==="modelsdev"?r("models.dev 补齐:对下游声明 {value}",{value:f}):r("继承上游:{value}",{value:f}):r("上游未声明(下游会按不支持处理)")}function kY(e,t,a){return a?zu.filter(o=>{const c=e[o];return c!=null}):t}function CY(e,t){const a={};for(const o of zu){const c=t.includes(o),d=e[o];sp.includes(o)?a[o]=c&&typeof d=="number"?String(d):"":a[o]=c?d===!0?"on":"off":"inherit"}return a}function TY({context:e,onClose:t}){const a=as(e.provider),o=D2(e.provider,e.id),c=zK(o),d=Gw(o),f=kY(d,qw(o?.capOverrides),a),[p,h]=x.useState(()=>CY(d,f)),[b,y]=x.useState(""),[v,j]=x.useState(!1);if(!o)return s.jsx(Yt,{open:!0,onOpenChange:E=>{E||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("模型能力")})}),s.jsx(Lt,{children:s.jsx("p",{className:"text-sm leading-[1.7] text-subtle",children:r("这一行已不在当前清单里(模型被移除、或目录刷新后上游不再提供它)。关闭后刷新列表再试。")})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")})]})]})});const w=o.id,k=o.providerLabel||c0(e.provider),S=r(a?"未声明":"继承上游"),N=r(a?"清除":"恢复继承");function R(E){const D=d[E];return P(E)?"":a?r("未填写"):typeof D=="number"?r("继承上游 {value}",{value:rp(D)}):r("上游未声明")}function P(E){return f.includes(E)}function T(E,D){h(I=>({...I,[E]:D}))}async function C(){if(!v){for(const E of sp){const D=p[E].trim();if(D&&$w(E,D)===null){y(r("{label}要填 1 ~ 1 亿之间的整数(留空 = {inherit})",{label:Bu[E],inherit:S}));return}}j(!0),y(r("保存中…"));try{nc(await cY(e.provider,e.id,UK(p))),t(),kr(r("✅ 已保存 {id} 的能力位({provider})",{id:w,provider:k}))}catch(E){y(r("保存失败:{message}",{message:Lo(E)})),j(!1)}}}return s.jsx(Yt,{open:!0,onOpenChange:(E,D)=>{if(!E){if(v){D.cancel();return}t()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("模型能力")})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"rounded-md border border-border bg-surface-inset px-3 py-2.5 font-mono text-[12px] text-subtle",children:[s.jsx("b",{className:"text-primary-fg",children:o.id}),r("({provider})",{provider:k})]}),sp.map(E=>s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-[7px]",children:[s.jsx(Je,{htmlFor:`cap-${E}`,children:Bu[E]}),P(E)?s.jsx(ne,{variant:"ghost",size:"2xs",disabled:v,title:r(a?"清除这一项(回到未声明)":"清除覆盖,回到上游声明值"),onClick:()=>T(E,""),children:N}):null]}),s.jsx(Fe,{id:`cap-${E}`,inputMode:"numeric",autoComplete:"off",spellCheck:!1,placeholder:R(E),disabled:v,value:p[E],onChange:D=>T(E,D.currentTarget.value),onKeyDown:D=>{D.key==="Enter"&&(D.preventDefault(),C())}}),s.jsx("p",{className:"text-xs leading-[1.6] text-subtle",children:P2(E,d[E]??null,P(E),a,Hu(o,E))})]},E)),n2.map(E=>s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{children:Bu[E]}),s.jsx(En,{options:SY(S),value:p[E],"aria-label":Bu[E],className:"self-start",onValueChange:D=>T(E,String(D))}),s.jsx("p",{className:"text-xs leading-[1.6] text-subtle",children:P2(E,d[E]??null,P(E),a,Hu(o,E))})]},E)),c?s.jsxs("div",{className:"rounded-md border border-border bg-surface-inset px-3 py-2.5 text-xs leading-[1.7] text-subtle",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-x-2 gap-y-1",children:[s.jsx("span",{children:r("可配思考档位")}),s.jsx("span",{className:"font-mono text-[12px] text-primary-fg",children:c.levels.join(" / ")}),c.defaultLevel?s.jsxs("span",{children:[r("(默认 "),s.jsx("span",{className:"font-mono text-[12px] text-primary-fg",children:c.defaultLevel}),r(")")]}):null]}),s.jsx("div",{className:"mt-1",children:r("这是模型自己能配的档位(来自上游目录),只读;要改某一档请到映射弹窗里选。")})]}):null,s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("这几项是给"),s.jsx("b",{children:r("下游客户端")}),r("看的能力声明("),s.jsx("code",{children:"/v1/models"}),r(" 里的 "),s.jsx("code",{children:"max_input_tokens"})," / ",s.jsx("code",{children:"supports_*"}),r(" 与 "),s.jsx("code",{children:"input_modalities"}),r("),下游按它们决定发不发图片、按多大的窗口堆历史。"),s.jsx("b",{children:r("不影响网关的转发与路由")}),r("。上游清单给的值不准时,在这里改;"),r(a?"这家的清单是你自己登记的,不填的项下游按未声明处理。":"「恢复继承」会把这一项交还给上游清单的值。")]}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:b})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:v,onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:v,onClick:()=>{C()},children:r("保存")})]})]})})}function hp(){return window}const EY="你好",_2=4e3,AY=[{value:"chat_completions",label:"OpenAI - Chat Completions"},{value:"responses",label:"OpenAI - Responses"},{value:"anthropic",label:"Anthropic - Messages"}],RY={chat_completions:"Chat Completions",responses:"Responses",anthropic:"Anthropic Messages"},OY="direct",MY={remote:r("远程目录"),builtin:r("内置清单"),manual:r("手动登记")},DY=[{test:e=>e===429,hint:r("该账号对这个模型正在限额冷却,等一会儿自己会好;也可以先测别的账号。")},{test:e=>e===401||e===403,hint:r("上游拒绝了这条登录态:重新登录一次,或把这条账号删掉。")},{test:e=>e===404,hint:r("上游不认识这个模型名:先点「获取模型」刷新清单,或核对默认绑定指向的上游模型。")},{test:e=>e===504,hint:r("上游没在预算内给完回答。可以只勾一个账号再测一次,看是普遍慢还是某一个账号慢。")},{test:e=>e>=500,hint:r("多半是上游自己的问题,过一会儿再试。同一个错误出现在所有账号上时,先查模型目录与映射。")}];function L2(){return hp().wbApp?.getState?.()?.accounts?.accounts||[]}function z2(e){return L2().filter(t=>(t.provider||mu)===e&&t.available!==!1&&t.enabled!==!1).sort(Jh)}function B2(e){const t=String(e.email||"").trim();return t&&cr(e.provider).emailAsName?t:gu(e)||t||r("未命名账号")}function IY(){const e=globalThis.crypto?.randomUUID?.();if(e)return e;const t=a=>Array.from({length:a},()=>Math.floor(Math.random()*16).toString(16)).join("");return`${t(8)}-${t(4)}-4${t(3)}-a${t(3)}-${t(12)}`}function d0(e){const t=Number(e);return!Number.isFinite(t)||t<=0?"—":t<1e3?`${Math.round(t)} ms`:`${(t/1e3).toFixed(t<1e4?2:1)} s`}function PY(e,t){return z2(e).length?"":r("该提供商没有可用账号(要在账号页启用一个、且凭证完整),一行都发不出去")}function H2({children:e,plain:t=!1}){return s.jsxs("p",{className:t?"flex items-center gap-2 text-xs leading-[1.6] text-subtle":"flex gap-2 rounded-md border border-border bg-surface-2 px-3 py-2.5 text-xs leading-[1.65] text-subtle",children:[s.jsx("span",{"aria-hidden":"true",className:t?"size-4 flex-none rounded-full border border-border-strong text-center text-[10px] leading-[14px]":"mt-px size-4 flex-none rounded-full border border-border-strong text-center text-[10px] leading-[14px]",children:"i"}),s.jsx("span",{children:e})]})}function _Y({open:e,label:t,text:a,onToggle:o}){return s.jsxs("div",{className:"overflow-hidden rounded-sm border border-border",children:[s.jsxs(ne,{variant:"ghost",size:"xs",className:"w-full","aria-expanded":e,onClick:o,children:[s.jsx("span",{className:"truncate",children:t}),s.jsx("span",{"aria-hidden":"true",className:"ml-auto text-[10px]",children:e?"▴":"▾"})]}),e?s.jsx("div",{className:"border-t border-hairline bg-surface px-2.5 py-2",children:s.jsx("pre",{className:"whitespace-pre-wrap font-mono text-[11.5px] leading-[1.65] text-subtle",children:a})}):null]})}function LY(e){const[t,a]=x.useState(()=>Date.now());return x.useEffect(()=>{if(!e)return;a(Date.now());const o=window.setInterval(()=>a(Date.now()),400);return()=>window.clearInterval(o)},[e]),t}function U2(e){if(e.transport||!e.result||e.result.error)return!1;const t=Number(e.result.status)||0;return t>=200&&t<300}function zY({target:e,onClose:t}){const a=e.provider,o=D2(a,e.id),c=z2(a),d=vj(L2()),[f,p]=x.useState(""),[h,b]=x.useState(EY),[y,v]=x.useState("chat_completions"),[j,w]=x.useState(""),[k,S]=x.useState(null),[N,R]=x.useState(""),[P,T]=x.useState(""),[C,E]=x.useState(!0),[D,I]=x.useState(()=>{const te=c.find(ke=>!Cf(ke,e.id))||c[0];return te?[te.id]:[]}),[O,_]=x.useState([]),[z,H]=x.useState(()=>new Set),B=x.useRef(0),L=x.useRef([]);L.current=O;const F=O.some(te=>te.state==="running"),$=LY(F);x.useEffect(()=>{let te=!0;return(async()=>{try{const ke=hp().workbuddyDesktop?.getProxyPool;if(typeof ke!="function")throw new Error(r("当前环境不支持代理池"));const le=await ke();if(!te)return;if(!le||typeof le!="object"||!Array.isArray(le.items))throw new Error(r("代理池响应异常"));S(le.items),R("")}catch(ke){if(!te)return;S([]),R(Lo(ke))}})(),()=>{te=!1}},[]);const X=x.useCallback((te=!1)=>{const ke=L.current.filter(le=>le.state==="running");B.current+=1;for(const le of ke)hp().workbuddyDesktop?.terminateStatsRequest?.(le.testId)?.catch(()=>{});_([]),ke.length&&!te&&kr(r("已中止在途测试({n} 个账号)",{n:ke.length}))},[]);x.useEffect(()=>()=>{X(!0)},[X]);async function K(te,ke){const le={provider:a,model:e.id,account_id:te.accountId,prompt:h.trim(),system_prompt:f.trim(),reasoning:P,stream:C,protocol:y,...j?{proxy:j}:{},test_id:te.testId},de=Se=>{B.current===ke&&_(Te=>Te.map(Le=>Le.testId===te.testId?{...Le,...Se}:Le))};try{const Se=await hp().workbuddyDesktop?.testModel(le);if(!Se){de({state:"done",transport:r("桥接调用返回空(本机网关没有响应这次测试)")});return}de({state:"done",result:Se})}catch(Se){de({state:"done",transport:Lo(Se)})}}function q(){const te=c.filter(Se=>D.includes(Se.id));if(!te.length){kr(r("至少选一个测试账号"),"err");return}const ke=B.current+1;B.current=ke;const le=Date.now(),de=te.map(Se=>({accountId:Se.id,label:B2(Se),position:d.get(Se.id)?.position||0,testId:IY(),startedAt:le,state:"running"}));H(new Set),_(de);for(const Se of de)K(Se,ke)}function Q(){F?X():_([])}const G=s.jsx("span",{className:"ml-2 font-mono text-[12px] font-normal text-subtle",children:e.id});if(!o)return s.jsx(Yt,{open:!0,onOpenChange:te=>{te||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("测试模型")})}),s.jsx(Lt,{children:s.jsx("p",{className:"text-sm leading-[1.7] text-subtle",children:r("这一行已不在当前清单里(模型被移除、或目录刷新后上游不再提供它)。关闭后刷新列表再试。")})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")})]})]})});const J=Fu(o).find(te=>te.isDefault)?.enabled===!1,Y=u0(o.id,o.id,a),re=Fu(o).filter(te=>!te.isDefault).map(te=>te.alias),M=lp(ip().data,o).filter(te=>te!=="off"&&te!=="none"),U=J?r("跟随映射(该行未启用,本次不注入)"):Y?r("跟随映射(当前 {level})",{level:Y}):r("跟随映射(未绑定等级)"),Z=[r("以模型本名直发"),re.length?r("另有 {n} 条别名映射({aliases}),别名不参与本次",{n:re.length,aliases:re.join(r("、"))}):"",J?r("该行当前未启用:测试照常按本名直发(「先测通、再决定要不要启用」正是这颗按钮的用法),但本行的思考等级绑定不参与本次,生产路由也要等绑定打开后才会放行"):Y?r("映射上绑定的思考等级是 {level},「跟随映射」按它注入",{level:Y}):r("映射上未绑定思考等级,「跟随映射」等于这次不注入")].filter(Boolean).join(r(";"))+r("。"),ae=hp().wbProviders?.PROTOCOL_OPTIONS||AY,ce=ae.find(te=>te.value===y)?.label||y,W=[{value:"",label:r("跟随账号配置")},{value:OY,label:r("直连(不使用代理)")},...(k??[]).map(te=>({value:`${Qa}${te.id}`,label:fu(te)}))];k===null?W.push({value:"__hint_pool__",label:r("正在读取代理列表…"),disabled:!0}):k.length||W.push({value:"__hint_pool__",label:r(N?"代理列表读取失败":"还没有代理(去「网络代理」页添加)"),disabled:!0});const ue=W.find(te=>te.value===j)?.label||r("跟随账号配置"),ve=c.map(te=>({value:te.id,label:`#${d.get(te.id)?.position||0} ${B2(te)}`+(Cf(te,e.id)?r(" · 限额中"):"")}));function ee(te){const ke=(Ae,oe)=>s.jsxs("div",{className:"flex items-center gap-2.5 border-b border-hairline px-3 py-2",children:[Ae,s.jsx("b",{className:"min-w-0 truncate text-[12.5px] text-foreground",title:te.label,children:te.label}),te.position?s.jsxs("span",{className:"flex-none text-xs text-subtle",children:["#",te.position]}):null,s.jsx("span",{className:"ml-auto flex-none font-mono text-[11.5px] tabular-nums text-subtle",children:oe})]},"head");if(te.state==="running"){const Ae=($-te.startedAt)/1e3;return s.jsxs("div",{className:"flex items-center gap-2.5 rounded-md border border-border bg-surface-2 px-3 py-2.5 text-xs text-subtle",children:[s.jsx(of,{className:"flex-none"}),s.jsxs("span",{className:"min-w-0 truncate",children:[r("账号 "),s.jsx("b",{className:"text-foreground",children:te.label}),r(" 已发出,等待上游首帧…")]}),s.jsx("span",{className:"ml-auto flex-none font-mono tabular-nums",children:r("已等待 {seconds}s",{seconds:Ae.toFixed(1)})})]},te.testId)}const le=te.result;if(!U2(te)){const Ae=Number(le?.status)||0,oe=DY.find(me=>me.test(Ae))?.hint??(te.transport?r("确认桌面端还在运行,再重试一次。"):"");return s.jsxs("div",{className:"rounded-md border border-border bg-surface-2",children:[ke(s.jsx(ze,{shape:"tag",variant:"destructive",className:"flex-none",children:Ae||r("失败")}),r("用时 {time}",{time:d0(le?.duration_ms)})),s.jsxs("div",{className:"flex flex-col gap-1.5 px-3 py-2.5",children:[s.jsxs("div",{className:"text-[12.5px] leading-[1.7]",children:[te.transport?s.jsxs(s.Fragment,{children:[s.jsx("b",{className:"text-destructive",children:r("本机网关没有返回结论")}),r(":"),te.transport]}):s.jsxs(s.Fragment,{children:[s.jsx("b",{className:"text-destructive",children:r("测试未通过")}),r(":"),le?.error||r("上游没有给出可读的错误说明")]}),Number(le?.attempts)>1?r("(中间共尝试 {n} 次)",{n:Number(le?.attempts)}):""]}),oe?s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:oe}):null]})]},te.testId)}const de=String(le?.reply??""),Se=String(le?.reasoning??""),Te=`think-${te.testId}`,Le=[le?.upstream_model&&le.upstream_model!==e.id?r("上游 {model}",{model:le.upstream_model}):"",le?.upstream_reasoning?r("思考等级 {level}",{level:le.upstream_reasoning}):"",le?.protocol&&le.protocol!=="chat_completions"?RY[le.protocol]||le.protocol:"",le?.proxy?r("节点 {proxy}",{proxy:le.proxy}):"",Number(le?.attempts)>1?r("尝试 {n} 次",{n:Number(le?.attempts)}):""].filter(Boolean).join(" · ");return s.jsxs("div",{className:"rounded-md border border-border bg-surface-2",children:[ke(s.jsx(ze,{shape:"tag",variant:"success",className:"flex-none",children:Number(le?.status)||200}),r("用时 {time} · 首字 {ttfb}",{time:d0(le?.duration_ms),ttfb:d0(le?.ttfb_ms)})),s.jsxs("div",{className:"flex flex-col gap-2 px-3 py-2.5",children:[s.jsxs("div",{className:"flex items-center gap-2 text-[11.5px] text-subtle",children:[s.jsx("span",{className:"flex-none",children:r("回复")}),Le?s.jsx("span",{className:"min-w-0 truncate",title:Le,children:Le}):null,s.jsx(ne,{variant:"ghost",size:"2xs",className:"ml-auto flex-none","data-copy":de,children:r("复制")})]}),s.jsx("div",{className:"max-h-[220px] overflow-y-auto whitespace-pre-wrap rounded-sm border border-border bg-surface px-3 py-2 text-[12.5px] leading-[1.7]",children:de||s.jsx("span",{className:"text-subtle",children:r("(上游这一次返回了空正文)")})}),Se?s.jsx(_Y,{open:z.has(Te),label:r("思考过程({n} 字)",{n:Se.length}),text:Se,onToggle:()=>H(Ae=>{const oe=new Set(Ae);return oe.has(Te)?oe.delete(Te):oe.add(Te),oe})}):null]})]},te.testId)}function he(){if(F){const ke=O.length-O.filter(le=>le.state==="running").length;return s.jsxs(s.Fragment,{children:[O.length>1?s.jsxs("p",{className:"text-xs text-subtle",children:[r("正在测 "),s.jsx("b",{className:"text-foreground",children:O.length}),r(" 个账号"),ke?s.jsxs(s.Fragment,{children:[r(",已完成 "),s.jsx("b",{className:"text-foreground",children:ke})]}):null,r("。")]}):null,O.map(le=>ee(le))]})}const te=O.filter(U2).length;return s.jsxs(s.Fragment,{children:[O.length>1?s.jsxs("p",{className:"text-xs text-subtle",children:[s.jsx("b",{className:te?"text-success":"text-foreground",children:te}),r(" 成功 ·"),s.jsxs("b",{className:O.length-te?"text-destructive":"text-foreground",children:[" ",O.length-te]}),r(" 失败")]}):null,O.map(ke=>ee(ke)),te===0?s.jsxs(H2,{children:[r("两边原因不一样时各自处理。如果"),s.jsx("b",{className:"text-foreground",children:r("同一条错误出现在所有账号上")}),r(",通常就不是账号问题了:先确认这个模型还在上游目录里(「获取模型」刷一次),再看默认绑定指向的上游模型对不对。")]}):null]})}return s.jsx(Yt,{open:!0,onOpenChange:te=>{te||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsxs(Ut,{children:[r("测试模型"),G]})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"flex items-center gap-2 rounded-md border border-border bg-surface-inset px-3 py-2.5",children:[s.jsx("span",{className:"min-w-0 flex-1 truncate font-mono text-[12.5px] font-semibold text-primary-fg",title:o.id,children:o.id}),s.jsx(ze,{shape:"tag",variant:"brand",children:c0(a)}),s.jsx(ze,{shape:"tag",variant:"outline",children:as(a)?r("自定义家"):MY[o.source]||r("来源未知")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("本次测试的发送口径")}),children:"?"}),s.jsx(Fi,{children:Z})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-system",children:r("系统提示词")}),s.jsx(Mi,{id:"model-test-system",rows:2,maxLength:_2,placeholder:r("留空则不携带;设置页的提示词模式照常生效"),value:f,onChange:te=>p(te.currentTarget.value)})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-prompt",children:r("用户提示词")}),s.jsx(Mi,{id:"model-test-prompt",rows:2,maxLength:_2,placeholder:r("留空用默认问候「你好」"),value:h,onChange:te=>b(te.currentTarget.value)})]}),s.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-protocol",children:r("对话协议")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("对话协议的说明")}),children:"?"}),s.jsx(Fi,{children:r("按所选网关对话协议组装请求并校验响应转换(Chat Completions / Responses / Anthropic Messages)。")})]})]}),s.jsxs(dt,{value:y,onValueChange:te=>v(String(te)),children:[s.jsx(pt,{id:"model-test-protocol",className:"w-full",children:s.jsx(ft,{className:"min-w-0 truncate",children:ce})}),s.jsx(mt,{children:ae.map(te=>s.jsx($e,{value:te.value,children:te.label},te.value))})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-proxy",children:r("测试节点")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("测试节点的说明")}),children:"?"}),s.jsx(Fi,{children:r("仅本次测试临时生效,不修改账号保存的代理配置。可选「网络代理」页里的节点或强制直连。")})]})]}),s.jsxs(dt,{value:j,onValueChange:te=>w(String(te)),children:[s.jsx(pt,{id:"model-test-proxy",className:"w-full",children:s.jsx(ft,{className:"min-w-0 truncate",children:ue})}),s.jsx(mt,{children:W.map(te=>s.jsx($e,{value:te.value,disabled:te.disabled,children:te.label},te.value))})]})]})]}),s.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-reasoning",children:r("思考等级")}),s.jsxs(dt,{value:P,onValueChange:te=>T(String(te)),children:[s.jsx(pt,{id:"model-test-reasoning",className:"w-full",children:s.jsx(ft,{children:P?r("{level}(本次指定)",{level:P}):U})}),s.jsxs(mt,{children:[s.jsx($e,{value:"",children:U}),M.map(te=>s.jsx($e,{value:te,children:r("{level}(本次指定)",{level:te})},te))]})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-1.5",children:[s.jsx(Je,{htmlFor:"model-test-stream",children:r("流式请求")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("流式请求的说明")}),children:"?"}),s.jsx(Fi,{children:r("默认开,与真实请求一致:可同时验证 SSE 链路与首字延迟。")})]})]}),s.jsx(Zn,{id:"model-test-stream",checked:C,onCheckedChange:te=>E(!!te)})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(Je,{htmlFor:"model-test-accounts",children:r("测试账号")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("测试账号的说明")}),children:"?"}),s.jsx(Fi,{children:r("勾几个就并行测几次;默认选队列里最靠前的一个。")})]}),s.jsx(ne,{variant:"ghost",size:"xs",className:"ml-auto",disabled:!c.length||D.length===c.length,onClick:()=>I(c.map(te=>te.id)),children:r("全选({n})",{n:c.length})})]}),s.jsx(Kh,{id:"model-test-accounts",value:D,onValueChange:I,options:ve,placeholder:r("选一个账号(至少一个)"),searchPlaceholder:r("搜索账号…"),emptyHint:r("这家没有可用账号(要在账号页启用一个、且凭证完整)")})]}),s.jsx(H2,{plain:!0,children:r("真实链路 · 消耗少量额度 · 日志带「测试」标记,不计报表")})]}),s.jsxs(tn,{className:"justify-end",children:[s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")}),s.jsx(ne,{variant:"default",disabled:!D.length||!c.length,onClick:q,children:r("开始测试")})]}),s.jsx(Yt,{open:O.length>0,onOpenChange:te=>{te||Q()},children:s.jsxs(Xt,{overlayForceRender:!0,className:"w-[min(680px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsxs(Ut,{children:[r(F?"测试中…":"测试结果"),G]})}),s.jsx(Lt,{children:he()}),s.jsx(tn,{className:"justify-end",children:F?s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"mr-auto text-xs text-subtle",children:r("关闭即中止")}),s.jsx(ne,{variant:"outline",onClick:()=>X(),children:r("中止测试")}),s.jsx(ne,{variant:"default",disabled:!0,children:r("测试中…")})]}):s.jsxs(s.Fragment,{children:[s.jsx(ne,{variant:"outline",onClick:Q,children:r("关闭")}),s.jsx(ne,{variant:"default",onClick:q,children:r("再测一次")})]})})]})})]})})}const V2=[{value:"enable",label:r("启用")},{value:"disable",label:r("禁用")},{value:"reasoning",label:r("设置思考等级")},{value:"delete",label:r("删除")}];function F2(e){return e.source==="manual"||as(e.provider)}function BY(e){return(e.name&&e.name!==e.id?r("{name}({id})",{name:e.name,id:e.id}):e.id)||e.id}function HY({models:e,onClose:t,onDone:a}){const[o,c]=x.useState("enable"),d=GK(ip().data,e),[f,p]=x.useState(()=>({select:d[0]||"",custom:""})),[h,b]=x.useState(!1),[y,v]=x.useState(""),j=f.select===fa?f.custom.trim():f.select,w=e.filter(F2).length,k=V2.find(R=>R.value===o)?.label||r("操作");async function S(R){return Promise.resolve(Wt().wbConfirm?.ask?.({title:r("删除选中的模型"),html:r("确定删除选中的 {count} 个模型登记?删除后 /v1/models 不再广告它们、请求也会被拒。",{count:R})+(e.length>R?"
    "+r("另有 {n} 个非手动登记的模型将被跳过。",{n:e.length-R}):""),okText:r("删除"),okClass:"danger"})??!1)}async function N(){if(h)return;if(!e.length){kr(r("没有选中的模型"),"err");return}if(o==="reasoning"&&f.select===fa&&!j){v(s.jsx("span",{className:"text-destructive",children:r("请填写自定义思考等级,或改选候选档 / 「清除」")}));return}if(o==="delete"){if(w===0){v(s.jsx("span",{className:"text-destructive",children:r("选中的模型都不是手动登记,无法删除(开关映射才是它们的手段)")}));return}if(!await S(w))return}b(!0),v("");let R=0,P=0,T=0,C="";for(const E of e){const D=E.provider||"";try{if(o==="delete"){if(!F2(E)){P+=1;continue}nc(await R2(D,E.id))}else if(o==="enable"||o==="disable"){const I=o==="enable";for(const O of Fu(E))nc(await rx(D,O.alias,E.id,{enabled:I}))}else for(const I of Fu(E))nc(await rx(D,I.alias,E.id,{reasoning:j}));R+=1}catch(I){T+=1,C||(C=Lo(I)),v(s.jsx("span",{className:"text-destructive",children:r("失败 {n} 个 · 首个失败:{error}",{n:T,error:C})}))}}T===0?(kr(P?r("✅ 批量{action}完成:共 {n} 个模型(跳过不可删除的 {skipped} 个)",{action:k,n:R,skipped:P}):r("✅ 批量{action}完成:共 {n} 个模型",{action:k,n:R})),a()):(kr(r("批量{action}完成:成功 {ok} 个,失败 {failed} 个",{action:k,ok:R,failed:T}),"err"),v(s.jsxs("span",{className:"text-destructive",children:[r("成功 {ok} 个,失败 {failed} 个",{ok:R,failed:T}),P?r(",跳过 {n} 个",{n:P}):"",C?r(";首个失败:{error}",{error:C}):""]}))),b(!1)}return s.jsx(Yt,{open:!0,onOpenChange:R=>{R||h||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("批量操作 · 已选 {n} 个模型",{n:e.length})})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("将作用于以下模型")}),s.jsx("p",{style:{maxHeight:84,overflowY:"auto"},children:e.map(BY).join(r("、"))})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("操作")}),s.jsx(_h,{value:o,onValueChange:R=>c(R),className:"flex-row flex-wrap items-center gap-5","aria-label":r("批量动作"),children:V2.map(R=>s.jsxs(Je,{className:"inline-flex cursor-pointer items-center gap-2 font-normal",children:[s.jsx(jo,{value:R.value}),R.label]},R.value))}),o==="reasoning"?s.jsxs("div",{className:"mt-2.5",children:[s.jsxs("div",{className:"field-row",children:[s.jsx("label",{htmlFor:"batch-model-reasoning",children:r("思考等级")}),s.jsxs(dt,{value:f.select,onValueChange:R=>p(P=>({...P,select:String(R)})),children:[s.jsx(pt,{id:"batch-model-reasoning",className:"min-w-[220px]",children:s.jsx(ft,{children:f.select===fa?r("自定义等级…"):f.select||r("清除(不覆盖)")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"",children:r("清除(不覆盖)")}),d.map(R=>s.jsx($e,{value:R,children:R},R)),s.jsx($e,{value:fa,children:r("自定义等级…")})]})]})]}),f.select===fa?s.jsxs("div",{className:"field-row mt-2",children:[s.jsx("label",{htmlFor:"batch-model-reasoning-custom",children:r("自定义等级")}),s.jsx(Fe,{id:"batch-model-reasoning-custom",maxLength:32,value:f.custom,onChange:R=>p(P=>({...P,custom:R.currentTarget.value}))})]}):null,s.jsxs("p",{className:"detail mt-1.5",children:[r("设置 / 清除会应用到选中模型的"),s.jsx("b",{children:r("全部映射")}),r("(默认绑定与别名 chips);「清除」= 不给这些映射指定等级(选「不覆盖」的口径与映射弹窗一致)")]})]}):null,o==="delete"?s.jsx("p",{className:"detail mt-2",children:w===0?r("选中的都不是手动登记的模型,删除不可用(上游目录带回来的行由清单决定存在性)"):r("可删除 {n} 个(手动登记 / 自定义家);",{n:w})+(e.length>w?r("其余 {n} 个会被跳过。",{n:e.length-w}):"")}):null]}),s.jsx("div",{className:"detail",style:{minHeight:18},children:y})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:h,onClick:t,children:r("关闭")}),s.jsx(ne,{variant:o==="delete"?"destructive":"default",disabled:h,onClick:()=>{N()},children:h?r("执行中…"):r("执行{action}",{action:k})})]})]})})}function rr(){return window}const $2={intl:"fm-table-intl",custom:"fm-table-custom"},q2={intl:"fetch-models",custom:"fetch-models-custom"},f0=["provider","source","state","count","note","updated","op"],p0=["pick","model","state"],UY={provider:"w-[13%]",source:"w-[21%]",state:"w-[9%]",count:"w-[6%]",note:"w-[20%]",updated:"w-[16%]",op:"w-[15%]"},VY={pick:"w-[8%]",model:"w-[74%]",state:"w-[18%]"},FY={pick:"",provider:r("提供商"),source:r("模型来源"),state:r("状态"),count:r("模型数"),note:r("说明"),updated:r("更新日期"),model:r("上游模型"),op:r("操作")},$Y={refreshed:{variant:"brand",label:r("已刷新")},failed:{variant:"destructive",label:r("失败")},skipped:{variant:"outline",label:r("跳过")}},G2=new Set(["cline-free","cline-pass"]),K2="workbuddy-desktop-fetch-model-source";function gp(e){return String(e??"").trim().toLowerCase()}function m0(e,t){rr().wbApp?.toast?.(e,t)}function h0(e){return e instanceof Error?e.message:String(e)}function Y2(e){const t=rr().formatTime??rr().wbApp?.formatTime;return String(t?.(e)??"")}function X2(){return rr().wbApp?.getState?.()?.accounts?.accounts||[]}function qY(e){const a=(rr().wbProviders?.customList?.()||[]).find(o=>o.id===e)?.models;return new Set((Array.isArray(a)?a:[]).map(o=>gp(o?.id)).filter(Boolean))}function Q2(e){if(e?.nameCustom===!0&&e?.name)return e.name;const t=String(e?.email||"").trim();return rr().wbAccountsModel?.providerFeatures?.(e?.provider)?.emailAsName&&t?t:String(e?.nickname||e?.name||t||e?.id||"").trim()||r("未命名账号")}function GY(e){if(G2.has(e))return[];const t=rr().wbAccountsModel?.byPriorityOrder,a=X2().filter(o=>(o?.provider||"workbuddy")===e&&o?.available!==!1&&o?.enabled!==!1);return t?a.sort(t):a}function Z2(){const e=new Set(rr().wbModelsPanel?.builtinProviders?.()||[]);for(const t of X2())t?.available===!1||t?.enabled===!1||e.add(t?.provider||"workbuddy");return[...e]}function KY(){const e=new Set(Z2());return(rr().wbProviders?.all?.()||[]).filter(t=>e.has(t?.id??""))}function YY(e){return Y2(Number(e.refreshedAt)||0)||"—"}function XY(e){return $Y[String(e.status)]??{variant:"outline",label:String(e.status||r("未知"))}}function QY(){try{const e=JSON.parse(localStorage.getItem(K2)||"{}");if(!e||typeof e!="object")return{};const t={};for(const[a,o]of Object.entries(e))typeof o=="string"&&o&&(t[a]=o);return t}catch{return{}}}function ZY(e){rr().wbFilterMemory?.save?.(K2,e)}function WY({options:e,onClose:t}){const a=e.providerId,o=!!e.custom,c=e.name||a,{onDone:d,onRefreshed:f}=e,[p,h]=x.useState("idle"),[b,y]=x.useState(""),[v,j]=x.useState(""),[w,k]=x.useState(null),[S,N]=x.useState(""),R=w!==null,[P,T]=x.useState(!1),[C,E]=x.useState([]),[D,I]=x.useState(()=>new Set),[O,_]=x.useState(()=>new Set),[z,H]=x.useState([]),[B,L]=x.useState(""),[F,$]=x.useState(QY);x.useEffect(()=>{rr().wbTableColumns?.repaint?.(o?q2.custom:q2.intl)},[o]);const X=o?[]:KY(),K=o?[]:J(),q=B.trim().toLowerCase(),Q=C.filter(oe=>!q||oe.toLowerCase().includes(q)),G=o?P?r("已选 {picked} 个 · 上游共 {upstream} 个 · 清单已有 {managed} 个",{picked:O.size,upstream:C.length,managed:D.size}):r("尚未获取"):Y(K);function J(){const oe=new Map(z.map(Ce=>[String(Ce.provider||""),Ce])),me=X.map(Ce=>{const Ne=String(Ce.id||"");return{provider:Ne,label:String(Ce.label||Ne),item:oe.get(Ne)}}),pe=new Set(me.map(Ce=>Ce.provider));for(const Ce of z){const Ne=String(Ce.provider||"");pe.has(Ne)||me.push({provider:Ne,label:String(Ce.providerLabel||Ne),item:Ce})}return me}function Y(oe){if(p==="loading")return r("正在刷新…");if(p==="error")return"";const me=oe.map(Ne=>Ne.item).filter(Ne=>!!Ne);if(!me.length)return P?r("刷新完成,但没有得到任何结果"):oe.length?r("共 {n} 家 · 点「获取模型」开始",{n:oe.length}):r("0 家");const pe=me.filter(Ne=>Ne.status==="refreshed").length,Ce=me.filter(Ne=>Ne.status==="failed").length;return Ce?r("{total} 家 · 成功 {done} · 失败 {failed}",{total:oe.length,done:pe,failed:Ce}):r("{total} 家 · 成功 {done}",{total:oe.length,done:pe})}function re(oe,me){const pe=GY(oe);if(!pe.length)return{list:pe,selected:""};const Ce=String(F[oe]||""),Ne=String(me||""),be=De=>pe.some(Ge=>String(Ge.id)===De);return{list:pe,selected:be(Ce)?Ce:be(Ne)?Ne:String(pe[0].id)}}function M(oe){const me={};for(const[pe,Ce]of Object.entries(F))Ce&&(me[pe]=Ce);for(const pe of oe){const{selected:Ce}=re(pe.provider,pe.reported);Ce&&(me[pe.provider]=Ce)}return me}const U=K.map(oe=>({provider:oe.provider,reported:oe.item?.accountId}));function Z(oe,me){$(pe=>({...pe,[oe]:me})),ZY({[oe]:me})}async function ae(){if(!R){k("load"),j(""),y(""),h("loading");try{if(o){const me=await rr().wbProviders?.customRequest?.("POST","/api/custom-providers/fetch-models",{providerId:a}),pe=new Set,Ce=(Array.isArray(me?.models)?me.models:[]).map(be=>String(be??"").trim()).filter(be=>{const De=gp(be);return!be||pe.has(De)?!1:(pe.add(De),!0)}),Ne=qY(a);E(Ce),I(Ne),_(new Set(Ce.filter(be=>!Ne.has(gp(be))))),T(!0),h("ready");return}const oe=await rr().workbuddyDesktop?.refreshModels({accounts:M(U),providers:Z2()});H(Array.isArray(oe?.results)?oe.results:[]),T(!0),h("ready"),Number(oe?.refreshed)>0&&f?.()}catch(oe){const me=h0(oe);y(me),h("error"),j(me)}finally{k(null)}}}async function ce(oe){if(!(R||!oe.provider)){k("row"),N(oe.provider),j("");try{const me=await rr().workbuddyDesktop?.refreshModels({accounts:M([{provider:oe.provider,reported:oe.item?.accountId}]),providers:[oe.provider]});H(pe=>W(pe,Array.isArray(me?.results)?me.results:[])),T(!0),h("ready"),Number(me?.refreshed)>0&&f?.()}catch(me){const pe=h0(me);j(pe),m0(r("获取失败:{message}",{message:pe}),"err")}finally{k(null),N("")}}}function W(oe,me){const pe=new Map(me.map(be=>[String(be.provider||""),be])),Ce=oe.map(be=>pe.get(String(be.provider||""))??be),Ne=new Set(Ce.map(be=>String(be.provider||"")));for(const be of me)Ne.has(String(be.provider||""))||Ce.push(be);return Ce}async function ue(){if(!o||R||!O.size)return;const oe=[...O];k("import"),j("");try{const me=Number(await rr().wbModelsCustom?.addModels?.(a,oe))||0;m0(r("✅ 已导入 {added} 个模型({skipped} 个已存在,跳过)",{added:me,skipped:oe.length-me})),k(null),t(),d?.()}catch(me){const pe=h0(me);m0(r("导入失败:{message}",{message:pe}),"err"),j(pe),k(null)}}function ve(){R||t()}function ee(){const oe=new Set(O);for(const me of C)D.has(gp(me))||oe.add(me);_(oe)}function he(oe){return s.jsx(Cl,{children:s.jsx(Tn,{colSpan:o?p0.length:f0.length,className:"py-[26px] text-center text-muted-foreground",children:oe})})}function te(oe){return s.jsx("span",{className:"font-mono text-[11.5px] tabular-nums text-muted-foreground",children:oe})}function ke(oe){return s.jsx("div",{className:"truncate font-mono text-[12px] font-semibold",children:oe})}function le(oe,me){const{list:pe,selected:Ce}=re(oe,me);if(!pe.length){const be=G2.has(oe)?r("这家的模型清单是全局的,不跟账号走"):r("这家还没有可用账号,刷新会使用默认登录态");return s.jsx("span",{className:"text-[11.5px] text-muted-foreground",title:be,children:"—"})}const Ne=pe.find(be=>String(be.id)===Ce);return s.jsxs(dt,{value:Ce,onValueChange:be=>Z(oe,String(be)),children:[s.jsx(pt,{className:"w-full",title:r("用哪个账号去拉这家的模型清单"),"aria-label":r("模型来源"),children:s.jsx(ft,{children:Ne?Q2(Ne):"—"})}),s.jsx(mt,{children:pe.map(be=>s.jsx($e,{value:String(be.id),children:Q2(be)},String(be.id)))})]})}function de(oe,me){_(pe=>{const Ce=new Set(pe);return me?Ce.add(oe):Ce.delete(oe),Ce})}function Se(oe,me,pe){if(pe||oe.target?.closest('[data-slot="checkbox"], input[type="checkbox"]'))return;const Ne=window.getSelection();Ne&&!Ne.isCollapsed&&oe.currentTarget.contains(Ne.anchorNode)||de(me,!O.has(me))}function Te(){return p==="idle"?he(r("点右侧「获取模型」从上游拉取这家的模型清单")):p==="loading"?he(r("正在获取…")):p==="error"?he(r("获取失败:{message}",{message:b})):Q.length?Q.map(oe=>{const me=D.has(gp(oe));return s.jsxs(Cl,{className:me?"opacity-50":"cursor-pointer",onClick:pe=>Se(pe,oe,me),children:[s.jsx(Tn,{children:s.jsx(_r,{checked:O.has(oe),disabled:me,"aria-label":oe,onCheckedChange:pe=>de(oe,!!pe)})}),s.jsx(Tn,{children:ke(oe)}),s.jsx(Tn,{children:me?s.jsx(ze,{variant:"brand",title:r("这个模型已经在这家的清单里,不重复导入"),children:r("已添加")}):s.jsx(ze,{variant:"outline",title:r("勾上它,导入后即进入这家的清单"),children:r("未添加")})})]},oe)}):he(C.length?r("没有匹配「{keyword}」的模型",{keyword:q}):r("上游没有返回任何模型"))}function Le(oe){const me=w==="row"&&S===oe.provider;return s.jsx(ne,{variant:"outline",size:"sm",className:"w-full",disabled:R,title:r("只刷新这一家的模型清单"),onClick:()=>{ce(oe)},children:me?r("获取中…"):oe.item?r("重新获取"):r("获取")})}function Ae(){return p==="loading"?he(r("正在获取…")):p==="error"?he(r("获取失败:{message}",{message:b})):K.length?K.map(oe=>{const me=oe.item;if(!me){const be=Y2(Number(rr().wbModelsPanel?.providerRefreshedAt?.(oe.provider))||0);return s.jsxs(Cl,{children:[s.jsx(Tn,{children:ke(oe.label)}),s.jsx(Tn,{children:le(oe.provider)}),s.jsx(Tn,{children:s.jsx(ze,{variant:"outline",children:r("待获取")})}),s.jsx(Tn,{children:te("—")}),s.jsx(Tn,{children:te("—")}),s.jsx(Tn,{children:te(be||"—")}),s.jsx(Tn,{children:Le(oe)})]},oe.provider)}const pe=XY(me),Ce=Number(me.count),Ne=me.status==="refreshed"?r("远程目录已更新,「来源」列会显示为「远程」"):me.message||(me.fixed?r("这家用固定模型清单,无可刷新"):r("本次没有取到新内容"));return s.jsxs(Cl,{children:[s.jsx(Tn,{children:ke(oe.label)}),s.jsx(Tn,{children:le(oe.provider,me.accountId)}),s.jsx(Tn,{children:s.jsx(ze,{variant:pe.variant,children:pe.label})}),s.jsx(Tn,{children:te(Ce?r("{n} 个",{n:Ce}):"—")}),s.jsx(Tn,{children:s.jsx("span",{className:"text-[11.5px] leading-[1.5] text-muted-foreground",children:Ne})}),s.jsx(Tn,{children:te(YY(me))}),s.jsx(Tn,{children:Le(oe)})]},oe.provider)}):he(r("还没有可刷新的提供商:先在账号页添加一个账号"))}return s.jsx(Yt,{open:!0,onOpenChange:(oe,me)=>{if(!oe){if(R){me.cancel();return}t()}},children:s.jsxs(Xt,{className:o?"w-[min(607px,calc(100vw-48px))]":"w-[min(1012px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("获取模型 — {name}",{name:c})})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx("span",{className:"text-[11.5px] text-muted-foreground",children:G}),o&&s.jsxs(Di,{className:"w-[240px] flex-none",children:[s.jsx(Pi,{type:"search",placeholder:r("搜索模型 ID…"),autoComplete:"off",value:B,onChange:oe=>L(oe.currentTarget.value)}),s.jsx(Ii,{"aria-hidden":"true",children:"⌕"})]}),s.jsx("div",{className:"mr-auto"}),o&&s.jsxs(s.Fragment,{children:[s.jsx(ne,{variant:"ghost",size:"sm",onClick:ee,children:r("全选未添加")}),s.jsx(ne,{variant:"ghost",size:"sm",onClick:()=>_(new Set),children:r("清空")})]}),s.jsx(ne,{variant:"outline",size:"sm",title:r("刷新全部家(逐家打上游)"),disabled:R,onClick:()=>{ae()},children:r(w==="load"?"获取中…":P?"重新获取":"获取模型")})]}),s.jsxs(Zy,{id:o?$2.custom:$2.intl,className:"table-fixed",containerClassName:"max-h-[min(48vh,460px)]",children:[s.jsx("colgroup",{children:(o?p0:f0).map(oe=>s.jsx("col",{"data-col":oe,className:o?VY[oe]:UY[oe]},oe))}),s.jsx(AE,{children:s.jsx(Cl,{children:(o?p0:f0).map(oe=>s.jsx(RE,{"data-col":oe,children:FY[oe]},oe))})}),s.jsx(Wy,{className:"[&_tr:last-child>td]:border-b-0",children:o?Te():Ae()})]})]}),s.jsxs(tn,{children:[s.jsx("span",{className:"min-w-0 text-[11.5px] text-muted-foreground",children:v}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:ve,children:r(o?"取消":"完成")}),o&&s.jsx(ne,{variant:"default",disabled:!O.size||R,onClick:()=>{ue()},children:w==="import"?r("导入中…"):O.size?r("导入选中的 {n} 个模型",{n:O.size}):r("导入")})]})]})})}let xp=null,$u=null;function W2(){xp&&(xp.unmount(),xp=null),$u&&($u.remove(),$u=null)}function JY(e){e?.providerId&&(W2(),$u=document.createElement("div"),document.body.append($u),xp=jn.createRoot($u),xp.render(s.jsx(WY,{options:e,onClose:W2})))}window.wbModelsFetchModal={open:JY};const Bo=(e,t)=>t?`${e} ta-${t}`:e;function J2(e,t){const a=(t||"").trim();if(a)return dp().find(o=>zo(o.provider,e)&&zo(o.id,a))}const eX="[.pv-row:hover_&_[data-slot=nav-item-count]]:invisible";function tX(e){const t=/x\s*([\d.]+)/i.exec(String(e||""));return t?`${t[1]}x`:String(e||"")}function eD(e){const t=/x\s*([\d.]+)/i.exec(String(e||""));if(!t)return null;const a=Number(t[1]);return Number.isFinite(a)?a:null}const nX={workbuddy:250,"workbuddy-intl":295,raccoon:60,catpaw:85,autoclaw:250,"autoclaw-intl":295,qoder:330,"qoder-intl":350,"cline-free":200,"cline-pass":200,codearts:210,loomy:155,kuku:15,accio:320,"accio-intl":335,trae:170,zcode:285};function sX(e){const t=nX[e];if(t!==void 0)return t;let a=0;for(let o=0;o>>0;return a%360}function rX(e){const t=String(e||"").trim();if(!t)return"?";const a=t.match(/[A-Za-z]/);return(a?a[0]:t[t.length-1]).toUpperCase()}const aX=e=>({"--av-h":String(sX(e))}),g0=s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3.5",y:"3.5",width:"7",height:"7",rx:"1.5"}),s.jsx("rect",{x:"13.5",y:"3.5",width:"7",height:"7",rx:"1.5"}),s.jsx("rect",{x:"13.5",y:"13.5",width:"7",height:"7",rx:"1.5"}),s.jsx("rect",{x:"3.5",y:"13.5",width:"7",height:"7",rx:"1.5"})]})});function lX(e){if(!e)return"";const t=Wt().wbPresetProviders?.list;if(!Array.isArray(t))return"";const a=t.find(o=>o.name===e);return a&&Wt().wbPresetProviders?.iconOf?.(String(a.key||""))||""}function oX(e,t){return as(e)?lX(t):Cg[e==="workbuddy-intl"?"workbuddy":e]||""}function qu(e,t,a){const o=a?"":oX(e,t),c=e==="all"||e==="custom-all";return s.jsx("span",{className:Ue("pv-ico",c&&"mute",o&&"img"),style:o?void 0:aX(e),"aria-hidden":"true",children:o?s.jsx("img",{src:o,alt:""}):a??rX(t)})}const iX={supportsToolCall:s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsx("path",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"})}),supportsImages:s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2.5"}),s.jsx("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),s.jsx("path",{d:"M21 15l-5-5L5 21"})]})}),supportsVideo:s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"9"}),s.jsx("path",{d:"M10 8.5l6 3.5-6 3.5z"})]})}),supportsReasoning:s.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"}),s.jsx("path",{d:"M9 18h6M10 22h4"})]})})};function cX(e,t,a,o){return o==="enabled"&&!pp(e)||o==="disabled"&&pp(e)||o==="mapped"&&!(e.aliases||[]).length||a!=="all"&&(e.provider||"")!==a?!1:t?[e.id,e.name,...e.aliases||[]].join(" ").toLowerCase().includes(t):!0}function uX(){const e=x.useSyncExternalStore(JK,ip),t=ex(e),a=as(t)||t==="custom-all",[o,c]=x.useState(null),[d,f]=x.useState(!1),[p,h]=x.useState(new Set),b=a&&!Vu()&&e0()&&!_o(t);x.useEffect(()=>{lY(),tx(),S2(),Wt().wbApp?.currentPage==="gateway"&&A2().then(()=>Wt().wbProviders?.refreshCustom?.()).then(()=>{tc()})},[]),x.useEffect(()=>{wY()});const y=n0(),v=Array.isArray(y.models)?y.models:[],j=e.search.trim().toLowerCase(),w=v.filter(J=>cX(J,j,t,e.stateFilter)),k=e.sort,S=E2(),N=S.length,R=t==="all"?r("全部"):t==="custom-all"?r("自定义 · 全部"):a?String(_o(t)?.name||t):s0().get(t)?.label||c0(t),P=v.filter(pp).length,T=v.filter(J=>(J.aliases||[]).length>0).length,C=gg(w.length,"models"),E=v.filter(J=>p.has(sc(J))),D=(J,Y)=>{const re=new Set(p);Y?re.add(J):re.delete(J),h(re)},I=w.map(sc),O=I.length>0&&I.every(J=>p.has(J)),_=I.some(J=>p.has(J)),z=s.jsx(_r,{checked:O,indeterminate:!O&&_,disabled:!I.length,"aria-label":r("全选当前筛选结果"),title:r("全选当前筛选出的模型(跨分页);再点取消"),onCheckedChange:J=>{const Y=new Set(p);for(const re of I)J===!0?Y.add(re):Y.delete(re);h(Y)}});function H(){const J=s0(),Y=Ji(),re=nY(),M=[...J.values()].reduce((ce,W)=>ce+W.n,0),U=r("全部({n} 家)",{n:J.size}),Z=[...re.values()].reduce((ce,W)=>ce+W.n,0),ae=r("全部({n} 家)",{n:[...re.values()].filter(ce=>ce.n>0).length});return s.jsxs("aside",{className:"prov-rail",id:"prov-rail","aria-label":r("按提供商选择"),children:[s.jsxs("div",{className:"rail-scroll",children:[s.jsx("div",{className:"rail-label",children:r("内置提供商")}),s.jsx(du,{active:t==="all","data-provider":"all",title:U,count:M,icon:qu("all","",g0),className:"shadow-none",onClick:()=>mp("all"),children:U}),[...J].map(([ce,W])=>s.jsx(du,{active:t===ce,"data-provider":ce,title:W.label,count:W.n,icon:qu(ce,W.label),className:"shadow-none",onClick:()=>mp(ce),children:W.label},ce)),s.jsx("div",{className:"rail-label",children:r("自定义提供商")}),Y.length?[...Z>0?[s.jsx(du,{active:Vu(),"data-provider":"custom-all",title:ae,count:Z,icon:qu("custom-all","",g0),className:"shadow-none",onClick:()=>mp("custom-all"),children:ae},"custom-all")]:[],...Y.map(ce=>{const W=String(ce.id||""),ue=String(ce.name||W);return s.jsxs("div",{className:"pv-row",children:[s.jsx(du,{active:t===W,"data-provider":W,title:ue,count:re.get(W)?.n??0,icon:qu(W,ue),className:Ue("shadow-none",eX),onClick:()=>mp(W),children:ue}),s.jsx("button",{type:"button",className:"pv-del","aria-label":r("删除自定义提供商"),title:r("删除这个自定义提供商(连同名下账号)"),onClick:()=>{hY(W)},children:"×"})]},W)})]:s.jsx("div",{className:"rail-empty",children:r("还没有自定义提供商")})]}),s.jsx("div",{className:"rail-foot",children:s.jsx(du,{variant:"add",id:"rail-add-custom",title:r("新建一个自定义提供商(同时创建它的第一个账号)"),onClick:()=>gY(),children:r("+ 新建自定义提供商")})})]})}function B(J,Y,re,M){const U=u0(J,Y,re);return s.jsx(ne,{variant:U?"secondary":"dashed",size:"2xs",disabled:M,className:"font-mono font-bold shadow-none",title:U?r("思考等级 {level}(点击修改)",{level:U}):r("设置思考等级(当前未绑定)"),onClick:()=>O2({alias:J,target:Y,provider:re}),children:U||r("+等级")})}function L(J){const Y=J.provider||"",re=Fu(J),[M,...U]=re;async function Z(ce){await Wt().wbConfirm?.ask?.({title:r("删除映射"),html:r("确定删除映射「{alias} → {target}」?",{alias:Yw(ce),target:Yw(J.id)}),okText:r("删除"),okClass:"danger"})&&o0(i0(ce,J.id,Y),()=>oY(Y,ce,J.id),r("映射已删除"))}const ae=ce=>{const W=ce.alias,ue=ce.enabled!==!1,ve=e.pending.has(i0(W,J.id,Y));return s.jsxs("span",{className:Ue("alias",!ue&&"map-off"),children:[s.jsx(Zn,{size:"sm",checked:ue,disabled:ve,title:r(ue?"映射已启用,点击关闭":"映射已关闭,点击启用"),"aria-label":r("{action}映射 {alias}",{action:r(ue?"关闭":"启用"),alias:W}),onCheckedChange:ee=>{o0(i0(W,J.id,Y),()=>rx(Y,W,J.id,{enabled:ee}),r(ee?"映射已启用":"映射已关闭"))}}),s.jsx("span",{className:"t","data-copy":W,title:r("点击复制:{name}",{name:W}),children:W}),ce.isDefault?s.jsx("span",{className:"binding-default",children:r("默认")}):null,B(W,J.id,Y,ve),ce.isDefault?null:s.jsx(ne,{variant:"ghost",size:"icon-2xs",className:"text-[12px] leading-none",disabled:ve,title:r("删除映射 {alias}",{alias:W}),onClick:()=>{Z(W)},children:"×"})]},`${W}${ce.isDefault?"d":"m"}`)};return s.jsxs("div",{className:"aliases",children:[s.jsxs("div",{className:"alias-row",children:[M?ae(M):null,s.jsx(ne,{variant:"dashed",size:"xs",onClick:()=>O2({target:J.id,provider:Y}),children:r("+ 映射")})]}),U.map(ae)]})}function F(J){if(J.source==="manual")return s.jsxs("span",{className:"src manual",title:r("手动登记的上游模型;移除它会直接删掉这条登记"),children:[s.jsx("i",{"aria-hidden":"true"}),r("手动")]});if(!J.source&&as(J.provider))return s.jsxs("span",{className:"src manual",title:r("用户登记的自定义模型;整份清单只属于这一家"),children:[s.jsx("i",{"aria-hidden":"true"}),r("自定义")]});if(J.source!=="remote"&&J.source!=="builtin")return s.jsx("span",{className:"rate",children:"—"});const Y=J.source==="remote",re=YK(Number(J.refreshedAt)||0),M=Y?re?r("来自上游目录接口,清单拉取于 {at};刷新失败时保留上一份成功结果",{at:re}):r("来自上游目录接口;刷新失败时保留上一份成功结果"):r("上游目录尚未拉到,用的是内置静态清单;点「刷新模型清单」可重试");return s.jsxs("span",{className:Ue("src",Y?"remote":"builtin"),title:M,children:[s.jsx("i",{"aria-hidden":"true"}),r(Y?"远程":"内置")]})}function $(J){const Y=Gw(J),re=qw(J.capOverrides),M=typeof Y.maxInputTokens=="number"?Y.maxInputTokens:null,U=typeof Y.maxOutputTokens=="number"?Y.maxOutputTokens:null,Z=r("上下文窗口 {input} / 最大输出 Token {output} —— 点击修改模型能力",{input:rp(M),output:rp(U)})+X(J);return s.jsxs("button",{type:"button",className:"caps-open",title:Z,onClick:()=>M2(J.provider||"",J.id),children:[s.jsxs("span",{className:Ue("cap-num",M===null&&"unset",Hu(J,"maxInputTokens")==="modelsdev"&&"filled"),children:[r2(M),re.includes("maxInputTokens")?s.jsx("i",{className:"cap-mark",title:r("已覆盖上游值")}):null]}),s.jsx("span",{className:"cap-sep",children:"/"}),s.jsxs("span",{className:Ue("cap-num",U===null&&"unset",Hu(J,"maxOutputTokens")==="modelsdev"&&"filled"),children:[r2(U),re.includes("maxOutputTokens")?s.jsx("i",{className:"cap-mark",title:r("已覆盖上游值")}):null]})]})}function X(J){const Y=["maxInputTokens","maxOutputTokens"].filter(re=>Hu(J,re)==="modelsdev").map(re=>Bu[re]);return Y.length?r(";其中 {keys} 由 models.dev 补齐",{keys:Y.join(r("、"))}):""}function K(J){const Y=Gw(J),re=qw(J.capOverrides);return s.jsx("button",{type:"button",className:"caps-open caps-badges",title:r("对下游声明的能力(工具调用 / 图片识别 / 视频识别 / 支持思考)—— 点击修改"),onClick:()=>M2(J.provider||"",J.id),children:n2.map(M=>{const U=Y[M]??null,Z=Kw(U),ae=re.includes(M),ce=Hu(J,M);return s.jsxs("span",{className:Ue("cap-dot",Z,ce==="modelsdev"&&"filled",ae&&"marked"),title:BK(M,U,ae,ce),children:[iX[M],ae?s.jsx("i",{className:"cap-mark"}):null]},M)})})}function q(J,Y,re){async function M(){await Wt().wbConfirm?.ask?.({title:r("移除自定义模型"),html:r("确定移除自定义模型「{id}」?这条登记会被直接移除,之后 /v1/models 不再广告它、请求它也会被拒。",{id:Yw(Y.id)}),okText:r("移除"),okClass:"danger"})&&o0(sc(Y),()=>R2(Y.provider||"",Y.id),as(Y.provider||"")?r("模型已移除"):r("自定义模型已移除"))}switch(J.key){case"check":return s.jsx("td",{className:Bo("cell-check",J.align),children:s.jsx(_r,{checked:p.has(sc(Y)),title:r("勾选后可批量操作"),"aria-label":r("勾选后可批量操作"),onCheckedChange:U=>D(sc(Y),U===!0)})});case"model":return s.jsxs("td",{className:Bo("cell-model",J.align),children:[s.jsx("div",{className:"mid",children:s.jsx("span",{className:"t","data-copy":Y.id,title:r("点击复制:{name}",{name:Y.id}),children:Y.id})}),Y.name&&Y.name!==Y.id?s.jsx("div",{className:"mname",children:Y.name}):null]});case"rate":return s.jsx("td",{className:Bo("cell-rate",J.align),children:s.jsx("span",{className:"rate",children:Y.credits?tX(Y.credits):"—"})});case"source":return s.jsx("td",{className:Bo("cell-source",J.align),children:F(Y)});case"budget":return s.jsx("td",{className:Bo("cell-budget",J.align),children:$(Y)});case"caps":return s.jsx("td",{className:Bo("cell-caps",J.align),children:K(Y)});case"alias":return s.jsx("td",{className:Bo("cell-alias",J.align),children:L(Y)});case"act":{const U=PY(Y.provider||""),Z=Y.source==="manual"||as(Y.provider||"");return s.jsx("td",{className:Bo("cell-act r",J.align),children:s.jsxs("div",{className:"row-actions",children:[s.jsx(ne,{variant:"ghost",size:"sm",disabled:!!U,title:U||r("以这个上游模型发一次最小请求,走真实转发链路"),onClick:()=>c({provider:Y.provider||"",id:Y.id}),children:r("测试")}),Z?s.jsx(ne,{variant:"ghost",size:"sm",className:"text-destructive",disabled:re,onClick:()=>{M()},children:r("移除")}):null]})})}default:return null}}function Q(J){const Y=e.pending.has(sc(J)),re=p.has(sc(J));return s.jsx("tr",{className:Ue(re&&"sel"),children:S.map(M=>s.jsx(x.Fragment,{children:q(M,J,Y)},M.key))},`${J.provider||""}${J.id}`)}function G(){if(!v.length){const Z=a?e0()?Vu()?r("自定义提供商还没有模型:先在左栏选一家,点「添加模型」登记,或「获取上游模型」从上游拉取"):r(b?"该提供商已不存在(可能已被删除),请刷新列表":"这家还没有模型:点「添加模型」登记,或「获取上游模型」从上游拉取"):r("加载中…"):e.data?r("暂无模型(请先添加账号)"):r("加载中…");return s.jsx("tr",{children:s.jsx("td",{colSpan:N,className:"empty",children:Z})})}if(!w.length)return s.jsx("tr",{children:s.jsx("td",{colSpan:N,className:"empty",children:j?r("没有匹配「{keyword}」的模型",{keyword:j}):r("没有匹配当前筛选的模型")})});const J=t==="all"||Vu(),Y=J&&!j&&e.stateFilter==="all"&&!C.paged,re=new Map;for(const Z of w){const ae=Z.provider||"";re.has(ae)||re.set(ae,{label:Z.providerLabel||ae||r("未知"),items:[]}),re.get(ae)?.items.push(Z)}const M=[];let U=0;for(const[Z,ae]of re){ae.items.sort((te,ke)=>{const le=+!pp(te)-+!pp(ke);if(le!==0||k==="default")return le;const de=eD(te.credits),Se=eD(ke.credits);return de===null||Se===null?de===Se?0:de===null?1:-1:k==="rate-asc"?de-Se:Se-de});const ce=e.expanded.has(Z)||!Y,W=ce?ae.items:ae.items.slice(0,x2),ue=ae.items.length-W.length,ve=C.paged?Math.max(0,C.rangeStart-1-U):0,ee=C.paged?Math.min(W.length,C.rangeEnd-U):W.length,he=ve0?r("(续)"):"",r("{n} 个模型",{n:ae.items.length})]})},`group:${Z}`));for(const te of he)M.push(Q(te));U+=W.length,ue>0?M.push(s.jsx("tr",{className:"tr-more",children:s.jsx("td",{colSpan:N,children:s.jsx(ne,{variant:"ghost",size:"sm",onClick:()=>uY(Z),children:r("展开其余 {n} 个模型 ▾",{n:ue})})})},`more:${Z}`)):ce&&Y&&ae.items.length>x2&&M.push(s.jsx("tr",{className:"tr-more",children:s.jsx("td",{colSpan:N,children:s.jsx(ne,{variant:"ghost",size:"sm",onClick:()=>dY(Z),children:r("收起 ▴")})})},`collapse:${Z}`))}return M}return s.jsxs(s.Fragment,{children:[s.jsx("section",{className:"panel",children:s.jsxs("div",{className:"mm",children:[H(),s.jsxs("div",{className:"mm-main",children:[s.jsxs("div",{className:"panel-head",children:[s.jsxs("div",{className:"mm-titlebar",children:[s.jsxs("div",{className:"mm-title",children:[t==="all"||t==="custom-all"?qu(t,"",g0):qu(t,R),s.jsx("h2",{children:R}),s.jsxs("span",{className:"mm-meta",children:[s.jsx("b",{children:v.length}),r(" 个模型 · 已启用 "),s.jsx("b",{children:P}),r(" · 有映射 "),s.jsx("b",{children:T})]})]}),s.jsxs("div",{className:"head-actions",children:[s.jsx(ne,{id:"btn-refresh-models",title:as(t)?r("从这一家的上游拉一份模型清单,勾选要哪些再导入(已添加的不会重复导入)"):r("刷新模型管理页里各提供商的远程模型目录,逐家结果列在弹窗里"),onClick:()=>I2(),children:r("获取模型")}),s.jsx(ne,{id:"btn-add-custom-model",variant:"outline",size:"sm",onClick:()=>bY(),children:r("+ 添加模型")})]})]}),s.jsxs("div",{className:"mm-filters",children:[s.jsx(En,{options:QK,value:e.stateFilter,onValueChange:fY,"aria-label":r("按状态筛选"),className:"shrink-0"}),s.jsx(En,{options:WK,value:e.sort,onValueChange:pY,"aria-label":r("按倍率排序"),className:"shrink-0"}),s.jsxs(Di,{className:"w-full min-[768px]:w-[240px] flex-none min-[768px]:flex-none",id:"models-search",children:[s.jsx(Pi,{type:"search",placeholder:r("搜索模型 ID / 名称 / 映射名…"),"aria-label":r("搜索模型"),autoComplete:"off",value:e.search,onChange:J=>mY(J.currentTarget.value)}),s.jsx(Ii,{"aria-hidden":"true",children:"⌕"})]}),E.length>0?s.jsxs("span",{className:"batch-chip",children:[r("已选 "),s.jsx("b",{children:E.length}),r(" 个"),s.jsx(ne,{id:"btn-batch-models",variant:"outline",size:"xs",title:r("对选中的 {n} 个模型执行批量操作",{n:E.length}),onClick:()=>f(!0),children:r("批量操作")})]}):null]})]}),s.jsx("div",{className:"models-table-wrap",children:s.jsxs("table",{className:"models-table",ref:J=>jY(J),children:[s.jsxs("colgroup",{children:[s.jsx("col",{className:"c-check","data-col":"check"}),s.jsx("col",{className:"c-model","data-col":"model"}),s.jsx("col",{className:"c-rate","data-col":"rate"}),s.jsx("col",{className:"c-source","data-col":"source"}),s.jsx("col",{className:"c-budget","data-col":"budget"}),s.jsx("col",{className:"c-caps","data-col":"caps"}),s.jsx("col",{className:"c-alias","data-col":"alias"}),s.jsx("col",{className:"c-act","data-col":"act"})]}),s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{"data-col":"check",children:z}),s.jsx("th",{"data-col":"model",children:r("上游模型")}),s.jsx("th",{"data-col":"rate",children:r("倍率")}),s.jsx("th",{"data-col":"source",children:r("来源")}),s.jsxs("th",{"data-col":"budget",children:[r("上下文 / 输出"),s.jsx("span",{className:"th-help","aria-hidden":"true",title:r("数字带虚线底 = 由 models.dev 补齐;右上角小点 = 你手动覆盖过;— = 未声明。点任意一格可改。"),children:s.jsx("svg",{viewBox:"0 0 24 24",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"9"}),s.jsx("path",{d:"M12 16v-4"}),s.jsx("path",{d:"M12 8h.01"})]})})})]}),s.jsxs("th",{"data-col":"caps",children:[r("能力"),s.jsx("span",{className:"th-help","aria-hidden":"true",title:r("圆点带内侧描边 = 由 models.dev 补齐;右上角小点 = 你手动覆盖过;虚线圈 = 未声明。悬停某一枚可看逐项出处。"),children:s.jsx("svg",{viewBox:"0 0 24 24",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"9"}),s.jsx("path",{d:"M12 16v-4"}),s.jsx("path",{d:"M12 8h.01"})]})})})]}),s.jsxs("th",{"data-col":"alias",children:[r("模型映射"),s.jsx("span",{className:"th-help","aria-hidden":"true",title:r("每条映射 = 对外名 → 上游模型;原始 ID 与别名有独立开关,默认绑定永远存在(没有映射时是合成的那条)。"),children:s.jsx("svg",{viewBox:"0 0 24 24",children:s.jsxs("g",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[s.jsx("circle",{cx:"12",cy:"12",r:"9"}),s.jsx("path",{d:"M12 16v-4"}),s.jsx("path",{d:"M12 8h.01"})]})})})]}),s.jsx("th",{className:"r","data-col":"act",children:r("操作")})]})}),s.jsx("tbody",{id:"models",children:G()})]})}),s.jsx($i,{className:"models-panel-foot",leading:Vu()?s.jsxs(s.Fragment,{children:[r("这里是"),s.jsx("b",{children:r("全部自定义提供商")}),r("的模型合集:每家的清单互相独立,别名也只在自己那家内生效;要改名称 / 协议 / Base URL,到账号页该家账号的「设置」→ 提供商一栏。")]}):a?s.jsxs(s.Fragment,{children:[r("自定义提供商的清单"),s.jsx("b",{children:r("只属于这一家")}),r(":这里的模型不会出现在其他家,别名也只在这一家内生效。改名称 / 协议 / Base URL 在账号页该家账号的「设置」→ 提供商一栏;整家不要了,鼠标移到左栏这家上点 × 删除(连同名下账号)。")]}):void 0,total:w.length,range:C.paged?{start:C.rangeStart,end:C.rangeEnd}:null,page:C.page,pageCount:C.pageCount,size:C.size,onSizeChange:C.setSize,onPageChange:C.goto})]})]})}),e.mapping?s.jsx(fX,{context:e.mapping,onClose:xY}):null,e.customModel?s.jsx(pX,{initial:e.customModel,onClose:vY}):null,e.capability?s.jsx(TY,{context:e.capability,onClose:yY}):null,o?s.jsx(zY,{target:o,onClose:()=>c(null)}):null,d?s.jsx(HY,{models:E,onClose:()=>f(!1),onDone:()=>{h(new Set),f(!1)}}):null]})}const dX=r("绑定在「对外名 → 上游模型」这一条映射上的思考等级(列表照抄 OmniProxy 的手动绑定),选「不覆盖」表示不给这条映射指定等级。它会跟着这条映射注入转发,由承载的那家翻译成自己的档位字段(CatPaw 归并成 low/high/max,Qoder 按模型声明的档位归一)。以下几种情况故意不注入:① off / none(关闭思考)—— 本项目没有安全的表达方式;② 表外的自定义等级(各家能力范围不同,无法判断上游收不收);③ 客户端请求体里已经自己指定了档位(那是更明确的意图,绑定不覆盖);④ 这家上游不认识档位字段(如 WorkBuddy / 小浣熊 / AutoClaw / Cline)。注入与跳过都会写进详细日志。");function tD(e,t,a){const o=T2(e),c=(t||"").trim(),d=o.find(f=>f.id.toLowerCase()===c.toLowerCase());return d?d.id:c||o[0]?.id||""}function fX({context:e,onClose:t}){const a=!!e.alias,[o,c]=x.useState(()=>e.provider||r0()[0]?.id||""),[d,f]=x.useState(e.alias||""),[p,h]=x.useState(()=>tD(o,e.target)),[b,y]=x.useState(""),[v,j]=x.useState(!1),[w,k]=x.useState(()=>{const _=lp(ip().data,J2(o,p)),z=a?u0(e.alias,e.target,e.provider):"";return z&&_.includes(z)?{select:z,custom:""}:{select:z?fa:"",custom:z}}),S=lp(ip().data,J2(o,p)),N=(()=>{const _=r0();for(const z of[e.provider,o])z&&!_.some(H=>H.id===z)&&_.push({id:z,label:r(Wt().wbProviders?.labelOf?.(z)||z)});return _})(),R=(()=>{const _=T2(o),z=(p||"").trim();return z&&!_.some(H=>H.id.toLowerCase()===z.toLowerCase())&&_.unshift({id:z,label:r("{name}(不在该家当前清单里)",{name:z}),off:!0}),_})(),P=N.find(_=>_.id===o)?.label||o||r("(全局)"),T=w.select&&w.select!==fa&&!S.includes(w.select)?{select:fa,custom:w.custom||w.select}:w,C=T.select===fa?T.custom.trim():T.select,E=T.select===fa;function D(_){c(_),h(tD(_,p))}async function I(){if(v)return;const _=a?e.alias||"":d.trim(),z=p;if(!_){y(r("请填写对外映射名"));return}if(!z){y(r("该提供商当前没有可选的上游模型"));return}if(!o){y(r("请选择提供商"));return}if(!a&&zo(_,z)&&dp().some(H=>zo(H.id,z)&&zo(H.provider,o))){y(r("原始 ID 已作为默认绑定,请直接使用该绑定的开关或等级按钮"));return}j(!0),y(r("保存中…"));try{nc(await rx(o,_,z,{reasoning:C})),j(!1),t();const H=C?r(" · 思考等级 {level}",{level:C}):"",B=r(Wt().wbProviders?.labelOf?.(o)||o);kr(a?r("✅ 已更新 {name} 的思考等级",{name:_}):r("✅ 已添加映射 {name} → {target}({label}){suffix}",{name:_,target:z,label:B,suffix:H}))}catch(H){y(r("保存失败:{message}",{message:Lo(H)})),j(!1)}}const O=_=>{_.key==="Enter"&&(_.preventDefault(),I())};return s.jsx(Yt,{open:!0,onOpenChange:(_,z)=>{if(!_){if(v){z.cancel();return}t()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r(a?"设置思考等级":"添加模型映射")})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"mapping-provider",children:r("提供商")}),s.jsxs(dt,{value:o,disabled:!0,onValueChange:_=>D(String(_)),children:[s.jsx(pt,{id:"mapping-provider",className:"w-full",children:s.jsx(ft,{children:N.find(_=>_.id===o)?.label||o})}),s.jsx(mt,{children:N.map(_=>s.jsx($e,{value:_.id,children:_.label},_.id))})]})]}),s.jsxs("div",{className:"grid grid-cols-[1fr_24px_1fr] items-end gap-2.5",children:[s.jsxs("div",{className:"flex min-w-0 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"mapping-alias",children:r("对外映射名(下游请求时用)")}),s.jsx(Fe,{id:"mapping-alias",maxLength:128,placeholder:r("例如 gpt-4o"),autoComplete:"off",autoFocus:!a,value:d,disabled:a,onChange:_=>f(_.currentTarget.value),onKeyDown:O})]}),s.jsx("div",{className:"pb-2 text-center text-muted-foreground",children:"→"}),s.jsxs("div",{className:"flex min-w-0 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"mapping-upstream",children:r("转发到上游模型")}),s.jsxs(dt,{value:p,disabled:!0,onValueChange:_=>h(String(_)),children:[s.jsx(pt,{id:"mapping-upstream",className:"w-full",children:s.jsx(ft,{children:R.find(_=>_.id===p)?.label||p})}),s.jsx(mt,{children:R.map(_=>s.jsxs($e,{value:_.id,children:[_.label,_.off?r("(已禁用)"):""]},_.id))})]})]})]}),s.jsxs("div",{className:"rounded-md border border-border bg-surface-inset px-3 py-2.5 font-mono text-[12px] text-subtle",children:[r("下游请求 "),s.jsx("b",{className:"text-primary-fg",children:d.trim()||r("<对外名>")}),r(" → 转发")," ",s.jsx("b",{className:"text-primary-fg",children:p||r("<上游模型>")}),r("({label})",{label:P}),C?s.jsxs(s.Fragment,{children:[r(" · 思考等级 "),s.jsx("b",{className:"text-primary-fg",children:C})]}):null]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs("div",{className:"flex items-center gap-[7px]",children:[s.jsx(Je,{htmlFor:"mapping-reasoning",children:r("思考等级")}),s.jsxs(Ui,{children:[s.jsx(Vi,{render:s.jsx("span",{className:"tip-q",tabIndex:0,"aria-label":r("思考等级的注入规则")}),children:"?"}),s.jsx(Fi,{children:dX})]})]}),s.jsxs(dt,{value:T.select,onValueChange:_=>{const z=String(_);k(H=>({...H,select:z}))},children:[s.jsx(pt,{id:"mapping-reasoning",className:"w-full",autoFocus:a,children:s.jsx(ft,{children:T.select===fa?r("自定义等级…"):T.select||r("不覆盖")})}),s.jsxs(mt,{children:[s.jsx($e,{value:"",children:r("不覆盖")}),S.map(_=>s.jsx($e,{value:_,children:_},_)),s.jsx($e,{value:fa,children:r("自定义等级…")})]})]}),E?s.jsx(Fe,{id:"mapping-reasoning-custom",maxLength:32,autoFocus:!0,placeholder:r("自定义等级(例如 custom-high)"),autoComplete:"off",disabled:v,value:T.custom,onChange:_=>k(z=>({...z,custom:_.currentTarget.value})),onKeyDown:O}):null]}),s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("对外名可自由命名,允许与上游模型 ID 同名(同名时该上游的原生路由优先,映射作兜底); 支持字母、数字与 "),s.jsx("code",{children:"- _ . / :"}),r("。同一对外名可在多个提供商各添加一条: 下游用同一个名字请求,网关按账号优先级主备切换,失败自动落到下一个提供商。")]}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:b})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:v,onClick:()=>{I()},children:r(a?"保存等级":"保存映射")})]})]})})}function pX({initial:e,onClose:t}){const[a,o]=x.useState(e.provider),[c,d]=x.useState(""),[f,p]=x.useState(""),[h,b]=x.useState(!1),y=(()=>{const S=aY();return a&&!S.some(N=>N.id===a)&&S.push({id:a,label:r(Wt().wbProviders?.labelOf?.(a)||a)}),S})(),v=y.some(S=>S.id===a)?a:y[0]?.id||"",j=y.find(S=>S.id===v)?.label||v||r("(未选)");async function w(){if(h)return;const S=c.trim();if(!v){p(r("请选择提供商"));return}if(!S){p(r("请填写上游模型 ID"));return}b(!0),p(r("保存中…"));try{const N=await iY(v,S);nc(N),b(!1),t();const R=y.find(P=>P.id===v)?.label||v;if(as(Uu()))kr(r("✅ 已登记模型 {name}({label})",{name:S,label:R}));else{const P=N;Array.isArray(P?.models)&&P.models.some(C=>C.id===S&&(C.provider||"")===v)?kr(r("✅ 已登记自定义模型 {name}({label})",{name:S,label:R})):kr(r("✅ 已登记 {name}({label}),但该提供商还没有可用账号,这一行要加上账号后才会显示",{name:S,label:R}),"err")}}catch(N){p(r("保存失败:{message}",{message:Lo(N)})),b(!1)}}const k=S=>{S.key==="Enter"&&(S.preventDefault(),w())};return s.jsx(Yt,{open:!0,onOpenChange:(S,N)=>{if(!S){if(h){N.cancel();return}t()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("添加自定义模型")})}),s.jsxs(Lt,{children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"custom-model-provider",children:r("提供商")}),s.jsxs(dt,{value:v,disabled:e.locked,onValueChange:S=>o(String(S)),children:[s.jsx(pt,{id:"custom-model-provider",className:"w-full",children:s.jsx(ft,{children:j})}),s.jsx(mt,{children:y.map(S=>s.jsx($e,{value:S.id,children:S.label},S.id))})]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"custom-model-id",children:r("上游模型 ID")}),s.jsx(Fe,{id:"custom-model-id",maxLength:128,placeholder:r("例如 gpt-5.5-preview"),autoComplete:"off",spellCheck:!1,autoFocus:!0,value:c,onChange:S=>d(S.currentTarget.value),onKeyDown:k})]}),s.jsxs("div",{className:"rounded-md border border-border bg-surface-inset px-3 py-2.5 font-mono text-[12px] text-subtle",children:[r("在 "),s.jsx("b",{className:"text-primary-fg",children:j}),r(" 上登记上游模型")," ",s.jsx("b",{className:"text-primary-fg",children:c.trim()||r("<上游模型 ID>")}),r("(登记后即可用这个名字请求)")]}),s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("填上游真正认识的那个模型 ID(不是给下游用的名字)。登记后它会进入该家的模型清单: 表格里出现这一行、"),s.jsx("code",{children:"/v1/models"}),r(" 会广告它、请求它也会被转发到这家。 支持字母、数字与 "),s.jsx("code",{children:"- _ . / :"}),r("。")]}),s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("「来源」列会标成"),s.jsx("b",{children:r("手动")}),r(",与远程目录 / 内置清单区分开。删除自定义模型是"),s.jsx("b",{children:r("直接移除")}),r("这条登记(不像内置模型那样只是隐藏),因为它的存在完全由这次登记决定。")]}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:f})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:h,onClick:()=>{w()},children:r("保存")})]})]})})}const nD='.page[data-page="gateway"]';let x0=null;function sD(){if(x0)return;const e=document.querySelector(nD);e&&(e.replaceChildren(),x0=jn.createRoot(e),x0.render(s.jsx(uX,{})))}document.querySelector(nD)?sD():document.addEventListener("DOMContentLoaded",sD,{once:!0});const rD=3065;function mX(){if(nl().workbuddyDesktop?.platform!=="web")return null;const e=typeof window>"u"?"":window.location?.origin;return e&&e!=="null"?e:null}function aD(e,t){return mX()??(e?`http://127.0.0.1:${e}`:t)}function nl(){return window}function ax(e){return e instanceof Error?e.message:String(e)}function Gu(e,t){nl().wbApp?.toast?.(e,t)}let bp={backend:null,gatewayBase:aD(0,`http://127.0.0.1:${rD}`)};const b0=new Set;function v0(){return bp}function hX(e){return b0.add(e),()=>{b0.delete(e)}}function gX(e){bp=e;for(const t of b0)t()}function lD(){return bp.gatewayBase.replace(/^https?:\/\//,"")}function xX(){return bp.backend?.ready===!0}function oD(e){const t=(a,o)=>{const c=document.getElementById(a);c&&(c.textContent=o)};t("api-base",`${e}/v1`),t("api-chat",`POST ${e}/v1/chat/completions`),t("api-responses",`POST ${e}/v1/responses`),t("api-messages",`POST ${e}/v1/messages`),t("api-models",`GET ${e}/v1/models`)}let y0=!1;async function Ku(){if(!y0){y0=!0;try{const e=nl().workbuddyDesktop;if(!e)throw new Error("后端桥不可用");const t=await e.getBackendStatus(),a=Number(t?.port)||0,o=v0(),c={backend:t??null,gatewayBase:aD(a,o.gatewayBase)};c.gatewayBase!==o.gatewayBase&&oD(c.gatewayBase),gX(c),nl().wbApp?.renderTopbarStatus?.()}catch(e){console.warn("读取后端状态失败:",ax(e))}finally{y0=!1}}}function bX(){oD(bp.gatewayBase),Ku()}async function iD(e){Gu(e||r("正在重启…"));try{await nl().workbuddyDesktop?.restartApp()}catch(t){Gu(r("重启失败:{reason}",{reason:ax(t)}),"err")}}const vX={idle:r("结束占用进程"),querying:r("查询中…"),ending:r("结束中…")};function yX({container:e}){const{backend:t,gatewayBase:a}=x.useSyncExternalStore(hX,v0),[o,c]=x.useState("idle"),d=t?.failure||null,f=lD(),p=t?.ready;let h="live off",b=r("正在检查… · {port}",{port:f});p===!0?(h="live pulse",b=r("网关运行中 · {port}",{port:f})):d?(h="live bad",b=r("{label} · {port}",{label:d.label||r("网关启动失败"),port:f})):p===!1&&(b=r("网关启动中… · {port}",{port:f}));const y=d?d.message??"":p===!0?r("本地网关正在监听 {url},可直接调用 OpenAI 兼容接口",{url:a}):r("正在确认网关是否已就绪");x.useEffect(()=>{Ku()},[]),x.useEffect(()=>{const j=nl().workbuddyDesktop?.onBackendError?.(()=>{Ku()});return typeof j=="function"?j:void 0},[]),x.useEffect(()=>{e.title=y},[e,y]);async function v(){if(o!=="idle")return;const j=nl().workbuddyDesktop;if(j){c("querying");try{const w=await j.getPortOccupant(),k=w?.occupant;if(!k){Gu(r("端口 {port} 上没有查到监听进程,请改用「更换端口」",{port:w?.port??""}),"err");return}const S=[r("即将结束以下进程:"),"",r("进程名:{name}",{name:String(k.name)}),r("PID:{pid}",{pid:String(k.pid)}),r("路径:{path}",{path:k.path||r("(未知)")}),"",r("结束它会强制退出该程序未保存的数据。确认继续?")],N=nl().wbConfirm?.ask;if(!N||!await N({title:r("结束占用端口的进程"),text:S.join(` +`),okText:r("结束进程"),okClass:"danger"}))return;c("ending"),(await j.endPortOccupant())?.released?(Gu(r("已结束进程 {name}(PID {pid}),端口已释放",{name:String(k.name),pid:String(k.pid)})),await N({title:r("重启程序"),text:r("端口已释放。现在重启程序让网关用这个端口启动?"),okText:r("重启")})?await iD(r("重启中…")):await Ku()):(Gu(r("进程已结束,但端口仍被占用,建议改用「更换端口」"),"err"),await Ku())}catch(w){Gu(r("结束失败:{reason}",{reason:ax(w)}),"err")}finally{c("idle")}}}return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"status-line",children:[s.jsx("span",{className:h}),s.jsx("span",{className:"txt",children:b})]}),d?.conflict?s.jsxs("div",{className:"status-actions",children:[d.canEndOccupant===!0?s.jsx(ne,{size:"sm",disabled:o!=="idle",onClick:()=>{v()},children:vX[o]}):null,s.jsx(ne,{size:"sm",onClick:()=>{SX()},children:r("更换端口")})]}):null]})}let j0=null;function cD(){if(j0)return;const e=document.getElementById("sidebar-status");e&&(e.replaceChildren(),j0=jn.createRoot(e),j0.render(s.jsx(yX,{container:e})))}const jX={idle:r("保存并重启"),checking:r("校验中…"),saving:r("保存中…")};function wX({status:e,onClose:t}){const a=Number(e?.port)||rD,[o,c]=x.useState(()=>a<65535?String(a+1):String(a-1)),[d,f]=x.useState("idle"),[p,h]=x.useState(""),[b,y]=x.useState(""),v=x.useRef(!0),j=Number(o)||0,w=e?.failure?.message||r("当前端口 {port},网关运行正常。",{port:a});async function k(){if(d!=="idle")return;const S=nl().workbuddyDesktop;if(!S)return;const N=Number(o)||0;if(!N||N<1024||N>65535){y(r("端口需在 1024-65535 之间"));return}f("checking"),y(""),h("");try{const R=await S.checkPort(N);if(!R?.ok){h(R?.message||r("该端口不可用"));return}if(R.same){h(R.message??"");return}if(f("saving"),(await S.changePort(N))?.changed===!1){h(r("与当前端口相同,无需重启"));return}t(),await iD(r("端口已改为 {port},正在重启…",{port:N}))}catch(R){y(ax(R))}finally{f("idle")}}return s.jsx(Yt,{open:!0,onOpenChange:S=>{S||t()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("更换网关端口")})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("当前状态")}),s.jsx("p",{children:w})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("新端口")}),s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5",children:[s.jsx(Je,{htmlFor:"port-input",className:"text-[12.5px] whitespace-nowrap text-subtle",children:r("端口号")}),s.jsx(Fe,{id:"port-input",type:"number",min:1024,max:65535,step:1,placeholder:r("例如 3066"),autoComplete:"off",className:"max-w-[130px]",value:o,onChange:S=>{c(S.currentTarget.value)},onKeyDown:S=>{S.key==="Enter"&&k()},autoFocus:!0,onFocus:S=>{v.current&&(v.current=!1,S.currentTarget.select())}})]}),p?s.jsx("p",{children:p}):null,s.jsx("p",{children:r("端口需在 1024-65535 之间。1023 及以下是系统保留范围,普通程序无法监听。")})]}),s.jsxs(dn,{children:[s.jsx("h3",{children:r("换端口后要改的地方")}),s.jsxs("p",{children:[r("网关地址会变成 "),s.jsx("code",{children:`http://127.0.0.1:${j||"—"}`}),r("。已经把这个地址填进其它工具(Claude Code、Cherry Studio 等)的,需要一并改成新地址,否则那些工具会连不上。")]})]}),s.jsx("p",{className:"min-h-[18px] text-[11.5px] text-muted-foreground",children:b})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:d!=="idle",onClick:()=>{k()},children:jX[d]})]})]})})}let vp=null,Yu=null;function uD(){vp&&(vp.unmount(),vp=null),Yu&&(Yu.remove(),Yu=null)}async function SX(){let e=v0().backend;e||(e=await nl().workbuddyDesktop?.getBackendStatus().catch(()=>null)??null),uD(),Yu=document.createElement("div"),document.body.append(Yu),vp=jn.createRoot(Yu),vp.render(s.jsx(wX,{status:e,onClose:uD}))}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",cD,{once:!0}):cD(),window.wbPortPanel={render:bX,sync:Ku,portLabel:lD,isReady:xX};function nn(){return window}function Es(e,t){nn().wbApp?.toast?.(e,t)}function mr(e){return e instanceof Error?e.message:String(e)}function dD(e){const t=String(e||"").trim();return/^https?:\/\//i.test(t)?t:""}async function fD(e){const t=dD(e);if(!t){Es(r("链接地址不受支持"),"err");return}try{await nn().workbuddyDesktop?.openReleasePage(t)}catch(a){Es(r("打开链接失败:{error}",{error:mr(a)}),"err")}}const lx="1127656296",NX=`assets/qq-group/${lx}.jpg`;function pD(e){return nn().wbMarkdown?.render?.(e)||""}function Xu(e){const a=e.target?.closest?.("[data-external]");a&&(e.preventDefault(),fD(a.dataset.external||""))}async function kX(){try{const e=await nn().workbuddyDesktop?.getUpdateStatus?.();e&&e.checked!==!1&&nn().wbApp?.updateUpdateBadge?.(e)}catch(e){console.warn("读取版本检查结果失败:",mr(e))}}const yp="__proxy_other__",mD={proxyChoice:null,pool:null,poolError:""};async function CX(){const e=nn().workbuddyDesktop,t={...mD};if(!e?.getUpdateProxy)return t;try{t.proxyChoice=(await e.getUpdateProxy())?.proxy??null}catch{}try{if(typeof e.getProxyPool!="function")throw new Error("桥未提供代理池方法");const a=(await e.getProxyPool())?.items;if(!Array.isArray(a))throw new Error("代理池响应异常");t.pool=a}catch(a){t.pool=[],t.poolError=mr(a)}return t}async function TX(e){if(e===yp)return null;const t=nn().workbuddyDesktop;if(!t?.setUpdateProxy)return null;const a=e===""?null:{source:"pool",proxyId:e.slice(Qa.length)};try{const o=await t.setUpdateProxy({proxy:a}),c=o?.proxy??null,d=o?.saved!==!1;return d?Es(c?r("✅ 更新出网已切换为 {label}",{label:c.label||r("指定代理")}):r("✅ 更新出网已切换为直连")):Es(r("出网线路已切换,但写入磁盘失败(重启后会恢复原线路)"),"err"),{choice:c,saved:d}}catch(o){return Es(r("保存失败:{error}",{error:mr(o)}),"err"),null}}function hD(e){const t=e.proxyChoice,a=t?.config?.source||t?.source,o=t?.label||r(a==="custom"?"自定义代理":"已设置"),c=!!t?.error,d=Array.isArray(e.pool)?e.pool:[];let f="";a==="pool"&&t?.config?.proxyId?f=`${Qa}${t.config.proxyId}`:t&&(f=yp);const p=[{value:"",label:r("直连")}];for(const h of d)p.push({value:`${Qa}${h.id}`,label:fu(h)});if(e.pool===null?p.push({value:"__hint_pool__",label:r("正在读取代理列表…"),disabled:!0}):d.length||p.push({value:"__hint_pool__",label:e.poolError?r("代理列表读取失败"):r("还没有代理(去「网络代理」页添加)"),disabled:!0}),f===yp){const h=a==="clash"?r("Clash 出口:"):a==="custom"?r("自定义:"):"";p.push({value:yp,label:`${h}${o}${c?r("(不可用)"):""}`})}else a==="pool"&&!d.some(h=>`${Qa}${h.id}`===f)&&p.push({value:f,label:`${o}${c?r("(不可用)"):""}`});return{current:f,items:p,selected:p.find(h=>h.value===f),broken:c,title:c?r("当前线路不可用:{error};请重新选择代理或切回直连",{error:String(t?.error||"")}):r("检查更新与下载安装包走哪条线路(当前:{current});选择即保存。选项来自「网络代理」页;直连失败时会自动借 Clash 混合端口重试一次,选定指定代理后只走它",{current:t?o:r("直连")})}}const Ho="https://proxylane.dev/zh-cn/isp-proxies?utm_source=agent2api&utm_medium=partnership&utm_campaign=agent2api_202610&utm_content=client",EX="assets/proxylane-logo-for-light-bg.png",AX="assets/proxylane-logo-for-dark-bg.png";function gD({children:e}){return s.jsx("a",{className:"font-semibold text-primary-fg no-underline hover:underline",href:Ho,"data-external":Ho,onClick:Xu,children:e})}function RX({item:e,onClose:t}){const a=e!==null,[o,c]=x.useState(e?.name||""),[d,f]=x.useState(e?.protocol==="socks5"?"socks5":"http"),[p,h]=x.useState(e?.host||""),[b,y]=x.useState(e?.port?String(e.port):""),[v,j]=x.useState(e?.username||""),[w,k]=x.useState(e?.password||""),[S,N]=x.useState(e?e.enabled:!0),[R,P]=x.useState(!1),[T,C]=x.useState(!1),[E,D]=x.useState(null);function I(){const z=o.trim();if(!z)return{error:r("请填写代理名称")};const H=p.trim();if(!H)return{error:r("请填写代理主机地址")};const B=Number(b);return!Number.isInteger(B)||B<1||B>65535?{error:r("代理端口必须是 1-65535 的整数")}:{payload:{name:z,source:"manual",protocol:d,host:H,port:B,username:v.trim(),password:w,enabled:S}}}async function O(){if(T)return;const z=I();if("error"in z){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",z.error]}));return}const H=z.payload,B={source:"custom",protocol:H.protocol,host:H.host,port:H.port,username:H.username,password:H.password};C(!0),D(r("正在连接上游…"));try{const L=await tr().workbuddyDesktop?.testProxy?.({proxy:B});if(L?.success){const F=Uj(L.durationMs);D(s.jsxs("span",{className:"text-success",children:[r("✅ 出口可用"),L.ip?r(" 出口 IP {ip}",{ip:L.ip}):"",F?` ${F}`:""]}))}else D(s.jsxs("span",{className:"text-destructive",children:["❌ ",L?.error||r("连接失败")]}))}catch(L){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",Ra(L)]}))}finally{C(!1)}}async function _(){if(R)return;const z=I();if("error"in z){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",z.error]}));return}P(!0),D(null);try{await _q(e,z.payload),qn(a?r("已保存「{name}」",{name:o.trim()}):r("已新增「{name}」",{name:o.trim()})),t()}catch(H){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",Ra(H)]})),P(!1)}}return s.jsx(Yt,{open:!0,onOpenChange:z=>{!z&&!R&&t()},children:s.jsxs(Xt,{className:"max-w-[560px]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r(a?"编辑代理":"新增代理")})}),s.jsxs(Lt,{className:"flex flex-col gap-3.5",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-name",children:r("名称")}),s.jsx(Fe,{id:"proxy-name",maxLength:60,autoComplete:"off",spellCheck:!1,placeholder:r("例如:香港 HTTP 出口"),value:o,onChange:z=>c(z.currentTarget.value)})]}),s.jsxs("div",{className:"flex flex-row items-end gap-2.5",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-protocol",children:r("协议")}),s.jsxs(dt,{value:d,onValueChange:z=>f(z),children:[s.jsx(pt,{id:"proxy-protocol",className:"min-w-[110px]",children:s.jsx(ft,{children:d==="socks5"?"SOCKS5":"HTTP"})}),s.jsxs(mt,{children:[s.jsx($e,{value:"http",children:"HTTP"}),s.jsx($e,{value:"socks5",children:"SOCKS5"})]})]})]}),s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-host",children:r("主机")}),s.jsx(Fe,{id:"proxy-host",placeholder:"127.0.0.1",autoComplete:"off",spellCheck:!1,value:p,onChange:z=>h(z.currentTarget.value)})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-port",children:r("端口")}),s.jsx(Fe,{id:"proxy-port",type:"number",min:1,max:65535,className:"max-w-[110px]",placeholder:"7890",value:b,onChange:z=>y(z.currentTarget.value)})]})]}),s.jsxs("div",{className:"flex flex-row items-end gap-2.5",children:[s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-user",children:r("用户名")}),s.jsx(Fe,{id:"proxy-user",placeholder:r("可选"),autoComplete:"off",value:v,onChange:z=>j(z.currentTarget.value)})]}),s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-pass",children:r("密码")}),s.jsx(Fe,{id:"proxy-pass",placeholder:r("可选"),autoComplete:"off",value:w,onChange:z=>k(z.currentTarget.value)})]})]}),s.jsxs("div",{className:"flex flex-row items-center gap-2.5",children:[s.jsx(Zn,{checked:S,onCheckedChange:N,"aria-label":r("启用这条代理")}),s.jsx("span",{className:"text-[12.5px]",children:r("启用(禁用的条目不会被账号使用,被引用时账号回退直连;仍可测试)")})]}),s.jsxs("p",{className:"text-xs leading-[1.65] text-subtle",children:[r("需要干净的出口?"),s.jsx(gD,{children:"ProxyLane"}),r(" AI 账号专用静态住宅 IP:Scamalytics 低欺诈评分,不限流量,首单 75 折(AGENT2API25)")," ",s.jsx(gD,{children:r("去获取")})]}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:E})]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",disabled:T||R,onClick:()=>{O()},children:r(T?"测试中…":"测试出口")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:R,onClick:t,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:R,onClick:()=>{_()},children:r(R?"保存中…":"保存")})]})]})})}function OX({onClose:e}){const[t,a]=x.useState(!0),[o,c]=x.useState(!1),[d,f]=x.useState(""),[p,h]=x.useState(""),[b,y]=x.useState(""),[v,j]=x.useState({}),[w,k]=x.useState(""),[S,N]=x.useState(!1);x.useEffect(()=>{let C=!0;return(async()=>{try{const E=await pO();if(!C||E===null)return;f(String(E.listenerPortBase??"")),h(String(E.listenerPortEnd??"")),y(String(E.testUrl??"")),j(E.defaults??{}),a(!1)}catch(E){if(!C)return;k(Ra(E)),a(!1)}})(),()=>{C=!1}},[]);function R(){const C=Number(d),E=Number(p);if(!Number.isInteger(C)||C<1||C>65535||!Number.isInteger(E)||E<1||E>65535)return k(r("端口范围必须是 1-65535 的整数")),null;if(C>E)return k(r("起始端口不能大于结束端口")),null;const D=b.trim();return D&&!D.startsWith("http://")&&!D.startsWith("https://")?(k(r("测试网址要以 http:// 或 https:// 开头")),null):(k(""),{listenerPortBase:C,listenerPortEnd:E,testUrl:D})}async function P(){if(o||t)return;const C=R();if(C){c(!0);try{await Lq(C),N(!0)}catch(E){k(Ra(E))}finally{c(!1)}}}function T(){f(String(v.listenerPortBase??"")),h(String(v.listenerPortEnd??"")),y(String(v.testUrl??"")),N(!1),k("")}return s.jsx(Yt,{open:!0,onOpenChange:C=>{!C&&!o&&e()},children:s.jsxs(Xt,{className:"max-w-[560px]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("代理设置")})}),s.jsx(Lt,{className:"flex flex-col gap-3.5",children:t?s.jsx("p",{className:"text-xs text-subtle",children:r("加载中…")}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"flex flex-row items-end gap-2.5",children:[s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-settings-base",children:r("节点端口范围(起始)")}),s.jsx(Fe,{id:"proxy-settings-base",type:"number",min:1,max:65535,placeholder:String(v.listenerPortBase??""),autoComplete:"off",value:d,onChange:C=>{f(C.currentTarget.value),N(!1)}})]}),s.jsx("span",{"aria-hidden":"true",className:"flex-none pb-[7px] text-subtle",children:"—"}),s.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-settings-end",children:r("节点端口范围(结束)")}),s.jsx(Fe,{id:"proxy-settings-end",type:"number",min:1,max:65535,placeholder:String(v.listenerPortEnd??""),autoComplete:"off",value:p,onChange:C=>{h(C.currentTarget.value),N(!1)}})]})]}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r("订阅节点会在本机各占一个监听端口,从该范围里挑空闲的分配;节点多的大订阅把默认范围({base}-{end})用尽时会报「没有可用的节点端口」,这时把范围调大再重启内核。已分配出去的端口不会因改范围而失效。",{base:v.listenerPortBase??"",end:v.listenerPortEnd??""})}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"proxy-settings-url",children:r("出口测试网址")}),s.jsx(Fe,{id:"proxy-settings-url",placeholder:v.testUrl||"",autoComplete:"off",spellCheck:!1,className:"font-mono text-[12px]",value:b,onChange:C=>{y(C.currentTarget.value),N(!1)}})]}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r("「测试」与「批量测试」访问的目标;留空用默认(打 WorkBuddy 上游)。判据是能否拿到 HTTP 响应,不用考虑该网址返回什么内容。")}),s.jsxs("div",{className:"min-h-[18px] text-xs",children:[w?s.jsxs("span",{className:"text-destructive",children:["❌ ",w]}):null,!w&&S?s.jsxs("span",{className:"text-success",children:["✅ ",r("已保存。重启内核后,新分配的节点端口才会按新范围来。")]}):null]})]})}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"ghost",disabled:t||o,onClick:T,children:r("恢复默认")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:o,onClick:e,children:r("关闭")}),s.jsx(ne,{variant:"default",disabled:t||o,onClick:()=>{P()},children:r(o?"保存中…":"保存")})]})]})})}function xD(e){return(Math.max(0,Number(e)||0)/1024/1024).toFixed(1)}function MX(e){return/^[A-Za-z]:[\\/]/.test(e)||e.startsWith("\\\\")||e.startsWith("/")}function DX({onClose:e}){const t=x.useSyncExternalStore(jg,wg),a=Nu(),o=a?.download,c=o?.state==="downloading",d=c&&o&&o.total>0?Math.round(o.received/o.total*100):null,[f,p]=x.useState(null),[h,b]=x.useState(""),[y,v]=x.useState(null),[j,w]=x.useState(a?.kernelDir||""),[k,S]=x.useState(!1),[N,R]=x.useState(!1),[P,T]=x.useState("");x.useEffect(()=>{let H=!0;return(async()=>{try{const B=(await nr().workbuddyDesktop?.getProxyPool?.())?.items;if(!Array.isArray(B))throw new Error(r("代理池响应异常"));H&&p(B)}catch(B){if(!H)return;p([]),b(Sr(B))}})(),()=>{H=!1}},[]),x.useEffect(()=>{a?.installed&&e()},[a?.installed]);const C=hD({proxyChoice:a?.downloadProxy??null,pool:f,poolError:h}),E=y??C.current,D=C.items.find(H=>H.value===E)??C.selected,I=a?.kernelDirDefault||"";async function O(){if(k)return;const H=j.trim();if(H&&!MX(H)){T(r("存放位置要填绝对路径,例如 D:\\proxy-kernel"));return}T(""),S(!0);try{const B={dir:H};E!==yp&&(B.proxy=E===""?null:{source:"pool",proxyId:E.slice(Qa.length)}),$q(B)}finally{S(!1)}}async function _(){if(!N){R(!0);try{const H=await qq();H==="done"?an(r("下载已经完成,停止没赶上(内核已安装)")):H==="none"?an(r("当前没有正在进行的下载"),"err"):H==="stalled"&&an(r("停止请求已发出,但下载还没收手,稍后再看一次进度"),"err")}finally{R(!1)}}}async function z(){const H=nr().workbuddyDesktop;if(typeof H?.pickFolder!="function"){an(r("当前环境不支持选择文件夹,直接填写绝对路径即可"),"err");return}try{const B=await H.pickFolder(j.trim()||I||null);if(B?.unsupported){an(r("当前环境不支持选择文件夹,直接填写绝对路径即可"),"err");return}if(B?.canceled||!B?.path)return;w(B.path)}catch(B){an(r("打开文件夹选择框失败:{reason}",{reason:Sr(B)}),"err")}}return s.jsx(Yt,{open:!0,onOpenChange:H=>{H||e()},children:s.jsxs(Xt,{className:"w-[min(520px,calc(100vw-48px))]",children:[s.jsxs(Vt,{children:[s.jsx(Ut,{children:r(c?"正在下载内核":"下载内核")}),s.jsx("span",{className:"text-[11.5px] text-subtle",children:r("内核 {version}({asset})",{version:a?.version||"—",asset:a?.asset||"—"})})]}),c?s.jsxs(Lt,{className:"flex flex-col gap-3",children:[s.jsx(cf,{value:d??null}),s.jsxs("div",{className:"flex items-center justify-between text-[12px]",children:[s.jsx("span",{className:"text-text-2",children:d!==null?r("{percent}%({received} / {total} MB)",{percent:d,received:xD(o?.received),total:xD(o?.total)}):r("正在连接 GitHub…")}),s.jsx("span",{className:"text-subtle",children:r("存放位置 {dir}",{dir:a?.kernelDir||"—"})})]}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r("关掉这个窗口不会中断下载(它在后台继续跑)—— 要停下就点下面的「停止下载」,未下载完的临时文件会被删除。")})]}):s.jsxs(Lt,{className:"flex flex-col gap-3.5",children:[s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"kernel-proxy",children:r("下载线路")}),s.jsxs(dt,{value:E,onValueChange:H=>v(String(H)),children:[s.jsx(pt,{id:"kernel-proxy",className:Ue("w-full",C.broken&&"border-destructive-bd"),children:s.jsx(ft,{className:"min-w-0 truncate",children:D?.label||r("直连")})}),s.jsx(mt,{children:C.items.map(H=>s.jsx($e,{value:H.value,disabled:H.disabled,children:H.label},H.value))})]}),s.jsx("div",{className:"text-[12px] text-subtle",children:C.broken?r("当前线路不可用:{error};重新选一条或切回直连",{error:String(a?.downloadProxy?.error||"")}):r("选项来自「网络代理」页(Clash Verge 同步的出口在这里可用;订阅节点要等内核起来才有端口)。选「直连」时连不上会自动借 Clash 混合端口重试一次;选定某条线路后只走它。")})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"kernel-dir",children:r("存放位置")}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(Fe,{id:"kernel-dir",className:"min-w-0 flex-1 font-mono text-[12px]",autoComplete:"off",spellCheck:!1,value:j,placeholder:I,onChange:H=>w(H.currentTarget.value)}),s.jsx(ne,{variant:"outline",size:"sm",className:"flex-none",onClick:()=>{z()},children:r("选择目录…")}),I&&j.trim()!==I?s.jsx(ne,{variant:"ghost",size:"sm",className:"flex-none",title:I,onClick:()=>w(I),children:r("恢复默认")}):null]}),s.jsx("div",{className:"text-[12px] text-subtle",children:r("内核二进制 / 配置 / 端口映射都会放在这里,默认 {dir};目录不存在会在下载开始时自动创建。",{dir:I||"—"})})]}),o?.state==="error"&&o.error?s.jsx("span",{className:"text-[12px] text-destructive",children:r("上次下载失败:{reason}",{reason:o.error})}):null,o?.state==="canceled"?s.jsx("span",{className:"text-[12px] text-subtle",children:r("上次下载已停止,未下载完的临时文件已删除")}):null,P?s.jsx("span",{className:"text-[12px] text-destructive",children:P}):null]}),s.jsx(tn,{children:c?s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:e,children:r("后台继续")}),s.jsx(ne,{variant:"destructive",disabled:N,onClick:()=>{_()},children:r(N?"正在停止…":"停止下载")})]}):s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:e,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:k||t.pending,onClick:()=>{O()},children:r(k?"正在开始…":"下载")})]})})]})})}function bD({showPortRange:e=!1}){const t=x.useSyncExternalStore(jg,wg),a=Nu(),[o,c]=x.useState(null),[d,f]=x.useState(!1);x.useEffect(()=>{let b=!0;return(async()=>{try{const y=await pO();if(!b||!y)return;const v=Number(y.listenerPortBase),j=Number(y.listenerPortEnd);Number.isFinite(v)&&Number.isFinite(j)&&v>0&&j>0&&c({base:v,end:j})}catch{}})(),()=>{b=!1}},[]);const p=a?.download.state==="downloading",h=p&&a.download.total>0?Math.round(a.download.received/a.download.total*100):null;return s.jsxs("div",{className:"flex flex-col gap-2 rounded-md border border-border bg-surface-2 px-3 py-2",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[s.jsx(ze,{variant:a?.running?"default":"secondary",children:a?.running?r("内核运行中"):a?.installed?a.halted?r("内核已手动关闭"):r("内核已停止"):r("内核未安装")}),s.jsxs("span",{className:"text-[12.5px] text-text-2",children:[a?.installed?r("内核 {version}",{version:a.version})+" · ":"",a?.running?r("控制端口 {port} · {n} 个节点监听器",{port:a?.controllerPort??"—",n:a?.listenerCount??0}):a?.installed?a.halted?r("内核已手动关闭(点「启动内核」拉起)"):r("内核已停止,点「启动内核」拉起"):r("按需下载(约 20-40MB)")]}),e&&o?s.jsx("span",{className:"text-[11.5px] text-subtle",children:r("节点端口范围 {base}–{end}",{base:o.base,end:o.end})}):null,s.jsx("div",{className:"ml-auto flex items-center gap-2",children:a?.installed?s.jsxs(s.Fragment,{children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:t.pending||p,onClick:()=>{Gq()},children:a?.running?r("重启内核"):r("启动内核")}),a?.running?s.jsx(ne,{size:"sm",variant:"outline",disabled:t.pending||p,onClick:()=>{Kq()},children:r("关闭内核")}):null,s.jsx(ne,{size:"sm",variant:"destructive",disabled:t.pending||p,onClick:()=>{Yq()},children:r("删除内核")})]}):s.jsx(ne,{size:"sm",variant:"outline",disabled:t.pending&&!p,onClick:()=>f(!0),children:r(p?"下载中…":"下载内核")})})]}),p?s.jsxs("div",{className:"flex items-center gap-3",children:[s.jsx(cf,{className:"min-w-[200px] flex-1",value:h??null}),s.jsx("span",{className:"text-[11px] text-subtle",children:h!==null?r("{percent}%({received} / {total} MB)",{percent:h,received:vD(a.download.received),total:vD(a.download.total)}):r("下载中…")})]}):null,a?.lastError?s.jsx("span",{className:"text-[12px] text-destructive",children:a.lastError}):null,d?s.jsx(DX,{onClose:()=>f(!1)}):null]})}function IX({onClose:e}){const t=x.useSyncExternalStore(jg,wg),a=x.useSyncExternalStore(uO,dO),o=zq(),c=t.data!==null,[d,f]=x.useState(null);return x.useEffect(()=>{Ml()},[]),s.jsxs(Yt,{open:!0,onOpenChange:p=>{p||e()},children:[s.jsxs(Xt,{className:"w-[min(880px,calc(100vw-48px))]",children:[s.jsxs(Vt,{children:[s.jsx(Ut,{children:r("订阅管理")}),s.jsxs("span",{className:"text-[11.5px] text-subtle",children:[c?r("{n} 条订阅",{n:o.length}):r("加载中…")," · ",r("节点由内核起成本地监听器,镜像进代理池")]})]}),s.jsxs(Lt,{className:"flex flex-col gap-3",children:[s.jsx(bD,{}),s.jsx("div",{className:"models-table-wrap",children:s.jsxs("table",{className:"models-table",children:[s.jsxs("colgroup",{children:[s.jsx("col",{className:"w-[18%]"}),s.jsx("col",{className:"w-[31%]"}),s.jsx("col",{className:"w-[9%]"}),s.jsx("col",{className:"w-[14%]"}),s.jsx("col",{className:"w-[8%]"}),s.jsx("col",{className:"w-[20%]"})]}),s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{children:r("名称")}),s.jsx("th",{children:r("订阅来源")}),s.jsx("th",{className:"ta-center",children:r("节点")}),s.jsx("th",{children:r("上次同步")}),s.jsx("th",{className:"ta-center",children:r("启用")}),s.jsx("th",{className:"ta-right",children:r("操作")})]})}),s.jsx("tbody",{children:o.length?o.map(p=>{const h=Nu()?.providerSync?.[p.id];return s.jsxs("tr",{className:p.enabled?"":"off",children:[s.jsx("td",{children:s.jsx("b",{children:p.name||r("未命名")})}),s.jsx("td",{className:"group",children:s.jsx("div",{className:"flex min-w-0 items-center gap-1",children:p.kind==="local"?s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"min-w-0 truncate font-mono text-[12px] text-text-2",title:p.fileName,children:p.fileName||r("本地 YAML 文件")}),s.jsx(ze,{variant:"secondary",children:r("本地文件")})]}):s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"min-w-0 truncate font-mono text-[12px] text-text-2",title:p.url,children:PX(p.url)}),s.jsx(ne,{variant:"ghost",size:"icon-xs",className:"copy-btn size-[21px] rounded-[var(--r-xs)] opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100","data-copy":p.url,title:r("复制订阅链接"),children:"⧉"})]})})}),s.jsx("td",{className:"ta-center",children:yD(h,p)>0?s.jsx(ze,{variant:"secondary",children:r("{n} 个",{n:yD(h,p)})}):s.jsx("span",{className:"text-subtle",children:r("—")})}),s.jsx("td",{children:h?.at?s.jsx("span",{className:"text-[12px] text-text-2",children:rO(h.at)}):s.jsx("span",{className:"text-subtle",children:r("未同步")})}),s.jsx("td",{className:"ta-center",children:s.jsx(Zn,{checked:p.enabled,disabled:t.pending,"aria-label":r("启用订阅「{name}」",{name:p.name||r("未命名")}),onCheckedChange:b=>{Uq(p,b)}})}),s.jsx("td",{children:s.jsxs("div",{className:"row-actions",children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:t.pending||t.refreshing!==null||p.kind==="local",title:p.kind==="local"?r("本地文件订阅无需更新(要换内容请编辑后重新选择文件)"):void 0,onClick:()=>{Vq(p)},children:t.refreshing===p.id?r("更新中…"):r("立即更新")}),s.jsx(ne,{size:"sm",variant:"ghost",disabled:t.pending,onClick:()=>f({item:p}),children:r("编辑")}),s.jsx(ne,{size:"sm",variant:"destructive",disabled:t.pending,onClick:()=>{Fq(p)},children:r("删除")})]})})]},p.id)}):s.jsx("tr",{children:s.jsx("td",{colSpan:6,className:"empty",children:c?s.jsxs("div",{className:"flex flex-col items-center gap-2 py-3",children:[s.jsx("span",{children:r("还没有订阅:粘贴订阅链接、导入本地 YAML 文件,或从图片识别二维码。")}),s.jsx(ne,{size:"sm",variant:"outline",disabled:t.pending,onClick:()=>f({item:null}),children:r("+ 新增订阅")}),s.jsx("span",{className:"text-[11px] text-subtle",children:r("订阅里的节点会自动同步进代理池,账号即可引用。")})]}):r("加载中…")})})})]})}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r("订阅里的节点会被内核起成本地监听器,镜像到代理池(账号按 id 引用,与本页其它出口同一用法)。内核只在用到订阅时按需下载(约 20-40MB),不随安装包分发。")}),t.error?s.jsx("span",{className:"text-destructive",children:r("读取失败:{reason}",{reason:t.error})}):null]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"default",disabled:t.pending,onClick:()=>f({item:null}),children:r("+ 新增订阅")}),s.jsx(ne,{variant:"outline",disabled:a.syncing||a.batchBusy,onClick:()=>{Rq()},children:a.syncing?r("同步中…"):r("同步 Clash Verge")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:e,children:r("完成")})]})]}),d?s.jsx(LX,{item:d.item,onClose:()=>f(null)}):null]})}function vD(e){return!Number.isFinite(e)||e<=0?"—":(e/1e3/1e3).toFixed(1)}function PX(e){try{const t=new URL(e);return t.host+(t.pathname!=="/"?"/…":"")}catch{return e.slice(0,60)}}function yD(e,t){return e?.count??t.nodeCount}function _X(){return s.jsxs("div",{className:"flex flex-col gap-2.5 rounded-lg border border-border bg-surface-2 px-3.5 py-3",children:[s.jsxs("a",{href:Ho,"data-external":Ho,onClick:Xu,className:"inline-flex w-fit items-center no-underline",children:[s.jsx("img",{src:EX,alt:"ProxyLane",className:"h-[24px] w-auto dark:hidden"}),s.jsx("img",{src:AX,alt:"ProxyLane",className:"hidden h-[24px] w-auto dark:block"})]}),s.jsxs("p",{className:"text-xs leading-[1.7] text-text-2",children:[s.jsx("a",{className:"font-semibold text-primary-fg no-underline hover:underline",href:Ho,"data-external":Ho,onClick:Xu,children:"ProxyLane"}),r(" 提供 AI 账号专用的原生静态住宅 IP(Static Residential ISP):IP 来自真实家庭宽带运营商,Scamalytics 低欺诈评分,每个 IP 独享,不限流量,$3.90 起。")]}),s.jsx("p",{className:"text-xs leading-[1.7] text-text-2",children:r("首次购买使用优惠码 AGENT2API25 享 75 折。")}),s.jsx("div",{children:s.jsx(ne,{size:"sm",render:s.jsx("a",{href:Ho,"data-external":Ho,onClick:Xu}),children:r("去获取")})})]})}function LX({item:e,onClose:t}){const a=e!==null,[o,c]=x.useState(e?.kind==="local"?"local":"url"),[d,f]=x.useState(e?.name||""),[p,h]=x.useState(e?.url||""),[b,y]=x.useState(e?.fileName||""),[v,j]=x.useState(""),[w,k]=x.useState(e?e.enabled:!0),[S,N]=x.useState(!1),[R,P]=x.useState(!1),[T,C]=x.useState(!1),[E,D]=x.useState(null),I=x.useRef(null);async function O(){if(S)return;const L=d.trim();if(!L){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",r("请填写订阅名称")]}));return}const F=p.trim();if(o==="url"&&!(F.startsWith("http://")||F.startsWith("https://"))){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",r("订阅链接必须是 http:// 或 https:// 开头")]}));return}if(!a&&o==="local"&&!v){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",r("请选择要导入的 YAML 文件")]}));return}N(!0);try{a&&o==="local"?await hO(e,{name:L,enabled:w,kind:"local",fileName:b||void 0,...v?{contentB64:v}:{}}):a?await hO(e,{name:L,url:F,enabled:w,kind:"url"}):o==="local"?await mO({name:L,kind:"local",fileName:b||void 0,contentB64:v}):await mO({name:L,kind:"url",url:F}),t()}catch($){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",Sr($)]})),N(!1)}}async function _(L){if(!R){P(!0),D(r("正在识别二维码…"));try{const F=await Xq(L);h(F),D(s.jsxs("span",{className:"text-success",children:["✅ ",r("已识别订阅链接")]}))}catch(F){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",Sr(F)]}))}finally{P(!1)}}}async function z(L){if(!T){C(!0),D(null);try{const F=await gO(L);j(F),y(L.name),D(s.jsxs("span",{className:"text-success",children:["✅ ",r("已选择「{name}」,保存后导入",{name:L.name})]}))}catch(F){D(s.jsxs("span",{className:"text-destructive",children:["❌ ",Sr(F)]}))}finally{C(!1)}}}function H(L){if(o!=="url")return;const $=Array.from(L.clipboardData?.files||[]).find(X=>X.type.startsWith("image/"));$&&(L.preventDefault(),_($))}function B(L){L!==o&&(c(L),D(null))}return s.jsx(Yt,{open:!0,onOpenChange:L=>{!L&&!S&&t()},children:s.jsxs(Xt,{className:"max-w-[560px]",overlayForceRender:!0,onPaste:H,children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r(a?"编辑订阅":"新增订阅")})}),s.jsxs(Lt,{className:"flex flex-col gap-3.5",children:[o==="residential"?null:s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"sub-name",children:r("名称")}),s.jsx(Fe,{id:"sub-name",maxLength:60,autoComplete:"off",spellCheck:!1,placeholder:r("例如:我的机场"),value:d,onChange:L=>f(L.currentTarget.value)})]}),a?null:s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{children:r("订阅来源")}),s.jsx(En,{options:[{value:"url",label:r("订阅链接")},{value:"local",label:r("本地 YAML 文件")},{value:"residential",label:r("家庭宽带")}],value:o,onValueChange:B,"aria-label":r("订阅来源")})]}),o==="residential"?s.jsx(_X,{}):o==="url"?s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"sub-url",children:r("订阅链接")}),s.jsx(Fe,{id:"sub-url",autoComplete:"off",spellCheck:!1,placeholder:"https://…",value:p,onChange:L=>h(L.currentTarget.value)}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:R,onClick:()=>I.current?.click(),children:r(R?"识别中…":"从图片识别二维码")}),s.jsx("span",{className:"text-[11px] text-subtle",children:r("也可以把二维码截图直接粘贴到弹窗里(Ctrl+V)")}),s.jsx("input",{ref:I,type:"file",accept:"image/*",className:"hidden",onChange:L=>{const F=L.currentTarget.files?.[0];F&&_(F),L.currentTarget.value=""}})]})]}):s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"sub-file",children:r("YAML 文件")}),s.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[s.jsx(ne,{size:"sm",variant:"outline",disabled:T,className:"shrink-0",onClick:()=>I.current?.click(),children:r(T?"读取中…":a?"重新选择文件…":"选择 YAML 文件…")}),s.jsx("span",{className:"min-w-0 truncate font-mono text-[12px] text-text-2",title:b||void 0,children:b||r(a?"保持原文件":"未选择文件")})]}),a?s.jsx("span",{className:"text-[11px] text-subtle",children:r("本地文件不会自动更新:要更新节点,重新选择文件后保存;不重选则内容保持不变。")}):null,s.jsx("input",{ref:I,type:"file",accept:".yaml,.yml,text/yaml,application/yaml,text/plain",className:"hidden",onChange:L=>{const F=L.currentTarget.files?.[0];F&&z(F),L.currentTarget.value=""}})]}),o==="residential"?null:s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"flex flex-row items-center gap-2.5",children:[s.jsx(Zn,{checked:w,onCheckedChange:k,"aria-label":r("启用这条订阅")}),s.jsx("span",{className:"text-[12.5px]",children:r("启用(禁用的订阅不参与内核同步,它的节点会从代理池移除)")})]}),s.jsx("p",{className:"text-xs leading-[1.65] text-subtle",children:r(o==="url"?"订阅内容由内核定时刷新(每 24 小时);节点数与同步状态在保存后由轮询刷新,稍等几秒。":"本地文件订阅的内容在导入时固定:节点会由内核起成本地监听器并镜像进代理池,节点数稍等几秒由轮询刷新。")}),s.jsx("div",{className:"min-h-[18px] text-xs text-subtle",children:E})]})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",disabled:S,onClick:t,children:r("取消")}),o==="residential"?null:s.jsx(ne,{variant:"default",disabled:S||R||T,onClick:()=>{O()},children:r(S?"保存中…":"保存")})]})]})})}const w0=[{key:"pick",label:r("选择"),align:"center"},{key:"name",label:r("节点")},{key:"addr",label:r("地址")},{key:"state",label:r("启用"),align:"center"},{key:"test",label:r("连通性")},{key:"act",label:r("操作"),align:"right"}],zX={pick:"p-pick",name:"",addr:"p-addr",state:"p-state",test:"p-test",act:"p-act"},jD="proxies";function S0(){return window}let ox=null,wD=null;function SD(){return ox?ox.apply([...w0]):w0.map(e=>({...e,align:e.align??"left"}))}function BX(){S0().wbTableColumns?.repaint?.(jD)}function HX(e){if(wD=e,ox)return!0;const t=S0().wbColSettings;return t?.register?(ox=t.register({id:jD,label:r("代理池表"),columns:w0.map(a=>({key:a.key,label:a.label,align:a.align??"left"})),mount:()=>document.querySelector('.page[data-page="proxies"] .panel-head .head-actions'),onChange:()=>wD?.()}),!0):!1}function UX(){S0().wbColSettings?.close?.()}function VX(){const e=x.useSyncExternalStore(uO,dO),t=x.useSyncExternalStore(jg,wg).data?.items??[],[a,o]=x.useState(null),[c,d]=x.useState(!1),[f,p]=x.useState(!1),[h,b]=x.useState(""),[y,v]=x.useState("all"),[j,w]=x.useState("all"),[k,S]=x.useState("all"),[N,R]=x.useState(0),[,P]=x.useReducer(W=>W+1,0),T=yg(),C=e.data!==null,E=e.selected.size,D=T.filter(W=>e.selected.has(W.id)&&bg(W)).length,I=e.batchProgress;x.useEffect(()=>{Ml()},[]),x.useLayoutEffect(()=>{if(!HX(()=>P())){const W=window.setTimeout(()=>R(ue=>ue+1),50);return()=>window.clearTimeout(W)}P()},[N]),x.useLayoutEffect(()=>{BX()}),x.useEffect(()=>()=>{UX()},[]);const O=h.trim().toLowerCase(),_=qX(T,t);function z(W){return j==="all"?!0:j==="manual"||j==="clash"||j==="subscription"?sl(W)===j:j===CD?!!W.orphan:W.source==="subscription"&&!W.orphan&&W.providerId===j}function H(W){return!(y!=="all"&&sl(W)!==y||!z(W)||k!=="all"&&kD(W)!==k||O&&![W.name,Xh(W),W.host,W.protocol,String(W.port??"")].join(" ").toLowerCase().includes(O))}function B(W){const ue=W??"all";w(ue),v(ue==="all"?"all":ue==="manual"||ue==="clash"?ue:"subscription")}function L(W){v(W),w("all")}const F=T.filter(H),$=F.map(W=>W.id),X=$.length>0&&$.every(W=>e.selected.has(W)),K=$.some(W=>e.selected.has(W))&&!X,q=SD(),Q=[];for(const W of ND())Q.push(...F.filter(ue=>sl(ue)===W.key));const G=gg(F.length,"proxies"),J=G.paged?G.slice(Q):Q,Y=new Map;for(const W of F)Y.set(sl(W),(Y.get(sl(W))??0)+1);x.useEffect(()=>{G.goto(1)},[O,y,j,k]);function re(W){const ue=W.lastTest;if(!ue||!ue.at)return s.jsx("span",{className:"text-subtle",children:r("未测试")});const ve=Uj(ue.durationMs);return s.jsxs("div",{className:"flex flex-col gap-0.5 leading-[1.5] min-w-0",children:[s.jsxs("span",{className:ue.success?"text-success":"text-destructive",children:[ue.success?r("✅ {ip}",{ip:ue.ip||r("连接成功")}):r("❌ 连接失败"),ve?` ${ve}`:"",s.jsxs("span",{className:"text-[11px] text-subtle",children:[" ",rO(ue.at)]})]}),ue.success?null:s.jsx("span",{className:"overflow-hidden text-ellipsis whitespace-nowrap text-[11px] text-subtle",title:String(ue.error||r("连接失败")),children:String(ue.error||r("连接失败"))})]})}function M(W){const ue=W.usedBy||[],ve=[];return W.protocol&&ve.push(W.protocol),ue.length&&ve.push(s.jsx("span",{className:"text-warn",title:ue.map(ee=>String(ee.name||ee.id||"")).join(r("、")),children:r("{n} 个账号在用",{n:ue.length})})),ve.length?s.jsx("span",{className:"text-[11px] text-subtle",children:ve.map((ee,he)=>s.jsxs(x.Fragment,{children:[he?" · ":"",ee]},he))}):null}function U(W){if(bq(W)&&(W.port===null||W.port===void 0))return s.jsx("span",{className:"text-subtle",children:r("已禁用(未开监听端口)")});if(W.resolveError){const ve=W.source==="subscription"&&(W.port===null||W.port===void 0);return s.jsx("span",{className:ve?"text-subtle":"text-destructive",title:W.resolveError,children:r(ve?"未分配端口":"解析失败")})}if(gq(W)){const ve=Nu()?.installed===!1;return s.jsx("span",{className:"text-subtle",title:r(ve?"代理内核未安装(在「订阅管理」里下载内核后,节点会自动分配监听端口)":"还没有监听端口(还没有账号引用它 —— 在账号里选它并保存后,内核会自动开端口)"),children:Xh(W)||r("未分配端口")})}const ue=Xh(W);return s.jsxs("div",{className:"flex min-w-0 items-center gap-1",children:[s.jsx("span",{className:"min-w-0 flex-1 font-mono text-[12px] leading-[1.45] text-text-2 break-all",title:ue||void 0,children:ue||"—"}),ue?s.jsx(ne,{variant:"ghost",size:"icon-xs",className:"copy-btn flex-none","data-copy":ue,title:r("复制地址"),children:"⧉"}):null]})}function Z(W,ue,ve,ee){const he=ve||e.batchBusy;switch(W){case"pick":return s.jsx(_r,{checked:ee,title:r("勾选后可批量操作"),"aria-label":r("勾选「{name}」",{name:ue.name||r("未命名")}),onCheckedChange:te=>Tq(ue.id,te)});case"name":return s.jsxs("div",{className:"flex flex-col gap-0.5 leading-[1.5] min-w-0",children:[s.jsx("b",{children:ue.name||r("未命名")}),M(ue)]});case"addr":return U(ue);case"state":{const te=lO(ue);return s.jsx(Zn,{checked:ue.enabled!==!1,disabled:he||te,"aria-label":r("启用「{name}」",{name:ue.name||r("未命名")}),title:kq(ue),onCheckedChange:ke=>{Mq(ue,ke)}})}case"test":return re(ue);case"act":{const te=vg(ue);bg(ue);const ke=cO(ue),le=e.testing===ue.id;return s.jsxs("div",{className:"row-actions",children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:he||e.testing!==null,onClick:()=>{Oq(ue)},children:r(le?"测试中…":"测试")}),ue.source!=="clash"&&ue.source!=="subscription"?s.jsxs(s.Fragment,{children:[s.jsx(ne,{size:"sm",variant:"ghost",disabled:he,onClick:()=>o({item:ue}),children:r("编辑")}),s.jsx(ne,{size:"sm",variant:"destructive",disabled:he,onClick:()=>{fO(ue)},children:r("删除")})]}):null,te?s.jsx(ne,{size:"sm",variant:"destructive",disabled:he,title:ke,onClick:()=>{fO(ue)},children:r("删除")}):null]})}default:return null}}function ae(W){const ue=e.pending.has(W.id),ve=Cq(W.id);return s.jsx("tr",{className:Ue(W.enabled?"":"off",ve&&"bg-primary-soft"),"data-id":W.id,children:q.map(ee=>s.jsx("td",{className:`ta-${ee.align}`,children:Z(ee.key,W,ue,ve)},ee.key))},W.id)}function ce(){if(!T.length)return s.jsx("tr",{children:s.jsx("td",{colSpan:q.length,className:"empty",children:r(C?"还没有代理。点右上角「+ 新增代理」手填一个,或在「订阅管理」里导入订阅节点、同步 Clash Verge 的出口。":"加载中…")})});if(!F.length)return s.jsx("tr",{children:s.jsx("td",{colSpan:q.length,className:"empty",children:O?r("没有匹配「{kw}」的出口",{kw:h.trim()}):r("没有匹配当前筛选的出口")})});const W=[];let ue="";for(const ve of J){const ee=sl(ve);if(ee!==ue){ue=ee;const he=ND().find(te=>te.key===ee);W.push(s.jsx("tr",{className:"tr-group",children:s.jsxs("td",{colSpan:q.length,children:[s.jsx("span",{className:"prov-tag",children:he?.label??ee}),r("{n} 个",{n:Y.get(ee)??0}),he?.note?s.jsxs("span",{className:"font-normal",children:[" · ",he.note]}):null]})},`group:${ee}:${W.length}`))}W.push(ae(ve))}return s.jsx(s.Fragment,{children:W})}return s.jsx(s.Fragment,{children:s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("代理池")}),s.jsx("span",{className:"panel-sub",children:C?r("{n} 个出口",{n:T.length}):r("加载中…")}),s.jsx("span",{className:"text-[11px] text-subtle",children:r("订阅与 Clash 的出口自动镜像进来")}),s.jsxs("div",{className:"head-actions",children:[s.jsx(ne,{variant:"outline",disabled:e.batchBusy,onClick:()=>d(!0),children:r("设置")}),s.jsx(ne,{variant:"outline",disabled:e.batchBusy,onClick:()=>p(!0),children:t.length?r("订阅管理({n})",{n:t.length}):r("订阅管理")}),s.jsx(ne,{variant:"outline",disabled:e.loading||e.batchBusy,onClick:()=>{Lf(),Ml()},children:e.loading?r("刷新中…"):r("刷新")}),s.jsx(ne,{variant:"default",disabled:e.batchBusy,onClick:()=>o({item:null}),children:r("+ 新增代理")})]})]}),s.jsx("div",{className:"px-3 pt-3",children:s.jsx(bD,{showPortRange:!0})}),E>0?s.jsxs("div",{className:"batch-bar active",children:[s.jsxs("span",{className:"batch-count",children:[r("已选")," ",s.jsx("b",{children:E})," ",r("个 · 共")," ",s.jsx("b",{children:F.length})," ",r("个")]}),D?s.jsx("span",{className:"batch-hidden",children:r("其中 {n} 条是同步来的只读条目(Clash / 订阅):可参与批量测试,删除会跳过",{n:D})}):null,s.jsxs("div",{className:"batch-actions",children:[s.jsx(ne,{variant:"outline",disabled:e.batchBusy,onClick:()=>{Iq()},children:I?r("测试中 {done}/{total}",{done:I.done,total:I.total}):r("批量测试")}),s.jsx(ne,{variant:"destructive",disabled:e.batchBusy,onClick:()=>{Pq()},children:r("批量删除")}),s.jsx(ne,{variant:"outline",disabled:e.batchBusy,onClick:()=>Aq(),children:r("取消选择")})]})]}):s.jsxs("div",{className:"flex flex-wrap items-center gap-2.5 border-b border-border px-4 py-[10px]",children:[s.jsxs(Di,{className:"w-[clamp(150px,22vw,220px)]",children:[s.jsx(Pi,{type:"search",value:h,"aria-label":r("搜索节点"),placeholder:r("搜索名称 / 地址 / 端口"),onChange:W=>b(W.currentTarget.value)}),s.jsx(Ii,{align:"inline-start","aria-hidden":"true",children:s.jsx(GX,{})})]}),s.jsxs(dt,{value:j,onValueChange:B,children:[s.jsx(pt,{className:"w-[clamp(150px,18vw,210px)]","aria-label":r("按提供方筛选"),children:s.jsx(ft,{children:_.find(W=>W.value===j)?.label??r("全部提供方")})}),s.jsx(mt,{children:_.map(W=>s.jsx($e,{value:W.value,children:s.jsxs("span",{className:"flex w-full items-center gap-2",children:[s.jsx("span",{className:"min-w-0 flex-1 truncate"+(W.count?"":" text-subtle"),children:W.label}),s.jsx("span",{className:"flex-none text-[11px] text-subtle",children:W.count})]})},W.value))})]}),s.jsx(En,{options:FX(T),value:y,onValueChange:L,"aria-label":r("按来源筛选")}),s.jsx(En,{options:$X(T),value:k,onValueChange:S,"aria-label":r("按状态筛选")}),s.jsx("span",{className:"ml-auto text-[11px] text-subtle",children:r("显示 {n} / 共 {total} 个出口",{n:F.length,total:T.length})})]}),s.jsx("div",{className:"models-table-wrap",children:s.jsxs("table",{className:"models-table proxies-table",children:[s.jsx("colgroup",{children:q.map(W=>s.jsx("col",{"data-col":W.key,className:zX[W.key]||void 0},W.key))}),s.jsx("thead",{children:s.jsx("tr",{children:q.map(W=>s.jsx("th",{"data-col":W.key,className:`ta-${W.align}`,children:W.key==="pick"?s.jsx(_r,{checked:X,indeterminate:K,disabled:!$.length,title:r("全选当前筛选出的出口"),"aria-label":r("全选当前筛选出的出口"),onCheckedChange:ue=>Eq($,ue)}):W.label},W.key))})}),s.jsx("tbody",{children:ce()})]})}),s.jsx($i,{leading:s.jsxs(s.Fragment,{children:[e.data?.clash&&e.data.clash.available===!1?s.jsx("span",{className:"text-subtle",children:e.data.clash.error?r("未检测到 Clash Verge:{reason}",{reason:e.data.clash.error}):r("未检测到 Clash Verge")}):null,e.error?s.jsx("span",{className:"text-destructive",children:r("读取失败:{reason}",{reason:e.error})}):null]}),total:F.length,page:G.page,pageCount:G.pageCount,size:G.size,onSizeChange:G.setSize,onPageChange:G.goto,range:G.paged?{start:G.rangeStart,end:G.rangeEnd}:null}),a?s.jsx(RX,{item:a.item,onClose:()=>o(null)}):null,c?s.jsx(OX,{onClose:()=>d(!1)}):null,f?s.jsx(IX,{onClose:()=>p(!1)}):null]})})}function sl(e){return e.source==="clash"?"clash":e.source==="subscription"?"subscription":"manual"}function ND(){return[{key:"manual",label:r("手动"),note:r("本页可编辑、可删除")},{key:"clash",label:"Clash Verge",note:r("名字与端口在 Clash Verge 里改;启用可在本页关闭")},{key:"subscription",label:r("订阅"),note:r("名字与端口跟随订阅与内核;启用可在本页关闭")}]}function FX(e){const t=a=>e.filter(o=>sl(o)===a).length;return[{value:"all",label:r("全部"),count:e.length},{value:"manual",label:r("手动"),count:t("manual")},{value:"clash",label:"Clash",count:t("clash")},{value:"subscription",label:r("订阅"),count:t("subscription")}]}function kD(e){return e.enabled===!1?"off":e.port===null||e.port===void 0?"wait":e.lastTest?.at?e.lastTest.success?"ok":"fail":"none"}function $X(e){const t=a=>e.filter(o=>kD(o)===a).length;return[{value:"all",label:r("全部状态"),count:e.length},{value:"ok",label:r("可用"),count:t("ok")},{value:"fail",label:r("失败"),count:t("fail")},{value:"wait",label:r("未就绪"),count:t("wait")},{value:"off",label:r("已禁用"),count:t("off")}]}const CD="__orphan";function qX(e,t){const a=e.filter(d=>sl(d)==="subscription"),o=t.map(d=>({value:d.id,label:d.name||d.id,count:a.filter(f=>!f.orphan&&f.providerId===d.id).length})).sort((d,f)=>f.count-d.count||d.label.localeCompare(f.label)),c=a.filter(d=>d.orphan).length;return[{value:"all",label:r("全部提供方"),count:e.length},{value:"manual",label:r("手动"),count:e.filter(d=>sl(d)==="manual").length},{value:"clash",label:"Clash Verge",count:e.filter(d=>sl(d)==="clash").length},{value:"subscription",label:r("全部订阅"),count:a.length},...o,...c?[{value:CD,label:r("已移除的订阅"),count:c}]:[]]}function GX(){return s.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[s.jsx("circle",{cx:"11",cy:"11",r:"8"}),s.jsx("path",{d:"m21 21-4.3-4.3"})]})}window.wbProxiesPanel={load:async()=>{await Lf(),await Ml()},visibleColumns:()=>SD().map(e=>({key:e.key}))};const TD='.page[data-page="proxies"]';function ED(){const e=document.querySelector(TD);!e||e.dataset.mounted==="1"||(e.dataset.mounted="1",e.replaceChildren(),jn.createRoot(e).render(s.jsx(VX,{})),tr().wbApp?.currentPage==="proxies"&&(Lf(),Ml()))}document.querySelector(TD)?ED():document.addEventListener("DOMContentLoaded",ED,{once:!0});const ix=["today","7","30","month","all","custom"],N0="7",k0="custom",AD="workbuddy-desktop-report-range",RD="workbuddy-desktop-report-custom-range",OD={today:r("今天"),7:r("近 7 天"),30:r("近 30 天"),month:r("本月"),all:r("全部"),custom:r("自定义区间")},KX={today:r("今天"),7:r("7 天"),30:r("30 天"),month:r("本月"),all:r("全部"),custom:r("自定义")};function YX(){try{const e=localStorage.getItem(AD);return e!==null&&ix.includes(e)?e:N0}catch{return N0}}function C0(e){const t=a=>String(a).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function XX(){const e=new Date;return{start:C0(new Date(e.getFullYear(),e.getMonth(),e.getDate()-6)),end:C0(e)}}const cx=/^\d{4}-\d{2}-\d{2}$/;function QX(){try{const e=localStorage.getItem(RD);if(e){const t=JSON.parse(e),a=typeof t?.start=="string"?t.start:"",o=typeof t?.end=="string"?t.end:"";if(cx.test(a)&&cx.test(o)&&a<=o)return{start:a,end:o}}}catch{}return XX()}function ZX(e){try{localStorage.setItem(RD,JSON.stringify(e))}catch{}}const WX=[[0,r("一")],[2,r("三")],[4,r("五")]],MD=400;function rc(e){const t=T0();return t.formatInt?t.formatInt(e):(Number(e)||0).toLocaleString("zh-CN")}function T0(){return window.wbUnits||{}}function os(e){const t=T0();return t.formatTokens?t.formatTokens(e):String(Number(e)||0)}function DD(e,t){const a=T0();return a.formatAxis?a.formatAxis(e,t):String(e)}function ac(e){return`${((Number(e)||0)*100).toFixed(1)}%`}function zt(e){return Math.round(e*10)/10}function ux(e){return[...e].reduce((t,a)=>t+(/[\u2e80-\u9fff]/.test(a)?9.7:5.4),0)}function dx(e){const[t,a,o]=String(e||"").split("-").map(Number);return new Date(t||1970,(a||1)-1,o||1)}const JX=[r("日"),r("一"),r("二"),r("三"),r("四"),r("五"),r("六")];function fx(e){const t=dx(e);return r("{m}月{d}日 周{wd}",{m:t.getMonth()+1,d:t.getDate(),wd:JX[t.getDay()]})}function ID(e){const t=String(e||"").slice(11,13);return t?`${t}:00`:"—"}const eQ=8;function PD(e,t){const a=(Array.isArray(e)?e:[]).map(d=>({name:String(d?.label??d?.model??"").trim()||r("未知模型"),tokens:Number(d?.tokens)||0})).filter(d=>d.tokens>0);if(!a.length)return[];const o=a.slice(0,eQ),c=o.map(d=>`${t?`[${t(d.name)}]`:""}${r("{model}:{tokens} tokens",{model:d.name,tokens:os(d.tokens)})}`);return a.length>o.length&&c.push(r("…还有 {n} 个模型",{n:a.length-o.length})),c}function _D(e,t){return[fx(e.date),r("总 Token:{tokens}({n} 次请求)",{tokens:os(e.tokens),n:rc(e.requests)}),...PD(e.models,t)].join(` +`)}function tQ(e,t){return[`${fx(String(e.hour).slice(0,10))} ${ID(e.hour)}`,r("命中率 {rate}(命中 {hit} / 输入 {input})",{rate:ac(e.rate),hit:os(e.hitTokens),input:os(e.inputTokens)}),r("总 Token:{tokens}",{tokens:os(e.totalTokens)}),...PD(e.models,t)].join(` +`)}const nQ=[1,1.5,2,2.5,3,4,5,6,8,10];function sQ(e){if(!(e>0))return 1;const t=10**Math.floor(Math.log10(e)),a=e/t;return(nQ.find(c=>c>=a-1e-9)??10)*t}function E0(e){return sQ(e/4)*4}function rQ(e,t,a){const o=e||{},c=o.topModel,d=Number(o.requests)||0,f=Number(o.successful)||0,p=d?`${(f/d*100).toFixed(1)}%`:"—",h=[{key:"requests",label:r("总请求数"),value:rc(d),sub:OD[t]||"",mono:!1},{key:"successful",label:r("成功请求数"),value:rc(f),sub:r("成功率 {rate}",{rate:p}),mono:!1},{key:"tokens",label:r("总 Token"),value:os(o.tokens),sub:r("输入 + 输出"),mono:!1},{key:"activeDays",label:r("活跃天数"),value:rc(o.activeDays),sub:r("区间共 {n} 天",{n:a}),mono:!1},{key:"streak",label:r("当前连续天数"),value:rc(o.streak),sub:r("含今天在内往前数"),mono:!1}];return h.push(c?{key:"topModel",label:r("Top 模型"),value:String(c.model??""),sub:r("{tokens} tokens · 占 {pct}",{tokens:os(c.tokens),pct:ac(c.percentage)}),mono:!0}:{key:"topModel",label:r("Top 模型"),value:"—",sub:r("所选范围内还没有模型用量"),mono:!1}),h}function LD(e){if(!Array.isArray(e))return null;const t=e.map(c=>({id:String(c?.id??"").trim(),label:String(c?.label??"").trim(),tokens:Number(c?.totalTokens??c?.tokens)||0})).filter(c=>c.tokens>0);if(!t.length)return[];const a=t.reduce((c,d)=>c+d.tokens,0),o=c=>a?c/a*100:0;return[...t].sort((c,d)=>d.tokens-c.tokens).map((c,d)=>{const f=o(c.tokens),p=os(c.tokens),h=c.label||c.id||r("未知"),b=c.id?r("{name}({id})",{name:h,id:c.id}):h;return{key:`${d}-${c.id||h}`,id:c.id,name:h,full:b,tip:r("{name}:{tokens} tokens · 占 {pct}%",{name:b,tokens:p,pct:f.toFixed(1)}),tokensText:p,percentText:`${f.toFixed(1)}%`,barWidth:`${f.toFixed(1)}%`}})}function zD(e){return`${os(e.reduce((t,a)=>t+(Number(a?.totalTokens??a?.tokens)||0),0))} tokens`}const px=["#f73b00","#f7bb07","#4aaa4d","#1872cb","#3444a3","#13c2c2","#722ed1","#eb2f96","#a0d911","#34d399","#d946ef","#ff85c0","#b37feb","#9d174d","#ffa39e","#69b1ff"],aQ={size:220,inner:.62,outer:.88,padAngle:2};function lQ(e,t,a,o,c,d){const f=P=>(P-90)*Math.PI/180,p=(P,T)=>[zt(e+P*Math.cos(f(T))),zt(t+P*Math.sin(f(T)))],h=d-c;if(h>=359.999){const[P,T]=p(a,0),[C,E]=p(a,180),[D,I]=p(o,0),[O,_]=p(o,180);return`M ${P} ${T} A ${a} ${a} 0 1 1 ${C} ${E} A ${a} ${a} 0 1 1 ${P} ${T} Z M ${D} ${I} A ${o} ${o} 0 1 0 ${O} ${_} A ${o} ${o} 0 1 0 ${D} ${I} Z`}const[b,y]=p(a,c),[v,j]=p(a,d),[w,k]=p(o,d),[S,N]=p(o,c),R=h>180?1:0;return`M ${b} ${y} A ${a} ${a} 0 ${R} 1 ${v} ${j} L ${w} ${k} A ${o} ${o} 0 ${R} 0 ${S} ${N} Z`}const oQ="#9aa0a6";function BD(e){const t=new Map;for(const a of Array.isArray(e)?e:[]){const o=String(a?.label??a?.model??a?.id??"").trim();!o||t.has(o)||(Number(a?.totalTokens??a?.tokens)||0)>0&&t.set(o,px[t.size%px.length])}return t}function HD(e,t){const a=(Array.isArray(e)?e:[]).map(N=>({label:String(N?.label??N?.model??N?.id??"").trim()||t,tokens:Number(N?.totalTokens??N?.tokens)||0,requests:Number(N?.requests)||0})).filter(N=>N.tokens>0);if(!a.length)return null;const o=a.reduce((N,R)=>N+R.tokens,0);if(!o)return null;const c=BD(e),{size:d,inner:f,outer:p,padAngle:h}=aQ,b=d/2,y=d/2,v=d/2*p,j=d/2*f;let w=0;const k=[],S=[];return a.forEach((N,R)=>{const P=N.tokens/o,T=P*360,C=a.length>1?Math.min(h/2,T/4):0,E=w+C,D=w+T-C;w+=T;const I=c.get(N.label)??px[R%px.length];let O=null;if(P>=.03){const _=(E+D)/2,z=j+(v-j)*.6,H=(_-90)*Math.PI/180;O={x:zt(b+z*Math.cos(H)),y:zt(y+z*Math.sin(H)),text:`${Math.round(P*100)}%`}}D>E&&k.push({key:`${R}-${N.label}`,d:lQ(b,y,v,j,E,D),fill:I,evenOdd:T>=359.999,label:O,tip:`${N.label} · ${os(N.tokens)} tokens · ${ac(P)}`}),S.push({key:`${R}-${N.label}`,fill:I,name:N.label,tokensText:os(N.tokens),percentText:ac(P),tip:r("{name} · {tokens} tokens · {n} 次请求 · {pct}",{name:N.label,tokens:os(N.tokens),n:rc(N.requests),pct:ac(P)})})}),{size:d,slices:k,legend:S,totalText:os(o)}}const iQ=[1,1.25,1.5,2,2.5,3,4,5,6,8,10];function cQ(e){if(!(e>0))return 1;const t=10**Math.floor(Math.log10(e)),a=e/t;let o=1;for(const c of iQ)c<=a+1e-9&&(o=c);return o*t}function uQ(e){const t=Number(e)||0;if(t<=0)return[0,1,2,3,1/0];const a=Math.max(1,cQ(t/4));return[0,a,a*2,a*3,1/0]}function dQ(e,t){if(e===0)return"0";const a=t[e-1],o=t[e];return Number.isFinite(o)?a===0?`≤${os(o)}`:`${os(a)}–${os(o)}`:`>${os(a)}`}function UD(e){const t=Array.isArray(e)?e:[];return uQ(t.reduce((a,o)=>Math.max(a,Number(o?.tokens)||0),0))}function fQ(e,t){const a=Array.isArray(e)?e:[];if(!a.length)return null;const o=(dx(a[0].date).getDay()+6)%7,c=new Array(o).fill(null).concat(a),d=Math.ceil(c.length/7),f=3,p=20,h=t-p,b=Math.floor((h-f*(d-1))/d),y=Math.max(7,Math.min(26,b)),v=y+3,j=y+f,w=p+d*j-f,k=Math.max(0,Math.round((t-w)/2)),S=v+7*j-f+2,N=Math.max(w,Math.round(t)),R=UD(a),P=O=>R.findIndex(_=>Number(O)<=_),T=[];for(let O=0;O({key:_,x:k+p-6,y:zt(v+O*j+y/2),text:_})),E=[];let D=-1,I=-9;for(let O=0;O({level:t,text:dQ(t,e)}))}function mQ(e){const t=e||{};return[["last10m",r("近 10 分钟")],["last1h",r("近 1 小时")],["last24h",r("近 24 小时")],["last7d",r("近 7 天")]].map(([o,c])=>{const d=t[o]||{},f=Number(d.inputTokens)||0;return{key:o,label:c,value:f?ac(d.rate):"—",sub:r("命中 {hit} / 输入 {input}",{hit:os(d.hitTokens),input:os(f)})}})}function hQ(e,t,a){const o=Array.isArray(e)?e:[];if(!o.length)return null;const c=230,d={left:44,right:56,top:26,bottom:24},f=Math.max(40,t-d.left-d.right),p=c-d.top-d.bottom,h=o.map(K=>Number(K.rate)||0),b=o.map(K=>Number(K.totalTokens)||0),y=Math.max(1,E0(Math.max(...h))),v=Math.max(...b),j=E0(v),w=v>0,k=K=>d.left+(o.length>1?f*K/(o.length-1):f/2),S=K=>d.top+p-p*K/y,N=K=>d.top+p-p*K/j,R=[],P=[],T=[];for(let K=0;K<=4;K+=1){const q=y*K/4,Q=zt(S(q)),G=q*100;R.push({key:`g${K}`,y:Q}),P.push({key:`r${K}`,x:d.left-8,y:Q,anchor:"end",text:`${Number.isInteger(G)?G:G.toFixed(1)}%`}),w&&T.push({key:`t${K}`,x:zt(d.left+f+8),y:Q,anchor:"start",text:DD(j*K/4,j)})}const C=o.length===1?4.5:2.5,E=(K,q)=>({points:K.map((Q,G)=>`${zt(k(G))},${zt(q(Q))}`).join(" "),dots:K.map((Q,G)=>({key:`d${G}`,cx:zt(k(G)),cy:zt(q(Q))}))}),D=[],I=(K,q,Q,G)=>{const J=ux(Q),Y=G==="middle"?K-J/2:G==="end"?K-J:K,re={left:Y,right:Y+J,top:q-8.5,bottom:q+2.5};return D.some(M=>re.leftM.left-2&&re.topM.top-1)?null:(D.push(re),{key:`${Q}-${K}-${q}`,x:zt(K),y:zt(q),text:Q,anchor:G})},O=(K,q)=>{const Q=ux(q)/2;return K-Qd.left+f+6?"end":"middle"},_=[];w&&o.forEach((K,q)=>{if(!(Number(K.totalTokens)>0))return;const Q=N(b[q]),G=Q-12>=d.top-10,J=os(b[q]),Y=I(k(q),G?Q-12:Q+13,J,O(k(q),J));Y&&_.push({...Y,key:`tl${q}`})});const z=[];o.forEach((K,q)=>{if(!((Number(K.inputTokens)||0)+(Number(K.hitTokens)||0)>0))return;const G=S(h[q]),J=G+15<=d.top+p+8,Y=ac(h[q]),re=I(k(q),J?G+13:G-7,Y,O(k(q),Y));re&&z.push({...re,key:`rl${q}`})});const H=o.length>1?f/(o.length-1):f,B=d.left,L=d.left+f,F=o.length<=MD?o.map((K,q)=>{const Q=Math.max(B,k(q)-H/2),G=Math.min(L,k(q)+H/2);return{key:`h${q}`,x:zt(Q),width:zt(G-Q),tip:tQ(K,a)}}):null,$=Math.max(1,Math.ceil(o.length/8)),X=[];for(let K=0;K=o.length;X.push({key:`x${K}`,x:zt(k(K)),y:c-8,anchor:K===0?"start":q?"end":"middle",text:ID(o[K].hour)})}return{width:t,height:c,plotLeft:B,plotW:f,plotH:p,plotTop:d.top,grid:R,rateTicks:P,tokenTicks:T,rateLine:E(h,S),tokenLine:w?E(b,N):null,dotR:C,rateLabels:z,tokenLabels:_,hourTicks:X,hits:F}}const gQ=13;function xQ(e,t,a){const o=Array.isArray(e)?e:[];if(!o.length)return null;const c=240,d={left:50,right:14,top:26,bottom:26},f=Math.max(40,t-d.left-d.right),p=f/o.length,h=o.map($=>Number($.tokens)>0?os($.tokens):""),b=Math.max(0,...h.map(ux)),y=h.every($=>!$)||b+4<=p,v=!y&&p>=gQ;v&&(d.top=10+Math.ceil(b*1.25));const j=c-d.top-d.bottom,w=o.map($=>Number($.tokens)||0),k=Math.max(...w),S=E0(k),N=Math.max(1,Math.min(28,p*.68)),R=d.top+j,P=$=>d.top+j-j*$/S,T=o.length<=MD,C=k<=0,E=[],D=[];if(!C)for(let $=0;$<=4;$+=1){const X=S*$/4,K=zt(P(X));E.push({key:`g${$}`,x1:d.left,y:K,x2:zt(d.left+f)}),D.push({key:`v${$}`,x:d.left-8,y:K,anchor:"end",text:DD(X,S)})}const I=[];o.forEach(($,X)=>{const K=Number($.tokens)||0;if(K<=0)return;const q=P(K);I.push({key:String($.date??X),x:zt(d.left+p*X+(p-N)/2),y:zt(q),width:zt(N),height:zt(Math.max(1,R-q)),rx:N>4?2:1,tip:_D($),nativeTip:!T})});const O=[],_=[],z=($,X)=>{const K=h[$],q=P(Number(o[$].tokens)||0),Q=zt(d.left+p*$+p/2);if(v)return{key:`b${$}`,x:Q,y:zt(q-6),anchor:"start",text:K,rotate:!0};const G=q-6,J=G-9M.leftU.left-2&&M.topU.top-1))return null;_.push(M)}return{key:`b${$}`,x:Q,y:Y,anchor:"middle",text:K}};if(y||v)h.forEach(($,X)=>{if(!$)return;const K=z(X,!1);K&&O.push(K)});else{const $=o.map((X,K)=>({index:K,value:Number(X.tokens)||0})).filter(X=>X.value>0).sort((X,K)=>K.value-X.value);for(const X of $){if(O.length>=8)break;const K=z(X.index,!0);K&&O.push(K)}}const H=T?o.map(($,X)=>({key:`h${X}`,x:zt(d.left+p*X),width:zt(p),tip:_D($,a)})):null,B=Math.max(1,Math.ceil(o.length/6)),L=[];for(let $=0;${const X=o.length===1,K=!X&&$===o.length-1,q=dx(o[$].date);return{key:`d${$}`,x:X?d.left+f/2:K?d.left+f:zt(d.left+p*$+p/2),y:c-8,anchor:X?"middle":K?"end":$===0?"start":"middle",text:`${q.getMonth()+1}/${q.getDate()}`}});return{width:t,height:c,plotLeft:d.left,plotW:f,plotH:j,plotTop:d.top,grid:E,valueTicks:D,bars:I,barLabels:O,dateTicks:F,hits:H,blank:C}}function lc(){return window}const VD=1e3,bQ=ix.map(e=>({value:e,label:KX[e]})),vQ=r("所选范围内每个账号各消耗了多少 Token,按 Token 用量从多到少排。账号是比提供商更细的一维:同一家可以挂多个账号,转发时按优先级在候选链上依次尝试,所以这里反映的是「具体哪个登录态在出力」。百分比按本区间的总 Token 数算(这一块只看用量,请求次数与成功率在概览卡片里)。「未知账号」是指那批请求没有账号身份:走默认登录态转发(未配置账号列表)时会这样;这一维上线前写出的旧聚合行也没有账号明细,但它们会在升级导入旧数据时按明细自动补算回来 —— 只有明细已被手动清理掉的那几天补不回来,仍留在「未知账号」里,那是确实无从恢复的部分。"),yQ=r("所选范围内每个提供商各消耗了多少 Token,按 Token 用量从多到少排。同一个模型名可能有多家都能提供,网关按设置页「转发路由」的优先级依次尝试,所以占比也反映了实际落到谁身上。百分比按本区间的总 Token 数算(这一块只看用量,请求次数与成功率在概览卡片里)。「未知」是指那批请求没记下承载它的提供商 —— 主要是记录提供商这个功能上线之前的旧明细,其次是请求在选定上游之前就失败了(请求体非法、模型不存在、没有可用账号)。这一维与账号那一维不同:旧明细里根本没有「哪家承载」的信息(早期版本只有单一上游,但那是配置事实而非逐条记录),所以无法回算,旧数据会一直留在「未知」里;此后新产生的请求都会记上具体的提供商。"),jQ=r("所选范围内每个模型各消耗了多少 Token,按用量从多到少排,扇区角度即占比。中心是这一维的合计(等于概览里的总 Token),右侧每行给出该模型的 Token 用量与百分比。扇区内的百分比只在 ≥3% 时标出,更小的会挤成一团 —— 完整读数在右侧列表与悬停气泡里。颜色按用量排名分配:最大的那段是红色,依次往后;同一份报表里换个维度看,配色口径不变。"),wQ=r("所选范围内每个提供商各消耗了多少 Token,按用量从多到少排,扇区角度即占比。同一个模型名可能有多家都能提供,网关按设置页「转发路由」的优先级依次尝试,所以占比也反映了实际落到谁身上。中心是这一维的合计(等于概览里的总 Token),右侧每行给出该提供商的 Token 用量与百分比。「未知」是指那批请求没记下承载它的提供商 —— 主要是记录提供商这个功能上线之前的旧明细,其次是请求在选定上游之前就失败了。"),SQ=r("命中率 = 缓存读取 Token / 输入 Token(promptTokens)。窗口越短越贴近「此刻」:上游把缓存读取与输入分开上报时,该比值合法地可能超过 100%,此处不夹取值、如实展示。"),NQ=r("每天的总 Token 用量(输入 + 输出)。柱顶标出当天的读数;区间很长、柱子挤到放不下时只标最高的那几天,其余悬停柱子即可读到。");let mx=VD,hx=!0,A0=!1,R0=!1,O0=0,Uo=null,oc=null,gx=null;function ic(e,t="empty"){return s.jsx("div",{className:t,style:{padding:"14px 0"},children:e})}function xx({text:e}){return s.jsx("span",{className:"tip-q","data-tip":e})}function kQ({accountId:e}){const t=(lc().wbApp?.getState?.()?.accounts?.accounts||[]).find(f=>f?.id===e),a=typeof t?.provider=="string"?t.provider:"";if(!a)return null;const o=lc().wbProviders?.labelOf?.(a)||a,c=t&&lc().wbAccountsModel?.editionSuffix?.(t)||"",d=c?`${o} ${c}`:o;return s.jsx("span",{className:`pbadge p-${a}`,title:r("提供商:{text}",{text:d}),children:d})}function CQ({summary:e,range:t}){const a=Array.isArray(e.dailyTrend)?e.dailyTrend:[];return s.jsx(s.Fragment,{children:rQ(e.overview,t,a.length).map(o=>s.jsxs("div",{className:"field",children:[s.jsx("div",{className:"label",children:o.label}),s.jsxs("div",{className:o.mono?"value mono":"value",children:[o.value,o.sub?s.jsx("div",{className:"sub",children:o.sub}):null]})]},o.key))})}function FD({panelId:e,listId:t,labelId:a,title:o,tip:c,rows:d,totalText:f,withBadge:p,emptyText:h}){return s.jsxs("section",{className:"panel",id:e,children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:o}),s.jsx(xx,{text:c}),s.jsx("span",{className:"panel-sub",id:a,children:f})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"rank-shares",id:t,children:d.length?d.map(b=>s.jsxs("div",{className:"rank-row","data-tip":b.tip,children:[s.jsxs("span",{className:"name",title:b.full,children:[p?s.jsx(kQ,{accountId:b.id}):null,b.name]}),s.jsx("span",{className:"track",children:s.jsx("span",{className:"bar",style:{width:b.barWidth}})}),s.jsx("span",{className:"num",title:`${b.tokensText} tokens`,children:b.tokensText}),s.jsx("span",{className:"pct",children:b.percentText})]},b.key)):ic(h)})})]})}function $D({panelId:e,listId:t,title:a,tip:o,ariaLabel:c,view:d,emptyText:f}){return s.jsxs("section",{className:"panel",id:e,children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:a}),s.jsx(xx,{text:o})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{id:t,children:d?s.jsxs("div",{className:"donut-layout",children:[s.jsxs("div",{className:"donut-wrap",children:[s.jsx("svg",{className:"donut-svg",width:d.size,height:d.size,viewBox:`0 0 ${d.size} ${d.size}`,role:"img","aria-label":c,children:d.slices.map(p=>s.jsxs(x.Fragment,{children:[s.jsx("path",{className:"donut-slice",d:p.d,fill:p.fill,fillRule:p.evenOdd?"evenodd":void 0,tabIndex:-1,"data-tip":p.tip}),p.label?s.jsx("text",{className:"donut-label",x:p.label.x,y:p.label.y,textAnchor:"middle",dominantBaseline:"central",children:p.label.text}):null]},p.key))}),s.jsxs("div",{className:"donut-center",children:[s.jsx("div",{className:"donut-center-value",children:d.totalText}),s.jsx("div",{className:"donut-center-label",children:r("总 Token")})]})]}),s.jsx("div",{className:"donut-legend",children:d.legend.map(p=>s.jsxs("div",{className:"donut-legend-row","data-tip":p.tip,children:[s.jsx("span",{className:"donut-dot",style:{background:p.fill}}),s.jsx("span",{className:"donut-legend-name",title:p.name,children:p.name}),s.jsx("span",{className:"donut-legend-tokens",children:p.tokensText}),s.jsx("span",{className:"donut-legend-percent",children:p.percentText})]},p.key))})]}):ic(f)})})]})}function TQ({view:e}){return s.jsxs("svg",{className:"report-svg",width:e.width,height:e.height,viewBox:`0 0 ${e.width} ${e.height}`,role:"img","aria-label":r("近 365 天活跃热力图"),children:[e.months.map(t=>s.jsx("text",{className:"hm-axis",x:t.x,y:10,children:t.text},t.key)),e.weekdays.map(t=>s.jsx("text",{className:"hm-axis",x:t.x,y:t.y,textAnchor:"end",dominantBaseline:"middle",children:t.text},t.key)),e.cells.map(t=>s.jsx("rect",{className:`hm-cell l${t.level}`,x:t.x,y:t.y,width:t.size,height:t.size,rx:2,tabIndex:-1,"data-tip":t.tip},t.key))]})}function qD({line:e,cls:t,radius:a}){return s.jsxs(s.Fragment,{children:[s.jsx("polyline",{className:`chart-line ${t}`,points:e.points}),e.dots.map(o=>s.jsx("circle",{className:`chart-dot ${t}`,cx:o.cx,cy:o.cy,r:a},o.key))]})}function M0({items:e,cls:t}){return s.jsx(s.Fragment,{children:e.map(a=>s.jsx("text",{className:`chart-label ${t}`,x:a.x,y:a.y,textAnchor:a.anchor,transform:a.rotate?`rotate(-90 ${a.x} ${a.y})`:void 0,dominantBaseline:a.rotate?"central":void 0,children:a.text},a.key))})}function EQ({view:e}){const{width:t,height:a,plotLeft:o,plotW:c,plotTop:d,plotH:f}=e;return s.jsxs(s.Fragment,{children:[s.jsxs("svg",{className:"report-svg",width:t,height:a,viewBox:`0 0 ${t} ${a}`,role:"img","aria-label":r("近 24 小时缓存命中率与总 Token 趋势"),children:[e.grid.map(p=>s.jsx("line",{className:"chart-grid",x1:o,y1:p.y,x2:zt(o+c),y2:p.y},p.key)),e.rateTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,dominantBaseline:"middle",children:p.text},p.key)),e.tokenTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,dominantBaseline:"middle",children:p.text},p.key)),e.tokenLine?s.jsx(qD,{line:e.tokenLine,cls:"tokens",radius:e.dotR}):null,s.jsx(qD,{line:e.rateLine,cls:"rate",radius:e.dotR}),s.jsx(M0,{items:e.tokenLabels,cls:"tokens"}),s.jsx(M0,{items:e.rateLabels,cls:"rate"}),e.hourTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,children:p.text},p.key))]}),e.hits?s.jsx("svg",{className:"report-svg chart-hit-layer",width:t,height:a,viewBox:`0 0 ${t} ${a}`,"aria-hidden":"true",children:e.hits.map(p=>s.jsx("rect",{className:"chart-hit",x:p.x,y:d,width:p.width,height:zt(f),tabIndex:-1,"data-tip":p.tip,"data-tip-variant":"plain"},p.key))}):null]})}function AQ({view:e}){const{width:t,height:a,plotLeft:o,plotW:c,plotTop:d,plotH:f}=e;return s.jsxs(s.Fragment,{children:[s.jsxs("svg",{className:"report-svg",width:t,height:a,viewBox:`0 0 ${t} ${a}`,role:"img","aria-label":r("按天 Token 趋势"),children:[e.grid.map(p=>s.jsx("line",{className:"chart-grid",x1:p.x1,y1:p.y,x2:p.x2,y2:p.y},p.key)),e.valueTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,dominantBaseline:"middle",children:p.text},p.key)),e.bars.map(p=>p.nativeTip?s.jsx("rect",{className:"bar",x:p.x,y:p.y,width:p.width,height:p.height,rx:p.rx,children:s.jsx("title",{children:p.tip})},p.key):s.jsx("rect",{className:"bar",x:p.x,y:p.y,width:p.width,height:p.height,rx:p.rx},p.key)),s.jsx(M0,{items:e.barLabels,cls:"tokens"}),e.dateTicks.map(p=>s.jsx("text",{className:"chart-axis",x:p.x,y:p.y,textAnchor:p.anchor,children:p.text},p.key)),e.blank?s.jsx("text",{className:"chart-empty",x:zt(o+c/2),y:zt(d+f/2),textAnchor:"middle",children:r("所选范围内暂无请求")}):null]}),e.hits?s.jsx("svg",{className:"report-svg chart-hit-layer",width:t,height:a,viewBox:`0 0 ${t} ${a}`,"aria-hidden":"true",children:e.hits.map(p=>s.jsx("rect",{className:"chart-hit",x:p.x,y:d,width:p.width,height:zt(f),tabIndex:-1,"data-tip":p.tip,"data-tip-variant":"plain"},p.key))}):null]})}const RQ=680;function D0(){const e=x.useRef(null),[t,a]=x.useState(0);return x.useLayoutEffect(()=>{const o=e.current;if(!o)return;let c=o.clientWidth;if(c&&a(c),typeof ResizeObserver!="function")return;const d=new ResizeObserver(()=>{const f=o.clientWidth;!f||f===c||(c=f,a(f))});return d.observe(o),()=>d.disconnect()},[]),[e,t||RQ]}async function GD(){if(!A0)try{const e=await lc().workbuddyDesktop?.getScheduledTasks(),t=(e?.tasks||[]).find(a=>a.id==="reportAutoRefresh");I0(t||null),A0=Array.isArray(e?.tasks)}catch(e){console.warn("读取报表自动刷新间隔失败,按默认 1 秒:",e instanceof Error?e.message:e),I0(null)}}function I0(e){A0=!0;const t=Number(e?.interval);!!e&&typeof e=="object"&&Number.isFinite(t)&&t>0&&(e.unit==="seconds"||e.unit==="minutes")?(hx=e.enabled!==!1,mx=e.unit==="minutes"?t*6e4:t*1e3):(hx=!0,mx=VD),oc?.applyAutoConfig(mx,hx)}const OQ={summary:null,error:null};function MQ(){const[e,t]=x.useState(OQ),[a,o]=x.useState(YX),[c,d]=x.useState(QX),[f,p]=x.useState(()=>({ms:mx,enabled:hx})),[,h]=x.useState(0),b=x.useRef(a),y=x.useRef(c),v=x.useRef(""),j=x.useCallback((Y,re)=>{v.current=re,t(Y)},[]),w=x.useCallback(async(Y={})=>{GD();const re=++O0,M=b.current,U=M===k0?y.current:void 0;try{const Z=lc().workbuddyDesktop;if(!Z)throw new Error("后端桥不可用");const ae=await Z.getStatsSummary(M,U);if(re!==O0)return Uo;if(!ae||typeof ae!="object")throw new Error("后端未返回报表数据");Uo=ae;const ce=JSON.stringify(ae);return ce!==v.current&&j({summary:ae,error:null},ce),Uo}catch(Z){if(re!==O0)return Uo;const ae=Z instanceof Error?Z.message:"";return Uo=null,Y.silent||console.warn("读取报表数据失败:",ae),j({summary:null,error:ae||r("未知错误")},""),null}},[j]),k=x.useCallback(Y=>{Y!==void 0&&(Uo=Y||null,Y&&j({summary:Y,error:null},JSON.stringify(Y)))},[j]),S=x.useCallback(Y=>{const re=ix.includes(Y)?Y:N0;if(re!==b.current){b.current=re,o(re);try{localStorage.setItem(AD,re)}catch{}w()}},[w]),N=x.useCallback(Y=>{const re={...y.current,...Y};if(!cx.test(re.start)||!cx.test(re.end))return;const M=re.start<=re.end?re:Y.start?{start:re.start,end:re.start}:{start:re.end,end:re.end};y.current=M,d(M),ZX(M),b.current===k0&&w()},[w]);x.useEffect(()=>{if(oc={load:w,render:k,applyAutoConfig:(Y,re)=>p({ms:Y,enabled:re})},gx){const Y=gx;gx=null,k(Y.data)}return lc().wbApp?.currentPage==="overview"&&w({silent:!0}),()=>{oc=null}},[w,k]),x.useEffect(()=>{if(!f.enabled||f.ms<=0)return;const Y=window.setInterval(()=>{document.hidden||lc().wbApp?.currentPage!=="overview"||R0||(R0=!0,w({silent:!0}).finally(()=>{R0=!1}))},f.ms);return()=>{window.clearInterval(Y)}},[f,w]),x.useEffect(()=>{const Y=()=>h(re=>re+1);return window.addEventListener("wb-units-changed",Y),()=>window.removeEventListener("wb-units-changed",Y)},[]);const R=D0(),P=D0(),T=D0(),{summary:C,error:E}=e,D=C&&ix.includes(C.range??"")?C.range:a,I=C&&Array.isArray(C.heatmap)?C.heatmap:[],O=C&&Array.isArray(C.cacheTrend24h)?C.cacheTrend24h:[],_=C&&Array.isArray(C.dailyTrend)?C.dailyTrend:[],z=C&&Array.isArray(C.providers)?C.providers:null,H=C&&Array.isArray(C.accounts)?C.accounts:null,B=C&&Array.isArray(C.models)?C.models:null,L=E?ic(r("读取报表失败:{error}",{error:E}),"empty report-error"):null,F=ic(r("正在加载…")),$=L??F,X=x.useMemo(()=>BD(B||[]),[B]),K=x.useCallback(Y=>X.get(Y)||oQ,[X]),q=C?fQ(I,R[1]):null,Q=C?hQ(O,P[1],K):null,G=C?xQ(_,T[1],K):null,J=C0(new Date);return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("统计概览")}),s.jsx("span",{className:"panel-sub",id:"report-range-label",children:OD[D]||""}),s.jsxs("div",{className:"head-actions",children:[s.jsx(En,{options:bQ,value:a,onValueChange:S,"aria-label":r("报表时间范围")}),a===k0?s.jsxs("span",{className:"report-date-range",children:[s.jsx(Fe,{type:"date",className:"report-date-input w-[132px]",value:c.start,max:c.end||J,"aria-label":r("开始日期"),title:r("起始日期(含当天)"),onChange:Y=>N({start:Y.target.value})}),s.jsx("span",{className:"report-date-sep","aria-hidden":"true",children:"~"}),s.jsx(Fe,{type:"date",className:"report-date-input w-[132px]",value:c.end,min:c.start||void 0,max:J,"aria-label":r("结束日期"),title:r("结束日期(含当天)"),onChange:Y=>N({end:Y.target.value})})]}):null]})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"field-grid",id:"report-overview",children:C?s.jsx(CQ,{summary:C,range:D}):$})})]}),s.jsxs("div",{className:"report-rank-grid",children:[H?s.jsx(FD,{panelId:"report-accounts-panel",listId:"report-accounts",labelId:"report-accounts-label",title:r("Top 账号"),tip:vQ,rows:LD(H)||[],totalText:zD(H),withBadge:!0,emptyText:r("所选范围内还没有账号用量")}):null,z?s.jsx(FD,{panelId:"report-providers-panel",listId:"report-providers",labelId:"report-providers-label",title:r("Top 提供商"),tip:yQ,rows:LD(z)||[],totalText:zD(z),withBadge:!1,emptyText:r("所选范围内还没有请求记录")}):null]}),s.jsxs("div",{className:"report-donut-grid",children:[B?s.jsx($D,{panelId:"report-models-panel",listId:"report-models-donut",title:r("模型用量"),tip:jQ,ariaLabel:r("模型用量占比"),view:HD(B,r("未知模型")),emptyText:r("所选范围内还没有模型用量")}):null,z?s.jsx($D,{panelId:"report-providers-pie-panel",listId:"report-providers-donut",title:r("提供商用"),tip:wQ,ariaLabel:r("提供商用占比"),view:HD(z,r("未知")),emptyText:r("所选范围内还没有提供商用量")}):null]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("活跃热力图")}),s.jsx("span",{className:"panel-sub",children:r("近 365 天,按天 Token 用量着色(档位按本窗口峰值自动定)")})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"heat-wrap",id:"report-heatmap",ref:R[0],children:C?q?s.jsx(TQ,{view:q}):ic(r("暂无热力图数据")):$})}),s.jsxs("div",{className:"panel-foot",children:[s.jsx("span",{className:"heat-scale-label",children:r("Token")}),s.jsx("span",{className:"heat-legend",id:"report-heat-legend",children:C?pQ(UD(I)).map(Y=>s.jsxs("span",{className:"heat-legend-item",children:[s.jsx("span",{className:`l${Y.level}`}),Y.text]},Y.level)):null}),s.jsx("div",{className:"spacer"}),s.jsx("span",{children:r("方格为本地自然日,无请求显示为空槽")})]})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("缓存命中率")}),s.jsx(xx,{text:SQ})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"field-grid",id:"report-cache-rates",children:C?mQ(C.cacheRates).map(Y=>s.jsxs("div",{className:"field rate",children:[s.jsx("div",{className:"label",children:Y.label}),s.jsxs("div",{className:"value big",children:[Y.value,s.jsx("div",{className:"sub",children:Y.sub})]})]},Y.key)):$})})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("近 24 小时缓存命中率趋势")}),s.jsx("span",{className:"panel-sub",children:r("按本地整点,无请求的整点不标注")})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"chart-wrap",id:"report-cache-trend",ref:P[0],children:C?Q?s.jsx(EQ,{view:Q}):ic(r("暂无缓存趋势数据")):$})}),s.jsxs("div",{className:"panel-foot",children:[s.jsxs("span",{className:"chart-legend",children:[s.jsx("span",{className:"swatch rate"}),r("缓存命中率"),s.jsx("span",{className:"axis-hint",children:r("左轴")})]}),s.jsxs("span",{className:"chart-legend",children:[s.jsx("span",{className:"swatch tokens"}),r("总 Token"),s.jsx("span",{className:"axis-hint",children:r("右轴")})]}),s.jsx("div",{className:"spacer"}),s.jsx("span",{children:r("无请求的整点按 0% 计,但不写读数")})]})]}),s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("按天 Token 趋势")}),s.jsx(xx,{text:NQ}),s.jsx("span",{className:"panel-sub",id:"report-trend-label",children:C?`${C.startDate||"—"} ~ ${C.endDate||"—"}`:"—"})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"chart-wrap tall",id:"report-daily-trend",ref:T[0],children:C?G?s.jsx(AQ,{view:G}):ic(r("暂无趋势数据")):$})})]})]})}async function DQ(e={}){return oc?oc.load(e):Uo}function IQ(e){if(e!==void 0){if(!oc){gx={data:e??null};return}oc.render(e)}}function PQ(){return Uo}window.wbReport={load:DQ,render:IQ,lastSummary:PQ,applyAutoRefresh:I0};const KD='.page[data-page="overview"]';let YD=!1;function XD(){if(YD)return;const e=document.querySelector(KD);e&&(YD=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(MQ,{})))}document.querySelector(KD)?XD():document.addEventListener("DOMContentLoaded",XD,{once:!0}),GD();const P0={all:{title:r("全部删除"),desc:r("删除日志记录本身。当前有筛选时只删命中的条目,按天聚合报表不受影响;无筛选时清空全部并重置报表。此方式无法恢复。")},raw:{title:r("仅清空报文原文"),desc:r("保留统计行与报表,只抹掉请求 / 响应正文。清理后详情弹窗的「预览对话」将无原文可看,统计数字分毫不动。")}},_Q=["all","raw"],LQ=3e3;function _l(){return window}let jp=!1;function wp(e,t){_l().wbApp?.toast?.(e,t)}function zQ(e){const t=Math.max(0,Number(e)||0);if(t<1024)return`${Math.round(t)} B`;const a=t/1024;if(a<1024)return`${a.toFixed(1)} KB`;const o=a/1024;return o<1024?`${o.toFixed(1)} MB`:`${(o/1024).toFixed(2)} GB`}function _0(){const e=_l().wbRequestsPanel?.clearParams?.();return typeof e=="string"?e:""}function QD(e){return{all:Number(e?.all)||0,raw:Number(e?.raw)||0,dbBytes:Number(e?.dbBytes)||0,vacuumRunning:e?.vacuumRunning===!0}}function L0(e){return e instanceof Error?e.message:String(e)}function ZD(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t]??t)}function BQ({onClose:e}){const[t,a]=x.useState("all"),[o,c]=x.useState({status:"loading"}),[d,f]=x.useState(""),[p,h]=x.useState(!1),[b,y]=x.useState(!1),v=x.useRef(!0),j=x.useRef(null),w=x.useCallback(D=>{jp=D,y(D)},[]),k=x.useCallback(()=>{j.current!==null&&(window.clearInterval(j.current),j.current=null)},[]),S=x.useCallback(D=>{c({status:"ready",all:D.all,raw:D.raw,dbBytes:D.dbBytes}),h(D.vacuumRunning)},[]),N=x.useCallback(async()=>{const D=_l().workbuddyDesktop;if(!D)return;let I;try{I=await D.getStatsClearPreview(_0())}catch{return}if(!v.current)return;const O=QD(I);S(O),!O.vacuumRunning&&(k(),f(""),wp(r("✅ 压缩完成")),_l().wbRequestsPanel?.load?.({silent:!0}))},[S,k]),R=x.useCallback(()=>{j.current===null&&(h(!0),j.current=window.setInterval(()=>{N()},LQ))},[N]);async function P(){c({status:"loading"});try{const D=_l().workbuddyDesktop;if(!D)throw new Error(r("后端桥不可用"));const I=await D.getStatsClearPreview(_0());if(!v.current)return;const O=QD(I);S(O),O.vacuumRunning&&R()}catch(D){if(!v.current)return;c({status:"failed"}),f(r("预览读取失败:{error}",{error:L0(D)}))}}x.useEffect(()=>(v.current=!0,P(),()=>{v.current=!1,k(),jp=!1}),[]);async function T(){const D=_l().workbuddyDesktop;if(D){h(!0);try{await D.compactStatsDb(),f(r("压缩已在后台开始,完成后会自动提示")),R()}catch(I){const O=L0(I);if(/409|正在进行/.test(O)){wp(r("压缩已在进行中")),f(r("压缩已在进行中,接上它的进度等待完成")),R();return}h(!1),f(r("压缩失败:{message}",{message:O})),wp(r("压缩失败:{message}",{message:O}),"err")}}}async function C(){if(jp)return;const D=_l().workbuddyDesktop,I=_l().wbConfirm?.ask;if(!D||!I)return;const O=P0[t].title,_=_0(),z=_.length>0,H=o.status==="ready"?t==="raw"?o.raw:o.all:0;if(await I({title:r("清理请求日志"),html:z?r("确定按当前筛选执行「{label}」?将处理 {count} 条,此操作无法恢复。",{label:ZD(O),count:H}):r("确定对全部请求日志执行「{label}」?将处理 {count} 条,此操作无法恢复。",{label:ZD(O),count:H}),okText:r(t==="raw"?"抹掉原文":"删除"),okClass:"danger"})){w(!0);try{const L=z?`mode=${t}&${_}`:`mode=${t}&all=1`,F=await D.clearStatsRequests(L),$=Number(F?.deleted)||0;wp(t==="raw"?r("已抹掉 {count} 条报文原文",{count:$}):r("已删除 {count} 条",{count:$})),w(!1),e(),_l().wbRequestsPanel?.notifyCleared?.()}catch(L){const F=L0(L);f(r("清理失败:{message}",{message:F})),wp(r("清理失败:{message}",{message:F}),"err"),w(!1)}}}const E=o.status==="ready"?r("将删除 {count} 条日志 · 其中 {raw} 条仍带报文原文 · 数据库占用 {db}",{count:o.all,raw:o.raw,db:zQ(o.dbBytes)}):o.status==="failed"?r("预览读取失败"):r("正在统计…");return s.jsx(Yt,{open:!0,onOpenChange:(D,I)=>{if(!D){if(jp){I.cancel();return}e()}},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("清理请求日志")})}),s.jsxs(Lt,{children:[s.jsx(_h,{"aria-label":r("清理方式"),value:t,onValueChange:D=>a(D==="raw"?"raw":"all"),children:_Q.map(D=>{const I=t===D;return s.jsxs("label",{"data-checked":I?"":void 0,className:"group/card grid cursor-pointer grid-cols-[auto_minmax(0,1fr)] items-center gap-x-2.5 gap-y-0.5 rounded-md border border-border px-3 py-2.5 transition-colors duration-150 ease-out hover:border-border-strong data-checked:border-primary data-checked:bg-primary-soft",children:[s.jsx(jo,{value:D,className:"row-span-2 self-center"}),s.jsx("span",{className:"text-[13px] font-semibold text-foreground group-data-checked/card:text-primary-fg",children:P0[D].title}),s.jsx("span",{className:"text-[11.5px] leading-[1.55] text-subtle",children:P0[D].desc})]},D)})}),s.jsx("p",{className:"text-[11.5px] text-muted-foreground",children:E})]}),s.jsxs(tn,{children:[s.jsx("span",{className:"min-w-0 text-[11.5px] text-muted-foreground",children:d}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>{T()},disabled:p,title:r(p?"压缩正在后台执行,完成后自动恢复":"回收已删除数据占用的磁盘空间(checkpoint + VACUUM,后台执行)"),children:r(p?"压缩中…":"压缩数据库")}),s.jsx(ne,{variant:"outline",onClick:e,disabled:b,children:r("取消")}),s.jsx(ne,{variant:"destructive",onClick:()=>{C()},disabled:b,children:r(b?"清理中…":"执行清理")})]})]})})}let Sp=null,Qu=null;function WD(){Sp&&(Sp.unmount(),Sp=null),Qu&&(Qu.remove(),Qu=null)}function HQ(){jp||WD()}function UQ(){WD(),Qu=document.createElement("div"),document.body.append(Qu),Sp=jn.createRoot(Qu),Sp.render(s.jsx(BQ,{onClose:HQ}))}window.wbRequestClearModal={open:UQ};const JD=[{value:"detail",label:r("请求详情")},{value:"preview",label:r("预览对话")},{value:"raw",label:r("原始报文")}],VQ="detail",eI="border-b border-hairline px-2.5 py-[7px] align-top",Vo="border border-hairline px-2 py-1 align-top",FQ="border border-hairline bg-surface-2 px-2 py-1 text-[11.5px] tracking-normal",bx="hover:[&>td]:bg-transparent";function Zu(){return window}function z0(){const e=Zu().workbuddyDesktop;if(!e)throw new Error(r("后端桥不可用"));return e}let B0=0;function $Q(e){if(!e)return"—";const t=new Date(e),a=o=>String(o).padStart(2,"0");return`${t.getFullYear()}-${a(t.getMonth()+1)}-${a(t.getDate())} ${a(t.getHours())}:${a(t.getMinutes())}:${a(t.getSeconds())}`}function tI(e){const t=Math.round(Number(e)||0);if(t<1e3)return`${t}ms`;const a=Math.floor(t/1e3);if(a>=60)return r("{m}分{s}秒",{m:Math.floor(a/60),s:a%60});const o=t%1e3;return o>0?r("{s}秒{ms}ms",{s:a,ms:o}):r("{n}秒",{n:a})}function qQ(e){const t=Number(e);return!Number.isFinite(t)||t<=0?"-":tI(t)}const GQ=r("生成速度:输出 token ÷ 流式段用时(总用时 − 首响);流式段不足总用时一半时按总用时计");function KQ(e){const t=Number(e.completionTokens)||0,a=Number(e.durationMs)||0;if(t<=0||a<=0)return"";const o=Number(e.firstResponseMs),c=Number.isFinite(o)&&o>0&&o=500&&c*2>=a,f=t/((d?c:a)/1e3);return`${f>=100?Math.round(f):f.toFixed(1)} tok/s`}function vx(e){return Zu().wbUnits?.formatTokens?.(e)??(Number(e)||0).toLocaleString("zh-CN")}function YQ(e){const t=Math.max(0,Date.now()-(Number(e)||0));return r("{n}秒",{n:Math.max(1,Math.floor(t/1e3))})}function XQ(e){const t=Number(e.status)||0;return t>=200&&t<300&&!e.error}function yx(e){return(Number(e?.status)||0)===0&&!e?.error}function nI(e){const t=String(e.provider??"").trim();return String(e.providerLabel??"").trim()||(t?Zu().wbProviders?.labelOf?.(t)||t:"")}function Np(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function H0(e){if(e==null)return"";if(typeof e=="string")return e;try{return JSON.stringify(e,null,2)}catch{return""}}function U0(e){return e instanceof Error?e.message:String(e)}const sI=[{label:r("请求头"),pick:e=>H0(e.requestHeaders)},{label:r("请求体"),pick:e=>H0(e.requestBody)},{label:r("响应头"),pick:e=>H0(e.responseHeaders)},{label:r("响应体"),pick:e=>e.responseBody?String(e.responseBody):""}];function jx({text:e,loading:t=!1}){return s.jsxs("div",{className:"flex items-center justify-center gap-2 py-6 text-center text-[12.5px] text-muted-foreground",children:[t?s.jsx(of,{className:"size-3.5"}):null,e]})}function pa({label:e,children:t}){return s.jsxs(Cl,{className:bx,children:[s.jsx("th",{scope:"row",className:`w-[76px] whitespace-nowrap text-left text-[12.5px] font-semibold text-muted-foreground ${eI}`,children:e}),s.jsx(Tn,{className:eI,children:t})]})}function QQ({row:e}){if(yx(e)){const c=Zu().wbRequestPhase;if(!c?.badgeHtml)return s.jsxs(ze,{variant:"info",shape:"tag",title:r("请求正在转发中,用时列显示的是已用时"),children:[s.jsx(my,{className:"req-live-dot"}),r("进行中")]});const d=c.elapsedLineHtml?.(e)??"";return s.jsxs("span",{className:"inline-flex flex-wrap items-center gap-1.5",children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:c.badgeHtml(e)}}),d?s.jsx("span",{className:"text-[11.5px] text-muted-foreground",dangerouslySetInnerHTML:{__html:d}}):null]})}const t=Number(e.status)||0,a=XQ(e),o=!a&&t>=200&&t<300?r("HTTP {status},但响应体阶段出错",{status:t}):"";return s.jsx(ze,{variant:a?"success":"destructive",shape:"tag",title:o||void 0,children:t||r("失败")})}function ZQ({row:e}){const t=String(e.clientModel??"").trim(),a=String(e.upstreamModel??"").trim(),o=String(e.model??"").trim(),c=String(e.clientReasoning??"").trim(),d=String(e.upstreamReasoning??"").trim(),f=(b,y)=>y?`${b}(${y})`:b;if(!t||!a||a.toLowerCase()===t.toLowerCase())return s.jsx(s.Fragment,{children:f(o,d||c)||"—"});const p=f(a,d),h=f(t,c);return s.jsxs("span",{className:"flex flex-col gap-0.5",children:[s.jsxs("span",{title:r("转发到上游的模型:{model}",{model:p}),children:["⬆️ ",p]}),s.jsxs("span",{className:"text-muted-foreground",title:r("下游请求的模型:{model}",{model:h}),children:["⬇️ ",h]})]})}function WQ(e){const t=Number(e?.status),a=e?.status!==null&&e?.status!==void 0&&Number.isFinite(t),o=e?.error?String(e.error):"";if(o){const c=a?r("失败({status}):{error}",{status:String(t),error:o}):r("失败:{error}",{error:o});return s.jsx("span",{className:"break-words text-destructive",children:c})}return a?s.jsx("span",{className:"text-success",children:r("成功({status})",{status:String(t)})}):s.jsx("span",{className:"text-muted-foreground",children:r("无结果记录")})}function JQ({row:e}){const t=Array.isArray(e.attemptDetails)?e.attemptDetails:[];if(!t.length)return s.jsx(s.Fragment,{children:"-"});const a=Number(e.attempts)||1;return s.jsxs(Zy,{className:"text-[11.5px]",children:[s.jsx(AE,{children:s.jsx(Cl,{className:bx,children:[r("轮次"),r("提供商"),r("账号"),r("结果"),r("体积"),r("内部重试"),r("提示")].map(o=>s.jsx(RE,{className:FQ,children:o},o))})}),s.jsxs(Wy,{children:[t.map((o,c)=>{const d=Array.isArray(o?.retries)?o.retries:[],f=d.map(v=>{const j=Number(v?.delayMs),w=Number.isFinite(j)&&j>0?j>=1e3?r(",{n}秒后重试",{n:Math.round(j/1e3)}):r(",{n}毫秒后重试",{n:Math.round(j)}):"";return`${String(v?.reason||r("未知原因"))}${w}`}).join(` +`),p=String(o?.notice??"").trim(),h=Number(o?.bodyBytes),b=Number.isFinite(h)&&h>0?h>=1024*1024?`${(h/1024/1024).toFixed(1)} MB`:h>=1024?`${Math.round(h/1024)} KB`:`${h} B`:"—",y=Number.isFinite(h)&&h>0?r("实际发给上游 {bytes} 字节",{bytes:h.toLocaleString()}):void 0;return s.jsxs(Cl,{className:bx,children:[s.jsx(Tn,{className:Vo,children:c+1}),s.jsx(Tn,{className:Vo,children:nI(o)||(o?.provider?String(o.provider):r("未知"))}),s.jsx(Tn,{className:Vo,children:o?.account?String(o.account):"—"}),s.jsx(Tn,{className:Vo,children:WQ(o)}),s.jsx(Tn,{className:`${Vo} whitespace-nowrap`,title:y,children:b}),s.jsx(Tn,{className:`${Vo} whitespace-nowrap`,title:f||void 0,children:d.length?r("↻ {n} 次",{n:d.length}):"-"}),s.jsx(Tn,{className:Vo,children:p||"—"})]},c)}),t.lengths.jsxs("li",{className:"py-0.5",children:[s.jsxs("b",{children:[y+1,". ",String(b.name||b.id||"—")]}),s.jsxs("span",{className:"text-muted-foreground",children:[" ",String(b.reason||"")]})]},String(b.id??y)))}):null,p.length?s.jsxs("div",{className:"mt-1 text-muted-foreground",children:[r("被跳过:"),p.map(b=>String(b.name||b.id||"")).join("、")]}):null,h?s.jsx("div",{className:"mt-1",children:r("最终承载:{picked}",{picked:h})}):null]})}function tZ({row:e}){if(!e)return s.jsx(jx,{text:r("列表数据已刷新,请重试(关闭后重新打开这条详情)")});const t=String(e.accountName??"").trim(),a=KQ(e);return s.jsx(Zy,{className:"text-[12.5px] text-subtle [&_tr:last-child>td]:border-b-0 [&_tr:last-child>th]:border-b-0",children:s.jsxs(Wy,{children:[s.jsx(pa,{label:r("时间"),children:$Q(e.ts)}),s.jsx(pa,{label:r("状态"),children:s.jsx(QQ,{row:e})}),s.jsx(pa,{label:r("耗时"),children:yx(e)?s.jsxs(s.Fragment,{children:[YQ(e.ts),s.jsx("span",{className:"text-[11.5px] text-muted-foreground",children:r("(请求仍在转发中)")})]}):r("{duration} / 首帧 {first}",{duration:tI(e.durationMs),first:qQ(e.firstResponseMs)})}),s.jsx(pa,{label:r("重试次数"),children:String(Number(e.attempts)||1)}),s.jsx(pa,{label:r("模型"),children:s.jsx(ZQ,{row:e})}),s.jsxs(pa,{label:r("提供商"),children:[nI(e)||"—",t?s.jsx("span",{className:"text-[11.5px] text-muted-foreground",children:r("(账号:{account})",{account:t})}):null]}),s.jsxs(pa,{label:r("令牌"),children:[r("输入 {input} · 输出 {output} · 总计 {total} · 缓存读 {cache}",{input:vx(e.promptTokens),output:vx(e.completionTokens),total:vx(e.totalTokens),cache:vx(e.cacheReadTokens)}),a?s.jsxs("span",{title:GQ,children:[" · ",a]}):null]}),e.isTest?s.jsx(pa,{label:r("来源"),children:s.jsx(ze,{variant:"brand",shape:"tag",title:r("模型管理页操作列那颗「测试」发起的请求:与真实请求同一条转发链路,但不计入报表统计"),children:r("模型测试")})}):null,s.jsx(pa,{label:r("错误"),children:e.error?s.jsx("span",{className:"text-destructive",children:String(e.error)}):"—"}),s.jsx(pa,{label:r("尝试明细"),children:s.jsx(JQ,{row:e})}),e.route?s.jsx(pa,{label:r("路由回放"),children:s.jsx(eZ,{row:e})}):null,s.jsx(pa,{label:r("敏感词"),children:Array.isArray(e.sensitiveHits)&&e.sensitiveHits.length?s.jsx("span",{className:"inline-flex flex-wrap gap-1.5",children:e.sensitiveHits.map((o,c)=>s.jsxs(ze,{variant:"sensitive",shape:"tag",children:[String(o?.word??"")," × ",String(Number(o?.count)||0)]},c))}):"—"})]})})}function nZ({state:e}){if(!e)return s.jsx(jx,{text:r("正在读取…"),loading:!0});const t=e==="gone"?null:e.body,a=t&&Zu().wbConversationPreview?.render?.(t.requestBody,t.responseBody)||"";return a?s.jsxs("div",{children:[e!=="gone"&&e.truncated?s.jsx("div",{className:"mb-2 text-[11.5px] text-warning",children:r("正文超过单条上限,可能已被截断")}):null,s.jsx("div",{dangerouslySetInnerHTML:{__html:a}})]}):s.jsx(jx,{text:r("无报文原文(未开启「调试模式」,或已被清理)")})}function sZ({data:e}){const t=e.status===null||e.status===void 0?"-":String(e.status),a=[e.url?`URL: ${e.url}`:"",e.provider?r("提供商: {provider}",{provider:String(e.provider)}):"",r("上游状态码: {status}",{status:t})].filter(Boolean);return s.jsxs("div",{className:"flex flex-col gap-4",children:[a.length?s.jsx("div",{className:"border-b border-hairline pb-2.5 text-xs leading-[1.7] break-all text-subtle",children:a.map((o,c)=>s.jsx("div",{children:o},c))}):null,sI.map(o=>{const c=o.pick(e)||"";return s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx("h3",{className:"text-[11.5px] font-semibold tracking-[.02em] text-muted-foreground",children:o.label}),c?s.jsx("pre",{className:"max-h-80 overflow-auto rounded-md border border-border bg-surface-2 p-[10px_12px] font-mono text-[11.5px] leading-[1.6] break-words whitespace-pre-wrap text-subtle",children:c}):s.jsx(jx,{text:r("这条请求没有保存这一段报文")})]},o.label)})]})}function rZ({id:e,row:t,token:a,onClose:o}){const[c,d]=x.useState(VQ),[f,p]=x.useState(null),[h,b]=x.useState(null),[y,v]=x.useState("—"),[j,w]=x.useState("idle"),k=x.useRef(!0),S=x.useRef(null),N=x.useRef({detail:0,preview:0,raw:0}),R=x.useCallback(()=>!k.current||a!==B0,[a]);async function P(){try{const O=await z0().getStatsRequestRaw(e);if(R())return;const _=Np(O)?O:null,z=String(_?.requestBody??"").trim()!==""||String(_?.responseBody??"").trim()!=="";p(_&&z?{body:_,truncated:!!_.truncated}:"gone")}catch(O){if(R())return;p("gone"),console.warn("读取原始正文失败(预览对话显示空态):",U0(O))}}async function T(){try{const O=await z0().getDebugTraffic(e);if(R())return;const _=Np(O)?O:{};if(!sI.some(z=>(z.pick(_)||"").trim())){b("gone");return}b({data:_}),v(_.truncated?r("报文超过单条上限,请求体 / 响应体已按上限截断"):r("内容按原样保存,请求头中的凭据字段已替换为 [redacted]"))}catch(O){if(R())return;b("gone"),v(r("在设置 → 通用里开启「调试模式」后,新发生的请求才会保存报文")),console.warn("读取调试报文失败(原始报文标签隐藏):",U0(O))}}x.useEffect(()=>(k.current=!0,P(),T(),()=>{k.current=!1}),[]),x.useLayoutEffect(()=>{const O=S.current;O&&(O.scrollTop=N.current[c])},[c]);function C(O){if(O==="raw"&&!Np(h)||O===c)return;const _=S.current;_&&(N.current[c]=_.scrollTop),d(O)}async function E(){if(!e||!yx(t))return;const O=Zu().wbConfirm?.ask;if(!(!O||!await O({title:r("终止请求"),html:r("确定终止这条正在转发的请求?
    上游连接会立即断开,明细将记为「请求已被手动终止」。"),okText:r("终止"),okClass:"danger"}))){w("pending");try{if(await z0().terminateStatsRequest(e),!k.current)return;w("accepted"),v(r("已受理终止:上游连接已断开,列表稍后刷新为「请求已被手动终止」"))}catch(z){if(!k.current)return;w("idle"),v(r("终止失败:{error}",{error:U0(z)}))}}}const D=Np(h),I=x.useMemo(()=>D?JD:JD.filter(O=>O.value!=="raw"),[D]);return s.jsx(Yt,{open:!0,onOpenChange:O=>{O||o()},children:s.jsxs(Xt,{className:"w-[min(920px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("请求详情")})}),s.jsxs(Lt,{ref:S,className:"gap-3",children:[s.jsx(En,{options:I,value:c,onValueChange:C,"aria-label":r("详情内容"),className:"self-start"}),s.jsx("section",{hidden:c!=="detail",children:s.jsx(tZ,{row:t})}),s.jsx("section",{hidden:c!=="preview",children:s.jsx(nZ,{state:f})}),D?s.jsx("section",{hidden:c!=="raw",children:s.jsx(sZ,{data:h.data})}):null]}),s.jsxs(tn,{children:[s.jsx("span",{className:"min-w-0 text-[11.5px] text-muted-foreground",children:y}),s.jsx("div",{className:"mr-auto"}),yx(t)?s.jsx(ne,{variant:"destructive",disabled:j!=="idle",onClick:()=>{E()},title:r("断开上游连接,明细记为「请求已被手动终止」"),children:r("终止请求")}):null,s.jsx(ne,{variant:"outline",onClick:o,children:r("关闭")})]})]})})}let kp=null,Wu=null;function rI(){kp&&(kp.unmount(),kp=null),Wu&&(Wu.remove(),Wu=null)}function aI(){B0+=1,rI()}function aZ(e,t){const a=String(e??"").trim();if(!a)return;rI();const o=++B0;Wu=document.createElement("div"),document.body.append(Wu),kp=jn.createRoot(Wu),kp.render(s.jsx(rZ,{id:a,row:Np(t)?t:null,token:o,onClose:aI}))}window.wbRequestDetail={open:aZ,close:aI};const lZ=150,oZ=80,cc=8,wx=8,iZ=520,cZ=220,uZ=1.1,dZ=900,V0=12,F0="req-hover-panel",fZ=["fixed z-[35] pointer-events-none","max-h-[min(360px,60vh)] overflow-x-hidden overflow-y-auto","rounded-md p-[10px_12px] text-[12px] leading-[1.6] break-normal","bg-surface-2 text-foreground shadow-3","border-0 dark:border dark:border-border-strong dark:bg-surface-3"].join(" "),Cp="rh-row rh-dim min-w-0 break-words text-muted-foreground",pZ="rh-row min-w-0 break-words";function mZ(){return window}function $0(e){return typeof e=="object"&&e!==null?e:null}const lI=e=>Array.isArray(e?.attemptDetails)?e.attemptDetails:[],oI=e=>Array.isArray(e?.retries)?e.retries:[],hZ=e=>Array.isArray(e?.sensitiveHits)?e.sensitiveHits:[];function q0(e){const t=String(e??"").trim();return t?mZ().wbProviders?.labelOf?.(t)||t:""}function gZ(e){const t=$0(e);return(Number(t?.attempts)||1)>1?!0:lI(t).some(a=>oI(a).length>0||!!a?.notice)}function iI(e){return e.dataset.reqHover==="sensitive"?"sensitive":"chain"}function xZ({details:e}){if(e.length<2)return null;const t=e.map(a=>q0(a.provider)||r("未知"));return s.jsxs("div",{className:"rh-chain mb-1.5 border-b border-border pb-1.5 break-words",children:[s.jsx("span",{className:"rh-chain-k font-semibold text-muted-foreground",children:r("切换路径:")}),s.jsx("span",{className:"rh-chain-v font-semibold text-foreground",children:t.join(" → ")})]})}function bZ({item:e}){const t=oI(e);return t.length?s.jsxs("div",{className:"rh-retry mt-0.5 mb-1 ml-2.5 border-l-2 border-border-strong pl-2",children:[s.jsx("div",{className:"rh-retry-head text-[11.5px] font-semibold text-warning",children:r("↻ 重试 {n} 次",{n:t.length})}),t.map((a,o)=>{const c=String(a?.reason??"").trim(),d=Number(a?.status),f=a?.status!==null&&a?.status!==void 0&&Number.isFinite(d),p=Number(a?.delayMs),h=Number.isFinite(p)&&p>0?p>=1e3?r(",{n}秒后重试",{n:Math.round(p/1e3)}):r(",{n}毫秒后重试",{n:Math.round(p)}):"";return s.jsxs("div",{className:"rh-retry-row min-w-0 break-words",children:[s.jsx("span",{className:"rh-retry-why mr-1 text-subtle [overflow-wrap:anywhere]",children:c||r("未知原因")}),f?s.jsx("span",{className:"rh-retry-status mr-1 text-muted-foreground tabular-nums whitespace-nowrap",children:`HTTP ${String(d)}`}):null,h?s.jsx("span",{className:"rh-dim text-muted-foreground",children:h}):null]},o)})]}):null}function vZ({item:e,index:t,inFlight:a}){const o=q0(e.provider),c=String(e.account??"").trim(),d=Number(e.status),f=e.status!==null&&e.status!==void 0&&Number.isFinite(d),p=e.error?String(e.error):"",h=String(e.notice??"").trim();return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:pZ,children:[s.jsx("span",{className:"rh-no mr-1 text-muted-foreground",children:r("尝试 {n} ·",{n:t+1})}),s.jsx("span",{className:"rh-who mr-1 font-semibold text-foreground",children:o||r("未知")}),c?s.jsx("span",{className:"rh-account mr-1 text-muted-foreground [overflow-wrap:anywhere]",children:c}):null,s.jsx("span",{className:"rh-arrow mr-1 text-muted-foreground",children:"→"}),p?s.jsx("span",{className:"rh-bad font-medium text-destructive [overflow-wrap:anywhere]",children:f?r("失败({status}):{error}",{status:String(d),error:p}):r("失败:{error}",{error:p})}):f?s.jsx("span",{className:"rh-ok font-medium text-success",children:r("成功({status})",{status:String(d)})}):a?s.jsx("span",{className:"rh-dim text-muted-foreground",children:r("进行中…")}):s.jsx("span",{className:"rh-dim text-muted-foreground",children:r("无结果记录")})]}),h?s.jsx("div",{className:"rh-notice mt-0.5 mb-1 ml-2.5 border-l-2 border-border-strong pl-2 text-warning [overflow-wrap:anywhere]",children:`⚠️ ${h}`}):null,s.jsx(bZ,{item:e})]})}function yZ({entry:e}){const t=Number(e.attempts)||1,a=lI(e);if(!a.length){const c=q0(e.provider),d=c?r("共 {n} 次尝试,最终由 {provider} 承载",{n:t,provider:c}):r("共 {n} 次尝试",{n:t});return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:Cp,children:d}),s.jsx("div",{className:Cp,children:r("这条记录的尝试明细未采集(该字段上线前的旧数据,或请求在转发前就失败)")})]})}const o=(Number(e.status)||0)===0&&!e.error;return s.jsxs(s.Fragment,{children:[s.jsx(xZ,{details:a}),a.map((c,d)=>s.jsx(vZ,{item:c,index:d,inFlight:o&&d===a.length-1},d)),a.lengths.jsxs("div",{className:"rh-row rh-hit flex items-baseline justify-between gap-2.5",children:[s.jsx("span",{className:"rh-hit-w break-words text-foreground",children:String(a?.word??"")}),s.jsx("span",{className:"rh-hit-c text-muted-foreground tabular-nums whitespace-nowrap",children:`× ${String(Number(a?.count)||0)}`})]},o)),t.length>V0?s.jsx("div",{className:Cp,children:r("另有 {n} 个词命中",{n:t.length-V0})}):null]}):s.jsx("div",{className:Cp,children:r("这条记录命中了敏感词,但没有留下命中明细")})}function wZ({kind:e,entry:t,panelRef:a}){return s.jsx("div",{ref:a,id:F0,role:"tooltip","data-kind":e,className:fZ,children:e==="sensitive"?s.jsx(jZ,{entry:t}):s.jsx(yZ,{entry:t})})}let On=null,Fo=0,Tp=0,Ep=null,Sx=null,G0=null,K0=null,uc=null,dc=null,Ap=null,cI="chain";function Y0(){window.clearTimeout(Fo),window.clearTimeout(Tp),Fo=0,Tp=0,Ep=null}function SZ(){const e=Ap?.current,t=On;if(!e||!t)return;const a=t.getBoundingClientRect(),o=window.innerWidth-cc*2;e.style.maxWidth="none",e.style.width="max-content";const c=e.offsetWidth,d=cI==="sensitive",p=Math.max(d?cZ:iZ,c)*(d?uZ:1),h=Math.min(p,o,dZ);e.style.maxWidth=`${h}px`,e.style.width=d?`${h}px`:"auto";const b=e.offsetWidth,y=e.offsetHeight,v=window.innerHeight-a.bottom-wx-cc,j=a.top-wx-cc,w=vv,k=a.left+a.width/2,S=Math.max(cc,Math.min(k-b/2,window.innerWidth-cc-b)),N=w?a.top-wx-y:a.bottom+wx;e.style.left=`${Math.round(S)}px`,e.style.top=`${Math.round(Math.max(cc,Math.min(N,window.innerHeight-cc-y)))}px`}function uI(e){if(!On)return;const t=e.target;t instanceof Node&&(t===On||On.contains(t)||Oa())}function dI(){Oa()}function fI(){Oa()}let Nx=!1;function NZ(){Nx||(Nx=!0,document.addEventListener("click",uI,!0),window.addEventListener("scroll",dI,!0),window.addEventListener("resize",fI))}function kZ(){Nx&&(Nx=!1,document.removeEventListener("click",uI,!0),window.removeEventListener("scroll",dI,!0),window.removeEventListener("resize",fI))}function CZ(){kZ(),dc&&(dc.unmount(),dc=null),uc&&(uc.remove(),uc=null),Ap=null}function pI(e,t){cI=e,(!uc||!dc||!Ap)&&(uc=document.createElement("div"),document.body.append(uc),Ap=x.createRef(),dc=jn.createRoot(uc));const a=dc,o=Ap;Ts.flushSync(()=>{a.render(s.jsx(wZ,{kind:e,entry:t,panelRef:o}))}),NZ(),SZ()}function mI(e){if(!e.isConnected)return;const t=$0(G0?.(e));t&&(Y0(),On&&On!==e&&Oa(),On=e,pI(iI(e),t),e.classList.add("active"),e.setAttribute("aria-describedby",F0))}function Oa(){Y0(),On&&(On.classList.remove("active"),On.removeAttribute("aria-describedby"),On=null),CZ()}function TZ(){if(!On)return;const e=String(On.dataset.reqHover||""),t=String(On.dataset.reqId||"");K0=!!(e&&t)&&On.matches(":hover")&&!Tp?{action:"move",kind:e,key:t}:{action:"close"}}function EZ(){const e=K0;if(K0=null,!e||!On)return;if(e.action==="close"){Oa();return}const t=Sx?AZ(Sx,e.kind,e.key):null,a=t?$0(G0?.(t)):null;if(!t||!a){Oa();return}t!==On&&(On.classList.remove("active"),On.removeAttribute("aria-describedby"),On=t,pI(iI(t),a),t.classList.add("active"),t.setAttribute("aria-describedby",F0))}function AZ(e,t,a){for(const o of e.querySelectorAll("[data-req-hover]"))if(String(o.dataset.reqHover||"")===t&&String(o.dataset.reqId||"")===a)return o;return null}function kx(e){const t=e.target;return t instanceof Element?t.closest("[data-req-hover]"):null}function RZ(e){const t=kx(e);if(!t||!Sx?.contains(t)||(Y0(),On===t&&dc))return;const a=On?0:lZ;On&&Oa(),Ep=t,Fo=window.setTimeout(()=>{Fo=0,Ep=null,mI(t)},a)}function OZ(e){const t=kx(e);if(t){if(Ep===t){window.clearTimeout(Fo),Fo=0,Ep=null;return}On===t&&(window.clearTimeout(Fo),Fo=0,Tp=window.setTimeout(()=>{Tp=0,On===t&&Oa()},oZ))}}function MZ(e){const t=kx(e);t&&mI(t)}function DZ(e){const t=kx(e);t&&On===t&&Oa()}function IZ(e){e.key!=="Escape"||!On||Oa()}function PZ(e){const t=e?.host;t&&(Sx=t,G0=e?.entryOf??null,t.addEventListener("pointerover",RZ),t.addEventListener("pointerout",OZ),t.addEventListener("focusin",MZ),t.addEventListener("focusout",DZ),t.addEventListener("keydown",IZ))}window.wbRequestHover={bind:PZ,close:Oa,hasProcessFacts:gZ,beforeListRedraw:TZ,afterListRedraw:EZ};function As(){return window}function X0(e){return e instanceof Error?e.message:String(e)}function Cx(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t]??t)}const Tx={connecting:{label:r("连接中"),cls:"phase-connecting"},waiting:{label:r("等待响应"),cls:"phase-waiting"},streaming:{label:r("响应中"),cls:"phase-streaming"},retrying:{label:r("重试中"),cls:"phase-retrying"},queued:{label:r("排队中"),cls:"phase-queued"}},hI=r("进行中"),_Z="running",gI={connecting:r("请求已受理,正在选路、取凭证、建立上游连接"),waiting:r("上游请求已发出,正在等第一个字节到达(模型的思考时间也在这段)"),streaming:r("首帧已到,上游内容正在下发"),retrying:r("本轮尝试失败,正在退避等待或切换到下一个账号"),queued:r("上游模型繁忙,请求已排进上游队列;网关正按上游建议的时长等待后重发(不是登录态或额度问题)"),"":r("请求正在转发中,用时列显示的是已用时")};function Q0(e){const t=String(e?.phase??"").trim().toLowerCase();return Object.prototype.hasOwnProperty.call(Tx,t)?t:""}function xI(e){const t=Q0(e);return t?Tx[t].label:hI}function bI(e){if(e==null||e==="")return"";const t=Number(e);if(!Number.isFinite(t)||t<0)return"";const a=Math.max(1,Math.floor(t/1e3));return a<60?r("{n}秒",{n:a}):r("{m}分{s}秒",{m:Math.floor(a/60),s:a%60})}function LZ(e){const t=e?.phaseElapsedMs;if(t!=null&&t!==""){const c=Number(t);if(Number.isFinite(c)&&c>=0)return c}const a=Number(e?.phaseStartedAt);if(!Number.isFinite(a)||a<=0)return null;const o=Date.now()-a;return Number.isFinite(o)?Math.max(0,o):null}function zZ(e){const t=Q0(e),a=t?Tx[t].label:hI,o=t?Tx[t].cls:_Z,c=gI[t]||gI[""];return`${Cx(a)}`}function BZ(e){const t=bI(LZ(e));if(!t)return"";const a=xI(e),o=r("进入「{phase}」阶段已持续 {time}",{phase:a,time:t});return`${Cx(t)}`}const Z0=[{key:"time",label:r("时间"),sel:".req-time",track:"92px"},{key:"target",label:r("提供商 / 账号"),sel:".req-target",track:"minmax(0, 1.1fr)"},{key:"retry",label:r("重试"),sel:".req-retry",track:"52px"},{key:"status",label:r("状态"),sel:".req-status",track:"96px"},{key:"model",label:r("模型"),sel:".req-model",track:"minmax(0, 1.3fr)"},{key:"client",label:r("客户端"),sel:".req-client",track:"110px"},{key:"dur",label:r("用时"),sel:".req-dur",track:"96px",align:"right"},{key:"usage",label:r("用量"),sel:".req-usage",track:"minmax(0, 1.6fr)"},{key:"error",label:r("错误"),sel:".req-error-cell",track:"minmax(0, 1.2fr)"},{key:"detail",label:r("详情"),sel:".req-detail",track:"60px",align:"right"}],vI=1e3,HZ=fg;function yI(e){return typeof e=="number"&&e>0?e:bu}const jI="workbuddy-desktop-logs-requests-range",wI="workbuddy-desktop-requests-filters",UZ=3e4,W0=["today","7","30","month","all"],J0="all",VZ={today:r("今天"),7:r("近 7 天"),30:r("近 30 天"),month:r("本月"),all:r("全部")},FZ={today:r("今天"),7:r("7 天"),30:r("30 天"),month:r("本月"),all:r("全部")},$Z=W0.map(e=>({value:e,label:FZ[e]})),SI=[{value:"",label:r("全部状态")},{value:"ok",label:r("成功")},{value:"error",label:r("失败")}],qZ=r("全部状态"),NI=r("全部提供商"),kI=r("全部模型"),Ex={status:"",provider:"",model:""};function Ax(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function GZ(e){const t=new Date;switch(e){case"today":return Ax(t);case"7":return Ax(new Date(t.getFullYear(),t.getMonth(),t.getDate()-6));case"30":return Ax(new Date(t.getFullYear(),t.getMonth(),t.getDate()-29));case"month":return Ax(new Date(t.getFullYear(),t.getMonth(),1));default:return null}}const sn={filters:{...Ex},range:KZ(),runningOnly:!1,offset:0,size:yI(mg("requests",fg))};let Rx={...Ex},eS=!1,CI=!1,tS=[],Ox=vI,Mx=!0,nS=!1,sS=!1,TI=0,rS=0,aS=null,EI=!1,Ju=null;function KZ(){try{const e=localStorage.getItem(jI);return e!==null&&W0.includes(e)?e:J0}catch{return J0}}function YZ(e){try{localStorage.setItem(jI,e)}catch{}}function AI(){const e=As().wbFilterMemory;return e?(eS=!0,Rx=e.load(wI,{...Ex}),sn.filters={...Rx},{...Rx}):{...Ex}}function XZ(e){Rx={...e},As().wbFilterMemory?.save(wI,{status:e.status||"",provider:e.provider||"",model:e.model||""})}function RI(){const e=new URLSearchParams,t=GZ(sn.range);t!==null&&e.set("start",String(t));const a=sn.runningOnly?"running":sn.filters.status;return a&&e.set("status",a),sn.filters.provider&&e.set("provider",sn.filters.provider),sn.filters.model&&e.set("model",sn.filters.model),e}function QZ(){const e=RI();return e.set("offset",String(sn.offset)),e.set("limit",String(sn.size)),e.toString()}function lS(e){const t=Math.round(Number(e)||0);if(t<1e3)return`${t}ms`;const a=Math.floor(t/1e3);if(a>=60)return r("{m}分{s}秒",{m:Math.floor(a/60),s:a%60});const o=t%1e3;return o>0?r("{s}秒{ms}ms",{s:a,ms:o}):r("{n}秒",{n:a})}const ZZ=r("生成速度:输出 token ÷ 流式段用时(总用时 − 首响);流式段不足总用时一半时按总用时计"),WZ=500;function JZ(e){const t=Number(e.completionTokens)||0,a=Number(e.durationMs)||0;if(t<=0||a<=0)return"";const o=Number(e.firstResponseMs),c=Number.isFinite(o)&&o>0&&o=WZ&&c*2>=a,f=t/((d?c:a)/1e3);return`${f>=100?Math.round(f):f.toFixed(1)} tok/s`}function eW(e){const t=Number(e);return!Number.isFinite(t)||t<=0?"-":lS(t)}function Dx(e){return As().wbUnits?.formatTokens?.(e)??(Number(e)||0).toLocaleString("zh-CN")}function tW(e){const t=Math.max(0,Date.now()-(Number(e)||0));return r("{n}秒",{n:Math.max(1,Math.floor(t/1e3))})}function nW(e){const t=Number(e.promptTokens)||0;return t<=0?"-":`${((Number(e.cacheReadTokens)||0)/t*100).toFixed(2)}%`}function oS(e){const t=Number(e.status)||0;return t>=200&&t<300&&!e.error}function Rp(e){return(Number(e?.status)||0)===0&&!e?.error}const OI=e=>String(e?.id||e?.ts||"");function sW(e){return(Array.isArray(e?.attemptDetails)?e.attemptDetails:[]).reduce((a,o)=>{const c=o?.retries;return a+(Array.isArray(c)?c.length:0)},0)}function MI(e){return r(As().wbProviders?.labelOf?.(e)||e)}function rW(e){const t=new Set;return e.map((a,o)=>{const c=OI(a)||`i${o}`;let d=c,f=1;for(;t.has(d);)d=`${c}#${f++}`;return t.add(d),d})}async function DI(){if(!(Date.now()-rS({value:String(o?.id||""),label:r(String(o?.label||o?.id||""))})).filter(o=>o.value),a=(Array.isArray(e?.models)?e.models:[]).map(o=>String(o||"")).filter(Boolean);Ju?.setFilterOptions(t,a)}catch(e){console.warn("读取请求日志筛选清单失败,筛选项退化为「全部」:",X0(e))}}}async function aW(){if(!nS)try{const e=await As().workbuddyDesktop?.getScheduledTasks(),t=(e?.tasks||[]).find(a=>a.id==="requestsAutoRefresh");iS(t||null),nS=Array.isArray(e?.tasks)}catch(e){console.warn("读取请求日志自动刷新间隔失败,按默认 1 秒:",X0(e)),iS(null)}}function iS(e){nS=!0;const t=Number(e?.interval),a=e?.unit;!!e&&typeof e=="object"&&Number.isFinite(t)&&t>0&&(a==="seconds"||a==="minutes")?(Mx=e.enabled!==!1,Ox=a==="minutes"?t*6e4:t*1e3):(Mx=!0,Ox=vI),Ju?.setAuto({ms:Ox,enabled:Mx})}function lW(){if(EI)return;const e=As().wbColSettings;e&&(EI=!0,aS=e.register({id:"requests",label:r("请求日志表"),columns:Z0.map(({key:t,label:a,align:o})=>({key:t,label:a,align:o})),mount:()=>document.querySelector('.page[data-page="requests"] .panel-head .head-actions'),onChange:()=>{Ts.flushSync(()=>Ju?.repaint()),As().wbTableColumns?.repaint?.("requests")}}))}function cS(){return(aS?aS.apply(Z0):Z0).map(t=>({...t,align:t.align||"left"}))}const oW={entries:[],total:0,matched:0,running:0,loaded:!1,error:""};function iW(e){return e.loaded?e.total?r("没有符合筛选条件的请求"):r("暂无请求日志,网关还没有转发过请求"):r("正在加载请求日志…")}function cW(e){const t=Number(e.firstResponseMs);return!Number.isFinite(t)||t<=0?null:s.jsx("span",{className:"req-dur-line sub",title:r("首响:上游首帧到达的耗时(请求仍在转发中)"),children:r("首响 {time}",{time:lS(t)})})}function uW(e,t){const{align:a,key:o}=t,c=t.sel.slice(1)+(o==="dur"?" req-num":""),d=`${c} ta-${a}`;switch(o){case"time":{if(!e.ts)return s.jsx("span",{className:d,children:"—"},o);const f=new Date(e.ts),p=h=>String(h).padStart(2,"0");return s.jsxs("span",{className:d,children:[s.jsx("span",{children:`${f.getFullYear()}-${p(f.getMonth()+1)}-${p(f.getDate())}`}),s.jsx("span",{children:`${p(f.getHours())}:${p(f.getMinutes())}:${p(f.getSeconds())}`})]},o)}case"target":{const f=String(e.provider??"").trim(),p=String(e.providerLabel??"").trim(),h=p?r(p):f?MI(f):"";return s.jsxs("span",{className:d,children:[h?s.jsx("span",{className:"req-provider",title:f&&f!==h?r("{name}({id})",{name:h,id:f}):h,children:h}):s.jsx("span",{className:"req-provider is-empty",title:r("这条明细没有记录提供商(旧数据或请求未走到转发)"),children:"—"}),e.accountName?s.jsx("span",{className:"req-acct",title:e.accountId||e.accountName,children:e.accountName}):s.jsx("span",{className:"req-acct is-empty",title:r("请求在任何账号接手之前就失败了"),children:"—"})]},o)}case"retry":{const f=Number(e.attempts)||1,p=OI(e),h=[];if(e.isTest&&h.push(s.jsx(ze,{variant:"brand",shape:"tag",title:r("这条明细是一次模型测试(人工发起):走的是真实转发链路,但不计入报表统计"),children:r("测试")},"test")),As().wbRequestHover?.hasProcessFacts?.(e)??f>1){const y=f>1?f:sW(e);h.push(s.jsx(ze,{variant:"warning",shape:"tag",render:s.jsx("button",{type:"button"}),className:"req-hover-tag","data-req-hover":"chain","data-req-id":p,children:y>1?r("重试 {n}",{n:y}):r("重试")},"chain"))}return Array.isArray(e.sensitiveHits)&&e.sensitiveHits.length&&h.push(s.jsx(ze,{variant:"sensitive",shape:"tag",render:s.jsx("button",{type:"button"}),className:"req-hover-tag","data-req-hover":"sensitive","data-req-id":p,"aria-label":r("命中了敏感词"),children:r("敏")},"sensitive")),h.length?s.jsx("span",{className:d,children:h},o):s.jsx("span",{className:`req-none ta-${a}`,children:"-"},o)}case"status":{if(Rp(e)){const b=window.wbRequestPhase;if(!b?.badgeHtml)return s.jsx("span",{className:d,children:s.jsx("span",{className:"req-status-badge",children:s.jsxs(ze,{shape:"tag",variant:"info",title:r("请求正在转发中,用时列显示的是已用时"),children:[s.jsx(my,{className:"req-live-dot","aria-hidden":"true"}),r("进行中")]})})},o);const y=b.elapsedLineHtml?.(e)??"";return s.jsxs("span",{className:d,children:[s.jsx("span",{className:"req-status-badge",dangerouslySetInnerHTML:{__html:b.badgeHtml(e)}}),y?s.jsx("span",{className:"req-status-line",dangerouslySetInnerHTML:{__html:y}}):null]},o)}const f=Number(e.status)||0,p=oS(e),h=!p&&f>=200&&f<300?r("HTTP {status},但响应体阶段出错:见错误列",{status:f}):void 0;return s.jsx("span",{className:d,children:s.jsx(ze,{shape:"tag",variant:p?"success":"destructive",title:h,children:f||r("失败")})},o)}case"model":{const f=String(e.clientModel??"").trim(),p=String(e.upstreamModel??"").trim(),h=String(e.model??"").trim(),b=String(e.clientReasoning??"").trim(),y=String(e.upstreamReasoning??"").trim(),v=(k,S)=>S?`${k}(${S})`:k;if(!f||!p||p.toLowerCase()===f.toLowerCase()){const k=v(h,y||b);return s.jsx("span",{className:d,title:k,children:k||"—"},o)}const j=v(p,y),w=v(f,b);return s.jsxs("span",{className:`${d} req-model-split`,children:[s.jsxs("span",{className:"req-model-line",title:r("转发到上游的模型:{model}",{model:j}),children:["⬆️ ",j]}),s.jsxs("span",{className:"req-model-line sub",title:r("下游请求的模型:{model}",{model:w}),children:["⬇️ ",w]})]},o)}case"client":{const f=String(e.client??"").trim();if(!f)return s.jsx("span",{className:`${d} is-empty`,title:r("这条明细没有记录来源客户端(旧数据、模型测试,或请求未带 User-Agent)"),children:"—"},o);const p=f==="other"?r("其它"):f;return s.jsx("span",{className:d,title:f==="other"?r("识别到 User-Agent,但不属于已知的客户端类型:{ua}",{ua:f}):r("来源客户端:{client}",{client:p}),children:p},o)}case"dur":return Rp(e)?s.jsxs("span",{className:d,children:[s.jsx("span",{className:"req-dur-line",title:r("已用时(请求仍在转发中)"),children:tW(e.ts)}),cW(e)]},o):s.jsxs("span",{className:d,children:[s.jsx("span",{className:"req-dur-line",children:lS(e.durationMs)}),s.jsx("span",{className:"req-dur-line sub",title:r("首响:上游首帧到达的耗时"),children:r("首响 {time}",{time:eW(e.firstResponseMs)})})]},o);case"usage":{if(Rp(e))return s.jsx("span",{className:d},o);if(!oS(e))return s.jsxs("span",{className:d,title:r("失败请求不记录用量"),children:[s.jsx("span",{className:"req-usage-line",children:"in: - / out: - / all: -"}),s.jsx("span",{className:"req-usage-line sub",children:r("缓存读取: - / 命中率: -")})]},o);const f=`in: ${Dx(e.promptTokens)} / out: ${Dx(e.completionTokens)} / all: ${Dx(e.totalTokens)}`,p=r("缓存读取: {cache} / 命中率: {rate}",{cache:Dx(e.cacheReadTokens),rate:nW(e)}),h=JZ(e),b=h?`${p} · ${h}`:p;return s.jsxs("span",{className:d,title:[f,b].filter(Boolean).join(` +`),children:[s.jsx("span",{className:"req-usage-line",children:f}),s.jsxs("span",{className:"req-usage-line sub",children:[p,h?s.jsxs("span",{title:ZZ,children:[" · ",h]}):null]})]},o)}case"error":return Rp(e)?s.jsx("span",{className:d},o):e.error?s.jsx("span",{className:d,title:String(e.error),children:String(e.error)},o):s.jsx("span",{className:`req-none ${c} ta-${a}`,children:"-"},o);case"detail":{const f=e.id?String(e.id):"";return f?s.jsx("span",{className:d,children:s.jsx(ne,{size:"sm",variant:"outline",className:"req-detail-btn",title:r("查看该请求的上游原始报文"),onClick:()=>{As().wbRequestDetail?.open?.(f,e)},children:r("详情")})},o):s.jsx("span",{className:`req-none ${c} ta-${a}`,children:"-"},o)}default:return null}}function dW(e){return s.jsx("div",{className:"req-head",children:e.map(t=>s.jsx("span",{"data-col":t.key,className:`${t.sel.slice(1)}${t.key==="dur"?" req-num":""} ta-${t.align}`,children:t.label},t.key))},"__head")}function fW(){const[e,t]=x.useState(oW),[a,o]=x.useState(()=>AI()),[c,d]=x.useState(()=>sn.range),[f,p]=x.useState(!1),[h,b]=x.useState(0),[y,v]=x.useState(()=>sn.size),[j,w]=x.useState(()=>({ms:Ox,enabled:Mx})),[k,S]=x.useState([]),[N,R]=x.useState([]),[,P]=x.useState(0),T=x.useRef(null),C=x.useRef(null),E=x.useRef(!1),D=x.useCallback(ee=>(sn.filters={...sn.filters,...ee},o({...sn.filters}),sn.filters),[]),I=x.useCallback(ee=>{sn.range=ee,d(ee)},[]),O=x.useCallback(ee=>{sn.offset=ee,b(ee)},[]),_=x.useCallback(ee=>{sn.runningOnly=ee,p(ee)},[]),z=x.useCallback(()=>{eS||!As().wbFilterMemory||(eS=!0,!CI&&D(AI()))},[D]),H=x.useCallback((ee,he)=>{As().wbRequestHover?.beforeListRedraw?.(),he&&(tS=he),E.current=!0,t(ee)},[]),B=x.useCallback(ee=>{As().wbRequestHover?.beforeListRedraw?.(),E.current=!0,t(he=>({...he,error:ee}))},[]),L=x.useCallback(async(ee={})=>{const{silent:he=!1,resetPage:te=!1}=ee;te&&O(0),aW(),z(),he||DI();const ke=++TI;try{const le=As().workbuddyDesktop;if(!le)throw new Error(r("后端桥不可用"));const de=await le.getStatsRequests(QZ());if(ke!==TI)return;const Se={entries:Array.isArray(de?.entries)?de.entries:[],total:Number(de?.total)||0,matched:Number(de?.matched)||0,running:Number(de?.running)||0,loaded:!0,error:""},Te=Math.max(0,(Math.ceil(Se.matched/sn.size)-1)*sn.size);if(sn.offset>Te)return O(Te),L({silent:he});te&&(C.current=0),H(Se,Se.entries)}catch(le){he||(console.warn("读取请求日志失败:",X0(le)),B(r("读取请求日志失败,详见控制台")))}},[O,H,B,z]);x.useEffect(()=>(Ju={load:L,setAuto:ee=>w(ee),setFilterOptions:(ee,he)=>{S(ee),R(he)},repaint:()=>P(ee=>ee+1)},As().wbRequestHover?.bind?.({host:T.current,entryOf:ee=>{const he=ee?.dataset?.reqId||"";return he&&(tS.find(te=>String(te?.id||"")===he)||tS.find(te=>String(te?.ts||"")===he))||null}}),L({silent:!0}),DI(),()=>{Ju=null}),[L]),x.useLayoutEffect(()=>{lW(),P(ee=>ee+1)},[]);const F=e.error||!e.entries.length?"":cS().map(ee=>ee.key).join("|");x.useLayoutEffect(()=>{F&&As().wbTableColumns?.repaint?.("requests")},[F]),x.useEffect(()=>{if(!j.enabled||j.ms<=0)return;const ee=window.setInterval(()=>{document.hidden||As().wbApp?.currentPage!=="requests"||sS||(sS=!0,L({silent:!0}).finally(()=>{sS=!1}))},j.ms);return()=>{window.clearInterval(ee)}},[j,L]),x.useLayoutEffect(()=>{E.current&&(E.current=!1,As().wbRequestHover?.afterListRedraw?.());const ee=C.current;if(ee===null)return;C.current=null;const he=T.current;he&&(he.scrollTop=ee)});function $(ee){const he=Math.max(1,Math.ceil(e.matched/sn.size)),ke=(Math.min(Math.max(1,ee),he)-1)*sn.size;ke!==sn.offset&&(O(ke),C.current=0,L())}function X(ee){const he=yI(ee);if(he===sn.size)return;sn.size=he,v(he),hg("requests",he);const te=sn.offset+1;O(Math.max(0,Math.floor((te-1)/he)*he)),C.current=0,L()}function K(ee){CI=!0,XZ(D(ee)),L({resetPage:!0})}function q(ee){const he=W0.includes(ee)?ee:J0;he!==sn.range&&(I(he),YZ(he),L({resetPage:!0}))}function Q(ee){ee!==sn.runningOnly&&(_(ee),L({resetPage:!0}))}const G=cS(),J=Math.max(1,Math.ceil(e.matched/sn.size)),Y=Math.min(J,Math.floor(h/sn.size)+1),re=e.matched?h+1:0,M=e.matched?h+e.entries.length:0,U=e.error?"—":e.matched===e.total?r("{n} 条",{n:e.total}):r("{matched} / {total} 条",{matched:e.matched,total:e.total}),Z=!f&&e.running>0?r(" · {n} 进行中",{n:e.running}):"",ae=[VZ[c]||r("全部")];f?ae.push(r("只看进行中")):a.status==="ok"?ae.push(r("只看成功")):a.status==="error"&&ae.push(r("只看失败")),a.provider&&ae.push(MI(a.provider)),a.model&&ae.push(a.model);const ce=x.useMemo(()=>!a.provider||k.some(ee=>ee.value===a.provider)?k:[{value:a.provider,label:a.provider},...k],[a.provider,k]),W=x.useMemo(()=>!a.model||N.includes(a.model)?N:[a.model,...N],[a.model,N]),ue=rW(e.entries),ve=e.entries.map((ee,he)=>s.jsx("div",{className:`req-row${Rp(ee)?" running":oS(ee)?"":" failed"}`,children:G.map(te=>uW(ee,te))},ue[he]));return s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("请求日志列表")}),s.jsx(ze,{id:"req-badge",variant:"outline","data-tone":"",children:U+Z}),s.jsx("span",{className:"panel-sub",children:r("按时间倒序,全量保留")}),s.jsx("div",{className:"head-actions",children:s.jsx(ne,{id:"btn-req-clear",variant:"destructive",onClick:()=>{As().wbRequestClearModal?.open?.()},children:r("清理")})})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"log-filters",children:[s.jsx(En,{options:$Z,value:c,onValueChange:q,"aria-label":r("请求日志时间范围"),className:"shrink-0"}),s.jsxs(dt,{value:a.status,disabled:f,onValueChange:ee=>K({status:String(ee??"")}),children:[s.jsx(pt,{id:"req-status",className:"min-w-[120px]",title:r(f?"「仅看进行中」开启时,状态固定为进行中":"按请求结果筛选"),"aria-label":r("按请求结果筛选"),children:s.jsx(ft,{children:SI.find(ee=>ee.value===a.status)?.label??qZ})}),s.jsx(mt,{children:SI.map(ee=>s.jsx($e,{value:ee.value,children:ee.label},ee.value))})]}),s.jsxs(dt,{value:a.provider,onValueChange:ee=>K({provider:String(ee??"")}),children:[s.jsx(pt,{id:"req-provider",className:"min-w-[120px]",title:r("按提供商筛选(只列日志里出现过的)"),"aria-label":r("按提供商筛选"),children:s.jsx(ft,{children:a.provider?ce.find(ee=>ee.value===a.provider)?.label||a.provider:NI})}),s.jsxs(mt,{children:[s.jsx($e,{value:"",children:NI}),ce.map(ee=>s.jsx($e,{value:ee.value,children:ee.label},ee.value))]})]}),s.jsxs(dt,{value:a.model,onValueChange:ee=>K({model:String(ee??"")}),children:[s.jsx(pt,{id:"req-model",className:"min-w-[120px]",title:r("按模型筛选(只列日志里出现过的;精确匹配模型名)"),"aria-label":r("按模型筛选"),children:s.jsx(ft,{children:a.model||kI})}),s.jsxs(mt,{children:[s.jsx($e,{value:"",children:kI}),W.map(ee=>s.jsx($e,{value:ee,children:ee},ee))]})]}),s.jsx(qF,{id:"btn-req-running",variant:"outline",size:"default",pressed:f,onPressedChange:Q,title:r("只显示正在转发中的请求(状态列按阶段显示:连接中 / 等待响应 / 响应中 / 重试中,用时列显示已用时)"),children:r("仅看进行中")}),s.jsx("div",{className:"spacer"}),s.jsx("span",{className:"panel-sub",id:"req-summary",children:ae.join(" · ")})]}),s.jsx("div",{className:"log-list",id:"req-list",ref:T,children:e.error?s.jsx("div",{className:"log-empty",children:e.error}):e.entries.length?[dW(G),...ve]:s.jsx("div",{className:"log-empty",children:iW(e)})})]}),s.jsx($i,{total:e.matched,range:{start:re,end:M},page:Y,pageCount:J,size:y,sizes:HZ,onSizeChange:X,onPageChange:$,disabled:!e.loaded&&!e.error})]})}async function II(e={}){await Ju?.load(e)}function pW(){return RI().toString()}function mW(){return rS=0,II({resetPage:!0})}const PI='.page[data-page="requests"]';let _I=!1;function LI(){if(_I)return;const e=document.querySelector(PI);e&&(_I=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(fW,{})))}document.querySelector(PI)?LI():document.addEventListener("DOMContentLoaded",LI,{once:!0}),window.wbRequestsPanel={load:II,applyAutoRefresh:iS,visibleColumns:cS,clearParams:pW,notifyCleared:mW},window.wbRequestPhase={labelOf:xI,badgeHtml:zZ,elapsedLineHtml:BZ,elapsedText:bI,phaseOf:Q0};function hW(e){if(e.status==="loading")return kt.appLoading;if(e.status==="unavailable")return kt.modelsDevUnavailable;const t=e.source==="builtin"?kt.modelsDevSourceBuiltin:e.source==="cache"?kt.modelsDevSourceCache:e.source==="network"?kt.modelsDevSourceNetwork:e.source,a=e.updatedAt>0?String(tt().wbApp?.formatTime?.(e.updatedAt)??""):"";if(!t&&!a&&!e.count)return kt.modelsDevEmpty;const o=a?r(",{time}",{time:a}):"",c=e.enabled?r("正在联网更新"):r("仅用现有数据、不联网刷新");return r("{count} 条 · 来自{origin}{at} · {mode}",{count:Number(e.count).toLocaleString("zh-CN"),origin:t||r("未知来源"),at:o,mode:c})}function tt(){return window}function Ot(e){return e instanceof Error?e.message:String(e)}function Ve(e,t){tt().wbApp?.toast?.(e,t)}async function gW(e){try{await tt().workbuddyDesktop?.openReleasePage?.(e)}catch(t){Ve(r("打开链接失败:{error}",{error:Ot(t)}),"err")}}const Ix=[{id:"general",label:r("通用"),icon:"sliders"},{id:"assistant",label:r("AI 助手"),icon:"spark"},{id:"display",label:r("显示"),icon:"display"},{id:"gateway",label:r("网关"),icon:"traffic"},{id:"routing",label:r("路由"),icon:"route"},{id:"retry",label:r("重试"),icon:"refresh"},{id:"timeout",label:r("超时"),icon:"timer"},{id:"security",label:r("安全"),icon:"shield"},{id:"data",label:r("数据"),icon:"database"},{id:"feedback",label:r("反馈与需求"),icon:"feedback"},{id:"about",label:r("更新"),icon:"download"}],zI="workbuddy-desktop-settings-cat",xW="workbuddy-desktop-theme",bW="workbuddy-desktop-zoom",BI="wb:theme",HI="wb:zoom",uS=80,UI=130,Px=5,vW=Array.from({length:(UI-uS)/Px+1},(e,t)=>uS+t*Px),yW=[{value:"system",label:r("跟随系统")},{value:"light",label:r("浅色")},{value:"dark",label:r("深色")}];function jW(){try{const e=localStorage.getItem(xW);return e==="light"||e==="dark"?e:"system"}catch{return"system"}}function wW(){try{const e=localStorage.getItem(bW);if(e===null||e.trim()==="")return 100;const t=Number(e);if(!Number.isFinite(t))return 100;const a=Math.round(t/Px)*Px;return Math.min(UI,Math.max(uS,a))}catch{return 100}}const dS=1,fS=99999,pS=[{key:"logRetentionDays",id:"settings-retention-log",label:r("事件日志保留天数"),unit:r("天"),min:dS,max:fS,hint:r("登录 / 账号切换 / 429 切换等系统事件,可填 1–99999 天。")},{key:"requestLogRetentionDays",id:"settings-retention-request",label:r("请求日志保留天数"),unit:r("天"),min:dS,max:fS,hint:r("「请求日志」页的逐条请求记录,默认 99999 天(近似全量保留),可填 1–99999 天。")},{key:"dailyAggregateRetentionDays",id:"settings-retention-daily",label:r("按天聚合保留天数"),unit:r("天"),min:dS,max:fS,hint:r("报表页的热力图与按天趋势,默认 99999 天(近似全量保留),可填 1–99999 天。")}],VI=[{key:"retryCount",id:"settings-retry-count",label:r("同一账号重试次数"),unit:r("次"),min:0,max:10,hint:r("在同一个账号上原地重发几次(不含首发;整条请求共用一份,用完后换来的账号只发一次就继续换)。可填 0–10,0 表示失败立即换号。")},{key:"retryCrossProviderCount",id:"settings-retry-cross-provider-count",label:r("切换账号重试次数"),unit:r("次"),min:0,max:10,hint:r("失败后最多再换几个账号试(填 N = 最多换 N 个,首发那个不算)。换到同一家名下另一个账号、或换到另一家,都各算一次;换满仍失败就返回错误。可填 0–10,0 表示失败立即报错。")},{key:"retryIntervalSeconds",id:"settings-retry-interval",label:r("重试间隔"),unit:r("秒"),min:0,max:300,hint:r("两次重试之间的等待时间,两项共用,可填 0–300 秒。")}],FI=[{key:"connectTimeoutSeconds",id:"settings-timeout-connect",label:r("连接中超时"),unit:r("秒"),min:1,max:3600,hint:r("建立上游 TCP/TLS 连接或代理隧道的最大等待时间(秒),默认 30 秒,范围 1~3600。")},{key:"headersTimeoutSeconds",id:"settings-timeout-headers",label:r("等待响应超时"),unit:r("秒"),min:1,max:3600,hint:r("请求发出后等待上游响应头的最大时间(秒),默认 300 秒,范围 1~3600。")},{key:"streamIdleTimeoutSeconds",id:"settings-timeout-stream-idle",label:r("流式响应空闲超时"),unit:r("秒"),min:1,max:3600,hint:r("流式响应相邻数据之间允许的最大空闲时间(秒),收到新数据后重新计时,默认 300 秒,范围 1~3600。")},{key:"bodyTimeoutSeconds",id:"settings-timeout-body",label:r("非流式响应超时"),unit:r("秒"),min:1,max:3600,hint:r("读取完整非流式响应体允许的最大时间(秒),默认 300 秒,范围 1~3600。")}],$I=[{key:"queueMaxWaits",id:"settings-queue-max-waits",label:r("排队等待次数"),unit:r("次"),min:0,max:10,hint:r("上游模型繁忙时会先排队(回一句「建议 N 秒后再来」,Qoder 免费模型就是这样):网关等一会儿再发同一请求,最多等几次。默认 2 次,可填 0–10;填 0 表示不等待,排队直接返回 503 并说明「不是登录态或额度问题」。")},{key:"queueWaitSeconds",id:"settings-queue-wait-seconds",label:r("排队等待秒数"),unit:r("秒"),min:0,max:120,hint:r("每次等待的时长,默认 0 = 跟随上游建议(实测 9~30 秒,上游没给建议时用 15 秒)。可填 0–120 秒强制一个固定时长。")}],qI="noRetryStatusCodes",mS=100,hS=599,GI=50,$o=[{value:"passthrough",optionLabel:r("透传客户端 system(默认)"),toastLabel:r("透传客户端 system")},{value:"custom",optionLabel:r("替换为网关提示词"),toastLabel:r("替换为网关提示词")},{value:"append",optionLabel:r("追加网关提示词"),toastLabel:r("追加网关提示词")}];function KI(e,t,a,o){const c=String(e??"").trim();if(!c)return{ok:!1,message:r("{noun}不能为空(可填 {min}–{max})",{noun:o,min:t,max:a})};if(!/^\d+$/.test(c))return{ok:!1,message:r("{noun}必须是整数",{noun:o})};const d=Number(c);return da?{ok:!1,message:r("{noun}必须在 {min}–{max} 之间(当前填的是 {text})",{noun:o,min:t,max:a,text:c})}:{ok:!0,value:d}}function SW(e,t){const a={...t};if(e&&typeof e=="object"){const o=e;typeof o.closeToTray=="boolean"&&(a.closeToTray=o.closeToTray),typeof o.autostart=="boolean"&&(a.autostart=o.autostart),typeof o.lanAccess=="boolean"&&(a.lanAccess=o.lanAccess),typeof o.lanPanel=="boolean"&&(a.lanPanel=o.lanPanel),typeof o.lightweightMode=="boolean"&&(a.lightweightMode=o.lightweightMode)}return a}function YI(e,t,a){if(!t||typeof t!="object")return null;const o=t,c={...a||{}};for(const d of e){const f=Number(o[d.key]);Number.isInteger(f)&&f>=d.min&&f<=d.max&&(c[d.key]=f)}return e.some(d=>Number.isInteger(c[d.key]))?c:null}function XI(e){if(!Number.isFinite(e)||e<=0)return"0 B";if(e<1024)return`${e} B`;const t=e/1024;if(t<1024)return`${t.toFixed(1)} KB`;const a=t/1024;return a<1024?`${a.toFixed(1)} MB`:`${(a/1024).toFixed(2)} GB`}function NW(e){const t=Number(e);return!Number.isFinite(t)||t<0?"—":t.toLocaleString("zh-CN")}const Jn={displayTheme:r("控制界面的深浅色,与左侧边栏底部的三个主题按钮是同一个设置(改哪一处,另一处立刻跟上)。「跟随系统」会随操作系统当前的浅色 / 深色自动切换,并在系统主题变化时即时跟上;选「浅色」或「深色」则把界面固定在该模式,不再随系统变化。窗口标题栏的深浅色会一并同步,不会出现深色界面配一条浅色标题栏的情况。"),displayZoom:r("等比放大或缩小整个界面(文字、控件、间距一起变),效果与浏览器按 Ctrl +/- 相同:80%–130%、5% 一档。窗口本身不缩放,变的是页面内容的显示比例,设置立即生效并记住,下次启动直接按这个比例打开。放得越大可视范围越小,窗口较窄或表格较宽时不建议调得太大。"),displayLanguage:r("界面语言。可选简体中文、繁體中文、English、日本語、한국어、Português (Brasil),或「跟随系统」(按浏览器 / 系统的语言列表自动选)。切换后整页立即刷新;该偏好只存在本机(localStorage),不影响账号、密钥与转发。"),tray:r("默认关闭窗口不会退出程序,而是把窗口缩到系统托盘,转发继续在后台运行(OpenAI 客户端不受影响);要彻底退出程序,请在托盘图标上右键选「退出」。关掉这个开关后,点关闭按钮即退出程序、转发随之中断。「开机自动启动」开启后,登录系统时会自动启动本程序(通常直接驻留托盘),不需要手动打开。"),lightweight:r("开启后,关闭窗口不只是隐藏,而是把界面窗口整个销毁:底层的 WebView2 六个常驻进程(约 200MB 内存)随之退出,网关转发、定时签到、余额查询都在后台进程里继续,不受影响;需要界面时点托盘图标重新打开(WebView 冷启动约 1 秒)。注意:界面销毁期间「ZCode 套餐池(Start Plan)」通道的验证码令牌由界面铸造,无法补充 —— 走该通道的请求会以 503 落进请求日志(写明原因),重新打开界面即自动恢复。此开关只在「关闭窗口时最小化到托盘」开启时有意义,最小化窗口不受影响。"),lan:r("默认网关只监听 127.0.0.1,只有本机能访问。开启后网关改听所有网卡,同一局域网内的设备可以把 API 地址指向本机 IP 一起使用。出于安全考虑,开启前必须先注册一个面板管理员:管理接口从此要求管理员会话或网关 Key,模型额度不会对局域网裸奔;一把启用的网关 Key 都没有时,转发接口也会拒绝服务,直到创建第一把。改动需要重启应用生效。「同时开放网页管理面板」把管理界面也出给局域网(其他设备的浏览器打开本机 IP 即可管理),默认关闭 —— 桌面端的面板仍只由本程序自己出。"),units:r("控制报表与请求日志里 Token 读数的写法:开启后按中文量级显示(1.2亿 / 8400万),关闭则用 k / M 缩写(与上游文档、接口字段的写法一致)。这只影响显示口径,不改变任何统计与存储的数值。"),queue:r("只对「排队制」的上游生效(目前是 Qoder 的免费模型):模型繁忙时上游不报错,只回一句「建议 N 秒后再来」(业务码 10605),网关按建议时长等一会儿再发同一请求,等满次数仍排不上才把「排队中」作为错误返回(HTTP 503,文案会说明这不是登录态或额度问题)。等待发生在首个字节之前,吃的是「等待响应超时」那份预算 —— 两项设置一起决定一次请求最多卡多久;排队不会标记账号限额、也不会换账号(换谁都一样在排队)。保存后对下一个请求立即生效,不用重启。"),captchaPool:r("ZCode「套餐池(Start Plan)」通道的每条推理请求都要附一个当次铸造的阿里云无痕验证令牌(一次性、约 2 分钟过期):令牌由界面里的铸造守卫静默铸好、推给网关入池,转发时逐条取用。这里的三个值管的是补货节奏:①「库存目标」= 库存低于它守卫才补铸、补到它为止,默认 3 个;②「轮询间隔」= 守卫多久看一次库存,默认 2500 毫秒,只影响反应速度(库存够用时不会多铸);③「单轮铸造上限」= 发现缺货时一轮最多铸几个,默认 1 个(连铸之间固定隔 500 毫秒)。请求密集、请求日志里连续出现「需要人机验证令牌」的 503 时,把目标与单轮上限适当调大、轮询调快,能让池子跟得上消耗 —— 代价是上游(阿里云)对铸造频率有风控,铸得越多越快越容易触发限流,且用不掉的令牌 2 分钟即过期作废、等于白烧配额,所以建议小步调。保存后对下一轮补货立即生效,不用重启。"),timeouts:r("上游请求四个阶段各自的等待上限(秒,1~3600):①「连接中超时」= 建立 TCP/TLS 连接或代理隧道的最大等待,默认 30 秒;②「等待响应超时」= 请求发出后等上游响应头的最大时间,默认 300 秒 —— 网关请求上游恒带 stream,响应头在 SSE 建立时就到达,与模型思考多久无关;③「流式响应空闲超时」= 流式响应相邻两块数据之间允许的最大空闲,收到新数据即重新计时,默认 300 秒 —— 上游长时间不吐数据即判定连接僵死并断开;④「非流式响应超时」= 读完整份非流式响应体的总预算(一次性计时、不重置),默认 300 秒。四项都是「等待上限」,只要数据还在来,正常的流式回答就一直往下传。保存后对下一个请求立即生效,不用重启。"),retry:r("请求转发到上游失败时(服务器瞬时错误、连接失败,以及 WorkBuddy 的 11-128 敏感词拦截),网关会等一段间隔后再发一次。次数分两档,管的是两件事:①「同一账号重试次数」在同一账号上原地重发几次 —— 一般是提示词被上游拦截、或链路瞬时抖动,等一会儿重发往往就好了;②「切换账号重试次数」这份请求最多再换几个账号试 —— 首发的那个账号不算,每换一个扣一次,不分是不是同一家(换到同一家的下一个账号也算一次),换满还失败就把错误返回给客户端。两项都设为 0 表示失败不重试、直接报错。注意账号级限额(429)不占这里的换号次数 —— 那类失败走「冷却该账号并换下一个账号」的降级,与这里的重试是两条路。另有「指定错误码直接换号」名单(默认 402):命中名单的上游状态码不在同一账号重发,直接按队列换下一个账号继续试(换号也占「切换账号重试次数」),换满仍失败才把错误返回给客户端。"),routing:r("转发一个请求时按什么顺序挑账号:①「路由策略」决定排队规则 —— 顺序优先是排第 1 的接走所有请求、直到它不能答(限流 / 故障 / 额度尽)才轮到下一位;负载均衡是每条请求换下一位,把负载摊到各个账号上。②「会话粘性」让同一会话(相同的模型 + 相同的开头消息)尽量跟住同一个账号 —— 多轮对话的上下文缓存能复用、少换号少浪费;自动档粘 5 分钟、会话内档粘 6 小时、每轮与关闭都不粘。账号的排队位次(账号表的第一列)在所有策略下都是地基,策略在它之上再排。此外路由还有三层自愈保护:转发失败的账号退避休息一会儿(15 分钟起步翻倍、封顶 1 小时)、被 429 的账号垫底排到队尾 30 分钟、余额不足 / Token 周期用量到顶的账号由限制器拦下 —— 前两层可以在下面按需开关,限制器由账号的「限制器」设置管。"),sanitize:r("上游用「逐字精确匹配」的方式审核请求体(不是语义审核):客户端注入的固定模板句、计费头字段名、以及某些裸错误码出现在报文里就会整单拦截,返回 400。开启本项后,网关在每次转发前改写这些指纹 —— 表头键值整段删除,承载语义的模板句只换一个词(如 official CLI for Claude → official CLI tool for Claude),对话内容与语义都不受影响。规则集是内置的,不需要也无法维护词表。关掉本项后客户端模板会原样发往上游,可能重新出现模板句被误拦的报错。"),developerRoleCompat:r("OpenAI 新版 API 用 developer 角色取代 system 承载指令,新版 OpenAI SDK 与部分客户端发的对话里会出现 role 为 developer 的消息;不少 OpenAI 兼容上游(尤其是自定义提供商的透传路径)不认识这个角色,收到就报 400。开启本项后,网关在每次转发前把 developer 角色的消息改写为 system —— 两类角色在 OpenAI 语义上等价(OpenAI 自己的迁移指南也是这么映射的),改写不影响对话内容与语义;对本来就只认 system 的各家内置上游同样无害。默认开启;关掉后 developer 消息会原样发往上游,不认识它的上游会报「角色不存在」一类的错误。"),clineHeaders:r("Cline 上游按请求头判定「调用方是不是 Cline 自家产品」:X-CLIENT-TYPE: cline-sdk 是硬门槛(缺了它免费池模型一律 403),版本号与平台标识让请求更贴近官方客户端的形态。这里列出的是网关默认会发的头:改某一行的值 = 覆盖默认值(也可以新增默认清单之外的自定义头);把值清空保存 = 这个头不发送;在界面删掉被改过的行 = 回落默认值。改完点「保存」,下一个 Cline 请求立即生效。不懂某一行的含义就不要动它 —— 伪装头的价值在「与官方客户端逐字一致」。"),cors:r("网关面(/v1/*)默认不应答浏览器跨源请求:页面直连会被预检拦下,只报「无法连接 API」。注意来源是 * —— 未配「网关 Key」时任何网页都能借本机网关打上游,故默认关闭;只给自己用的话,让页面与网关同源(本地反代 /v1)更稳妥。面板接口(/api/*)不受影响。"),prompt:r("客户端(Claude Code / Codex 等 CLI)会在 system 提示词里注入几十句固定模板,上游按逐字匹配审核,命中就整单拦截(HTTP 400)。指纹脱敏能改写实测命中过的那几句,但换一个客户端版本就可能冒出新的。这里可以把 system 整段换成网关自己那份:①「透传」= 不动客户端 system(默认,行为与之前完全一致);②「替换」= 删掉客户端所有 system / developer 消息,换成网关的提示词(客户端项目规范随之消失);③「追加」= 在开头连续 system 块之后插入一条网关提示词,既有消息逐字不动(客户端规范与网关提示词并用)。那份提示词有两个来源:提示词文件(留空用内置默认),或直接在界面上编辑正文 —— 编辑过就以那份正文为准(优先于文件),清空则回到文件 / 内置默认。另外,透传 / 追加模式下撞了内容拦截(多半是指纹误报)时,网关会自动换一段最小中性提示词重试一次,并把「降级期」开到次日 00:00 —— 期间所有请求直接带中性提示词出门,不再先撞一次 400;这里能看见并提前解除它。上面几项是**默认值**:想给某个提供商单独配,用下面的「按提供商」加一行(带「网关自带」的家默认就列在那里)—— 不同的上游对这些内容的接受程度不一样。"),debug:r("开启后,网关会把每次转发**发给上游的请求**(请求头 + 请求体)与**上游返回的响应**(状态码 + 响应头 + 响应体)完整保存到本地,供请求日志页的「详情」查看。请求头里的 Authorization、Cookie、API Key 等凭据字段一律替换成 [redacted],不会明文落盘;请求体与响应体按原样保存(可能包含你的对话内容)。报文只保留最近 500 条,超出后丢弃最旧的。这是排障用的临时开关,不需要时建议关闭。"),io:r("导出会把全部账号与自定义提供商定义写入一个 JSON 文件,可以拷到另一台机器上导入后继续使用。导入采用合并策略:同提供商下按业务身份(UID / userId / apiKey 等)去重 —— 已存在的账号只更新凭证,保留本机原有的优先级顺序;新账号追加到转发顺序末尾,不会抢占当前正在使用的账号;自定义提供商定义按 id 合并,本机缺失时自动补建。"),backup:r("把整份数据库(账号、网关配置、事件日志、请求统计、调试报文与桌面设置)导出成一个 SQL 文件,恢复时整体替换本机全部数据 —— 与上面「账号导入 / 导出」的逐条合并是两种语义:恢复会连配置、日志与当前启用状态一起换成备份那台机器的状态。导出默认包含日志与调试报文(文件可能很大),不需要时可以取消勾选只备业务数据。恢复前会自动把当前数据备份到配置目录的 backups/ 下,恢复后需要重新登录管理面板。"),retention:r("三档数据各自独立计时,超出保留天数的部分会被删除:事件日志是登录、账号切换、429 切换这类系统事件;请求日志是网关每次转发到上游的逐条记录;按天聚合供报表页的热力图与按天趋势使用。请求日志与按天聚合默认 99999 天(约 274 年,效果上等于全量保留),事件日志默认 30 天。把某一档改小(例如 30 天改成 7 天)保存后会立即删除超出的历史数据,此操作不可恢复;改大或保持不变不会删除任何数据。三档的可填范围均为 1–99999 天。"),storage:r("全部数据(账号、事件日志、请求记录、调试报文、设置)统一保存在配置目录下的 agent2api.db 这一个 SQLite 数据库里。备份时只需拷贝这个文件;更换保存位置请设置环境变量 AGENT2API_PROXY_HOME 后重启程序。"),modelsDev:r("models.dev 是一个开源的模型资料库(社区维护),这里用它补齐「上游没告诉我们」的模型能力:上下文窗口、最大输出、工具调用、图片、视频、是否支持思考,以及这个模型认识哪些思考档位。优先级是:你在「模型能力」里手工改的值 > 上游清单自己声明的值 > models.dev 的值 —— 它只填上游没声明的空位,从不推翻上游已声明的。网关随包内嵌了一份快照,所以离线、首次启动、访问不通时也有数据;开启时会按「模型目录刷新」任务的间隔联网更新(同一轮里一并刷新,也可在这里立即刷新)。关闭只停联网刷新,已经拿到的数据继续用。")},Un={timeouts:r("保存后立即生效,不用重启;超时按上游失败处理(计入请求日志的「错误」列,并按「请求重试」的设置决定是否重试)。"),queue:r("等待期间请求日志的状态列会显示「排队中」阶段,详情弹窗的「内部重试」里能逐次看到等待时长;等待用尽后返回 HTTP 503(不是 401/429:既不会刷新凭证,也不会把账号标成限额)。"),captchaPool:r("保存后对下一轮补货立即生效,不用重启。守卫跑在应用界面里:轻量模式关窗销毁界面期间无法铸造,走套餐池(Start Plan)通道的请求会以 503 落进请求日志(写明原因),重新打开界面即自动恢复。"),retry:r("保存后立即生效,不用重启;次数用尽仍失败时,错误原样返回给客户端。"),routing:r("保存后立即生效,不用重启:策略与粘性作用于**下一次**转发的选路,进行中的请求不受影响。"),retryCodes:r("命中这些上游状态码的失败不在同一账号重发,直接换下一个账号继续试(换号占用「切换账号重试次数」,换满仍失败才把错误原样返回给客户端)。输入 100–599 的状态码后回车添加,点 × 或退格删除;默认 402(积分不足)。清空全部表示任何错误都照常重试。"),sanitize:r("默认开启。命中明细会记进请求日志的「敏」标签(悬停可看命中了哪几条规则)。本项只改发给上游的副本,客户端看到的响应内容不变。"),developerRoleCompat:r("默认开启。只改 role 字段本身,消息内容与顺序都不动;本项只改发给上游的副本,客户端看到的响应内容不变。"),clineHeaders:r("值与默认值相同的行不占覆盖(存的是「改过的键」,不是全量配置);值留空保存表示这个头不发送,删除改过的行表示回落默认值。改完立即生效,不用重启。"),cors:r("默认关闭。改动立即生效,不用重启;关闭期间的跨源请求会被预检拦下。"),debug:r("开启后新发生的请求才会被记录(已经过去的请求补不回来)。报文统一存放在本地数据库里,只保留最近 500 条(超出后丢弃最旧的),条数见左侧「数据 → 数据存储」的「调试报文」。"),promptMode:r("替换 = 客户端 system / developer 消息全部删掉,换成网关的提示词;追加 = 保留客户端内容,只在开头 system 块之后多插一条。两者都只改发给上游的副本,客户端看到的响应不变。"),promptFile:r("UTF-8 文本文件路径,留空用内置默认提示词(通用编码助手提示词,不含任何会被上游拦截的模板句)。只在「替换 / 追加」模式下生效,透传模式不读它。"),promptText:r("在这里直接编辑提示词正文:保存后以这份文本为准(优先于上面的提示词文件),清空则回到文件 / 内置默认。改一个字不必再去编辑器里开文件。"),promptGatewayText:r("上游按「结构」校验身份:三段必须各自成块,所以这里分开编辑三段(不能合成一段)。动态段里的运行值写成占位符,发请求时才替换:{cwd} 工作目录、{platform} 平台、{shell} shell、{os_version} 系统版本、{git} 是否 git 仓库、{provider} 提供方标识、{model} 模型名。清空某一段 = 那一段恢复官方原文。第三段发出时前面会自带一个空行(官方形状)。"),prompt:r("改完立即生效,不用重启(下一个请求就用新模式)。降级是自动的临时状态,解除后本模式自己的提示词立刻恢复。"),promptProviders:r("「用哪份提示词」本来是按上游分别决定的事,所以每家可以有自己的模式、提示词文件与正文:不在这里列出的提供商一律沿用上面那份默认设置,「跟随默认」把这一家取消、回到默认。带「网关自带」那一行的家(目前是 ZCode 两家)默认就列在这里 —— 那一段是网关自己装上去的文本,不来自客户端也不来自提示词文件,默认开启、可以关掉,也可以改它的正文(改过的那一段以你的文本为准);关掉后还能不能通过上游校验,取决于上游当下的口径,行内说明了实测依据。「模式 / 提示词文件 / 正文」管的是客户端自己的 system 怎么处理,与那个开关是两件事。"),modelsDev:r("「模型管理」里每个能力的来源标记(上游 / models.dev / 已覆盖)读的就是这份数据;映射弹窗的思考档位下拉也按这里的数据只列该模型真实认识的档位。"),retention:r("保存后立即生效:改小保留天数会立刻删除超出的历史数据,且不可恢复。"),storageFile:r("配置目录下的 agent2api.db(账号、日志、请求记录、调试报文与设置都在里面)。"),storageSize:r("库主文件的大小(不含运行期间的 WAL 临时文件,退出时已自动并回)。"),storage:r("数据统一保存在配置目录下的 agent2api.db;如需更换位置,请设置环境变量 AGENT2API_PROXY_HOME 后重启程序。"),captcha:r("开启后,登录页在浏览器后台自动完成验证(对真人无感),而脚本每次尝试都要先算一道题 —— 暴力破解与抢注的成本显著上升。仅影响面板的登录 / 注册,与 API 客户端的 API Key 无关。"),panelLogin:r("当前浏览器以管理员身份登录着本面板。「退出登录」会撤销这台设备的登录会话(30 天内的自动续期一并失效),需要重新输入账号密码;其他已登录的设备不受影响。"),exportDanger:r("导出文件内含 accessToken / refreshToken / apiKey 等凭证与自定义提供商定义,可直接用于登录。请妥善保管,不要外传或上传到公共位置。"),backupDanger:r("备份文件内含全部账号凭证、网关 API Key 与面板管理员凭据,可直接用于登录。请妥善保管,不要外传或上传到公共位置。")},kt={appLoading:"—",appUnavailable:r("主进程未返回启动设置,请更新桌面端后重试"),appTrayOn:r("关闭窗口时程序不退出,转发继续在后台运行;退出请用托盘菜单"),appTrayOff:r("关闭窗口即退出程序,后台转发随之中断"),appLightOn:r("轻量模式已开启:关窗即销毁界面进程(释放约 200MB 内存),网关在后台继续;界面销毁期间 ZCode 套餐池(Start Plan)通道不可用,相关请求会在请求日志里注明原因"),appLightOff:r("未开启轻量模式:关窗仅隐藏窗口,界面进程常驻内存,随时打开不等待"),unitsOn:r("当前显示为「1.2亿 / 8400万」这类中文量级。"),unitsOff:r("当前显示为「1.20M / 8.4k」这类英文缩写。"),debugUnavailable:r("未能读取调试模式设置,请稍后重试"),debugOn:r("正在保存上游原始报文:"),debugOff:r("未开启,转发时不保存任何原始报文。"),sanitizeUnavailable:r("未能读取指纹脱敏设置,请稍后重试"),sanitizeOn:r("正在剥离出站请求里的审核指纹:表头键值整段删除,模板句最小改写。"),sanitizeOff:r("未开启,客户端 system 模板会原样发往上游,可能被内容审核误拦(400)。"),roleCompatUnavailable:r("未能读取开发者角色兼容设置,请稍后重试"),roleCompatOn:r("正在归一角色:developer 角色消息转发前改写为 system。"),roleCompatOff:r("未开启,developer 角色消息会原样发往上游,不认识该角色的上游会报错(400)。"),corsUnavailable:r("未能读取网关跨域访问设置,请稍后重试"),corsOn:r("正在应答跨源请求:浏览器跨域请求可直连 /v1/*。"),corsOff:r("未开启,浏览器跨域无法直连网关。"),modelsDevUnavailable:r("未能读取 models.dev 元数据状态,请稍后重试"),modelsDevSourceBuiltin:r("随包内嵌的快照(发版时的那份)"),modelsDevSourceCache:r("上次成功刷新的结果(存在本机数据库里)"),modelsDevSourceNetwork:r("刚刚从 models.dev 拉到的最新数据"),modelsDevEmpty:r("还没有装载任何数据。"),promptUnavailable:r("未能读取系统提示词设置,请稍后重试"),degradeUntilFallback:r("次日 00:00"),themeSystem:r("当前跟随操作系统的深浅色设置,系统切换时界面会自动跟上。"),themeLight:r("当前固定为浅色模式,不随系统变化。"),themeDark:r("当前固定为深色模式,不随系统变化。"),zoomWeb:r("网页端的界面缩放由浏览器自己控制(Ctrl + / Ctrl -,或浏览器菜单里的缩放),此项不可调。"),zoomDefault:r("当前按 100% 显示(默认比例)。"),languageHint:r("界面语言只保存在本机(localStorage)。切换后整页立即刷新,不影响账号、密钥与转发。")},_x=[{value:"order",label:r("顺序优先"),tip:r("排第 1 的接走所有请求,直到它不能答(限流 / 故障 / 额度尽)才轮到下一位 —— 就是「从上往下」的现状行为。")},{value:"rotate",label:r("负载均衡"),tip:r("每条请求轮换到下一个可用账号;新会话交给当前最闲的那位。适合想把手里的号摊开用、不让某一个一直扛。")},{value:"provider",label:r("家内轮询"),tip:r("家之间仍按优先级,只有同一家内部轮流用各账号 —— 想优先用某几家、又不愿把某一家的某个账号焊死时用它。")}],Lx=[{value:"auto",label:r("自动"),tip:r("同一会话在 5 分钟内尽量跟住同一个账号;停了 5 分钟再发就算新会话。多数场景用它 —— 多轮对话少换号,也不至于把账号焊死。")},{value:"session",label:r("会话内"),tip:r("同一会话在 6 小时内跟住同一个账号;适合一坐几个小时的长会话,上游的上下文缓存能吃到更多。")},{value:"turn",label:r("每轮"),tip:r("每条请求都重新按策略选路 —— 行为与「关闭」一致,仅保留会话识别的记录。")},{value:"off",label:r("关闭"),tip:r("不做会话识别,每条请求都重新按策略选路。")}],kW=[{key:"routingFailoverBackoff",label:r("失败退避"),defaultOn:!0,tip:r("转发失败的账号休息一会儿再回来:15 分钟起步,连续失败翻倍,封顶 1 小时;成功一次立即恢复。目的是「让这次失败先凉一会儿」,免得一条条地反复撞同一个坏账号。")},{key:"routingSink",label:r("限流垫底"),defaultOn:!0,tip:r("还有额度时被 429 的账号排到队尾,30 分钟后自动回到队列(成功转发一次也会立即回来)。它标记的是「疑似共享池被别人抢」,不是「这个账号本身有问题」。⚠️ 注意它与路由策略的配合:在「家内轮询」下,队尾意味着这一家整体被往后排 —— 如果某个提供商的账号被批量限流,它们会集体沉到队尾,那个家可能长时间轮不到。这时可以关掉本项,让 429 过的账号只受冷却约束(冷却到点自动回来)。")},{key:"routingBreakerEnabled",label:r("熔断"),defaultOn:!1,tip:r("连续失败到阈值后把这个账号整个打开(默认关)。与失败退避的分工:退避管「单次失败先凉一会儿」,惩罚轻、自动恢复;熔断管「这个账号现在整体不对劲,别再一条条地试」,要连续成功若干次才关。打开期间该账号被跳过,除非全场只剩它 —— 那时仍放行试一次。")}],QI=[{key:"zcodeCaptchaPoolTarget",id:"settings-captcha-pool-target",label:r("库存目标"),unit:r("个"),min:1,max:10,hint:r("ZCode 套餐池(Start Plan)通道每条请求都要消耗一个当次铸造的人机验证令牌(一次性,2 分钟过期),库存低于该值时界面自动补铸到它。默认 3 个。调大能吸收突发并发,但用不掉的令牌 2 分钟就过期作废,烧的是上游风控配额。可填 1–10。")},{key:"zcodeCaptchaPoolPollMs",id:"settings-captcha-pool-poll-ms",label:r("轮询间隔"),unit:r("毫秒"),min:1e3,max:3e4,hint:r("铸造守卫每隔多久看一次库存(毫秒)。只影响发现缺货的反应速度 —— 库存够用时轮询不会铸造任何令牌。默认 2500 毫秒,可填 1000–30000。")},{key:"zcodeCaptchaPoolMaxPerRound",id:"settings-captcha-pool-max-per-round",label:r("单轮铸造上限"),unit:r("个"),min:1,max:5,hint:r("发现缺货时一轮最多铸几个(连铸之间固定隔 500 毫秒)。默认 1 个:SDK 同一实例连铸容易互相干扰。调大补货更快,但单轮连铸越多越容易触发上游风控。可填 1–5。")}];function ZI(){return tt().workbuddyDesktop?.platform==="web"}let ht={...{category:Ix[0].id,scrollReset:0,busy:null,app:{status:"loading",closeToTray:!1,autostart:!1,lanAccess:!1,lanPanel:!1,lightweightMode:!1,lanIp:null,port:0,adminRegistered:null},unitsChinese:!0,retention:{status:"loading",values:null},retry:{status:"loading",values:null},retryCodes:null,timeouts:{status:"loading",values:null},queue:{status:"loading",values:null},captchaPool:{status:"loading",values:null},routing:{status:"loading",strategy:"order",sticky:"auto",failoverBackoff:!0,sink:!0,breakerEnabled:!1},debug:{status:"loading",on:!1,count:null,limit:null},sanitize:{status:"loading",on:!1},developerRoleCompat:{status:"loading",on:!1},clineHeaders:{status:"loading",defaults:{},overrides:{},effective:{}},cors:{status:"loading",on:!1},prompt:{status:"loading",mode:"passthrough",file:"",text:"",source:"",lines:0,fileError:"",degradeActive:!1,degradeUntilText:"",providers:[],gateway:{},gatewayText:{},options:[]},storage:{status:"loading",available:!0,file:"",bytes:0,accounts:null,logs:null,requests:null,dailyDays:null,debug:null},captcha:{available:!0,enabled:!1},modelsDev:{status:"loading",enabled:!0,source:"",updatedAt:0,count:0},ioFailure:null,retentionConfirm:null,dbIncludeLogs:!0,dbBackupConfirm:null,dbWarning:null,lanConfirm:null,lanRegister:null,panelLogin:!1},panelLogin:ZI()};const gS=new Set;function CW(e){return gS.add(e),()=>{gS.delete(e)}}function TW(){return ht}function EW(){return x.useSyncExternalStore(CW,TW)}function Xe(e){ht={...ht,...e};for(const t of gS)t()}function Ma(e){Xe({app:{...ht.app,...e}})}function Da(){Xe({})}let Sn=null;function is(e){Sn=e,Xe({busy:e})}function es(){Sn=null,Xe({busy:null})}function xS(e){const t=Ix.some(a=>a.id===e)?String(e):Ix[0].id;Xe({category:t,scrollReset:ht.scrollReset+1})}function AW(e){xS(e);try{localStorage.setItem(zI,e)}catch{}}function WI(){let e=null;try{e=localStorage.getItem(zI)}catch{e=null}xS(e)}function JI(){Xe({unitsChinese:tt().wbUnits?.isChinese?.()!==!1})}function RW(e){tt().wbUnits?.setChinese?.(e),JI(),Ve(r(e?"✅ 已改用本地量级词(万 / 亿式)":"✅ 已改用 k / M 缩写"))}function bS(e){if(e===void 0)return;if(!e||typeof e!="object"){Ma({status:"unavailable"});return}const t=e;Ma({status:"ready",closeToTray:t.closeToTray===!0,autostart:t.autostart===!0,lanAccess:t.lanAccess===!0,lanPanel:t.lanPanel===!0,lightweightMode:t.lightweightMode===!0})}async function eP(){try{bS(await tt().workbuddyDesktop?.getAppSettings())}catch(e){console.warn("读取应用设置失败:",Ot(e)),bS(null)}}async function OW(){const e=tt().workbuddyDesktop;if(e?.localIp){try{Ma({lanIp:await e.localIp()||null})}catch{}try{const t=Number((await e.getBackendStatus?.())?.port)||0;t&&Ma({port:t})}catch{}try{const t=(await e.panelAdminStatus?.())?.registered===!0;Ma({adminRegistered:t})}catch{}}}async function vS(e,t){if(Sn){Da();return}const a=ht.app,o={closeToTray:e==="tray"?t:a.closeToTray,autostart:e==="autostart"?t:a.autostart,lanAccess:a.lanAccess,lanPanel:a.lanPanel,lightweightMode:e==="lightweight"?t:a.lightweightMode};is("app"),Ma(o);const c=r(e==="autostart"?"开机自动启动":e==="lightweight"?"轻量模式":"关闭窗口时最小化到托盘");try{const d=tt().workbuddyDesktop;if(!d)throw new Error(r("主进程桥不可用"));const f=await d.saveAppSettings(o);Ma({status:"ready",...SW(f,o)}),Ve(r("✅ 已更新「{label}」",{label:c}))}catch(d){Ma(a),Ve(r("保存失败:{message}",{message:Ot(d)}),"err")}finally{es()}}function MW(e){if(Sn){Da();return}Xe({lanConfirm:{mode:e?"enable":"disable",panel:ht.app.lanPanel}})}function DW(e){if(Sn){Da();return}Xe({lanConfirm:{mode:"panel",panel:e}})}function yS(e){const t=ht.lanConfirm;if(Xe({lanConfirm:null}),!(!t||!e)){if(t.mode==="disable"){zx(!1,!1);return}if(t.mode==="panel"){zx(!0,t.panel);return}IW()}}async function IW(){const e=tt().workbuddyDesktop;if(!e?.panelAdminStatus){Ve(r("当前环境不支持局域网访问设置"),"err");return}is("lan");let t;try{t=(await e.panelAdminStatus())?.registered===!0}catch(a){es(),Ve(r("查询管理员状态失败:{message}",{message:Ot(a)}),"err");return}if(es(),Ma({adminRegistered:t}),t){await zx(!0,ht.app.lanPanel);return}Xe({lanRegister:{busy:!1,error:""}})}async function PW(e,t){if(Sn)return;const a=tt().workbuddyDesktop;if(!a?.panelRegister)return;const o=e.trim();if(!o||o.length>64){Xe({lanRegister:{busy:!1,error:r("请填写管理员账号(64 字符以内)")}});return}if(t.length<8){Xe({lanRegister:{busy:!1,error:r("密码至少 8 位")}});return}Xe({lanRegister:{busy:!0,error:""}});try{if(await a.panelRegister(o,t),ht.lanRegister===null)return;Xe({lanRegister:null}),Ma({adminRegistered:!0}),await zx(!0,ht.app.lanPanel)}catch(c){Xe({lanRegister:{busy:!1,error:Ot(c)}})}}function tP(){Xe({lanRegister:null})}async function zx(e,t){if(Sn)return;const a=tt().workbuddyDesktop;if(!a?.changeLanAccess){Ve(r("当前环境不支持局域网访问设置"),"err");return}is("lan"),Ma({lanAccess:e,lanPanel:t});try{(await a.changeLanAccess(e,t))?.createdKey&&Ve(r("✅ 已自动创建网关 Key「默认」(可在「网关 Key」页查看)")),Ve(r("✅ 设置已保存,应用正在重启…"))}catch(o){Ve(r("保存失败:{message}",{message:Ot(o)}),"err"),await eP()}finally{es()}}async function _W(){if(!Sn){Xe({ioFailure:null}),is("export");try{const e=await tt().workbuddyDesktop?.exportAccounts();if(e?.canceled){Ve(r("已取消导出"));return}const t=Number(e?.count)||0,a=Number(e?.customProviders)||0;if(!t&&!a){Ve(r("没有可导出的账号"),"err");return}const o=a?r("、{n} 个自定义提供商",{n:a}):"",c=e?.file?r(" 到 {file}",{file:e.file}):"";Ve(r("✅ 已导出 {count} 个账号{note}{file}",{count:t,note:o,file:c}))}catch(e){Ve(r("操作失败:{message}",{message:Ot(e)}),"err")}finally{es()}}}async function LW(){if(!Sn){Xe({ioFailure:null}),is("import");try{const e=await tt().workbuddyDesktop?.importAccounts();if(e?.canceled){Ve(r("已取消导入"));return}const t=Number(e?.added)||0,a=Number(e?.updated)||0,o=Number(e?.skipped)||0,c=Number(e?.failed)||0,d=Array.isArray(e?.errors)?e.errors:[],f=e?.customProviders??{},p=Number(f.added)||0,h=Number(f.updated)||0,b=[];o&&b.push(r("跳过 {n} 个",{n:o})),c&&b.push(r("失败 {n} 个",{n:c}));const y=b.length?r(",{items}",{items:b.join(r("、"))}):"",v=p||h?r(",自定义提供商新增 {added} 个、更新 {updated} 个",{added:p,updated:h}):"",j=r("新增 {added} 个、更新 {updated} 个{suffix}{note}",{added:t,updated:a,suffix:y,note:v});if(c){Ve(r("导入完成:{summary}",{summary:j}),"err");const w=d.slice(0,3).map(k=>{const S=k?.customProvider?r("自定义提供商 {id}",{id:k?.id||r("(无 id)")}):k?.id??r("未知账号"),N=k?.message??r("未知原因");return r("{label}({message})",{label:S,message:N})}).join(r(";"));Xe({ioFailure:{failed:c,detail:w,more:d.length>3}})}else Ve(r("✅ 导入完成:{summary}",{summary:j}));(t||a||p||h)&&await tt().wbApp?.refresh?.()}catch(e){Ve(r("操作失败:{message}",{message:Ot(e)}),"err")}finally{es()}}}function zW(e){Xe({dbIncludeLogs:e})}async function BW(){if(!Sn){is("dbExport");try{const e=tt().workbuddyDesktop;if(!e?.exportDatabase){Ve(r("当前环境不支持整库备份(仅桌面端可用)"),"err");return}const t=await e.exportDatabase(ht.dbIncludeLogs);if(t?.canceled){Ve(r("已取消导出"));return}const a=Number(t?.bytes)||0,o=Array.isArray(t?.tables)?t.tables.length:0;Ve(r("✅ 已备份 {n} 张表({size})到 {file}",{n:o,size:XI(a),file:t?.file||""}))}catch(e){Ve(r("操作失败:{message}",{message:Ot(e)}),"err")}finally{es()}}}function HW(){Sn||Xe({dbBackupConfirm:{includeLogs:ht.dbIncludeLogs}})}function jS(e){Xe({dbBackupConfirm:null}),e&&UW()}async function UW(){if(Sn)return;const e=tt().workbuddyDesktop;if(!e?.importDatabase){Ve(r("当前环境不支持整库恢复(仅桌面端可用)"),"err");return}is("dbImport"),Xe({dbWarning:null});try{const t=await e.importDatabase(),a=Array.isArray(t?.tables)?t.tables.length:0,o=t?.safetyBackup?r(",替换前的数据已备份为 {name}",{name:t.safetyBackup}):"";Ve(r("✅ 已恢复 {n} 张表{note}",{n:a,note:o}));const c=typeof t?.warning=="string"?t.warning.trim():"";c&&Xe({dbWarning:c}),await _S(),await tt().wbApp?.refresh?.()}catch(t){Ve(r("恢复失败:{message}",{message:Ot(t)}),"err")}finally{es()}}function Bx(e){if(e===void 0)return;const t=YI(pS,e,ht.retention.values);Xe({retention:{status:t===null?"unavailable":"ready",values:t}})}async function Hx(){try{Bx(await tt().workbuddyDesktop?.getRetention())}catch(e){console.warn("读取数据保留设置失败:",Ot(e)),Bx(null)}}let Ux=null;function Vx(e){const t=Ux;Ux=null,Xe({retentionConfirm:null}),t?.(e)}function VW(e){return new Promise(t=>{Ux&&Vx(!1),Ux=t,Xe({retentionConfirm:{head:e}})})}function FW(e,t,a){return t===null?r("没能读到「{label}」的当前值,改为 {days} 天可能会删除超出的历史数据。",{label:e.label,days:a}):r("「{label}」将从 {previous} 天改为 {days} 天。",{label:e.label,previous:t,days:a})}async function $W(e,t){if(Sn||ht.retentionConfirm)return;const a=KI(t,e.min,e.max,r("天数"));if(!a.ok){Ve(a.message,"err");return}const o=ht.retention.values?.[e.key],c=typeof o=="number"&&Number.isInteger(o)?o:null;if(c!==null&&a.value===c)return;const d=c===null||a.valueNumber.isInteger(d?.[f.key]))){const f=d?.[e.key]??t;Ve(a?r("✅ 已保留 {days} 天,超出部分已清理",{days:f}):r("✅ 已保留 {days} 天",{days:f}));return}await Hx(),Ve(a?r("✅ 已保留 {days} 天,超出部分已清理",{days:t}):r("✅ 已保留 {days} 天",{days:t}))}catch(c){Ve(r("保存失败:{message}",{message:Ot(c)}),"err"),await Hx()}finally{es()}}function Op(e,t){if(t===void 0)return;const a=YI(e.fields,t,e.read().values);e.write({status:a===null?"unavailable":"ready",values:a}),e.syncExtras?.(a===null?null:t)}async function ed(e){try{Op(e,await e.get())}catch(t){console.warn(`${e.consoleLabel}失败:`,Ot(t)),Op(e,null)}}async function Fx(e,t,a){if(Sn)return;const o=KI(a,t.min,t.max,t.label);if(!o.ok){Ve(o.message,"err");return}const c=e.read().values?.[t.key];if(Number.isInteger(c)&&o.value===c)return;is(e.scope);const d=e.read().values;d&&e.write({status:"ready",values:{...d,[t.key]:o.value}});try{const f=await e.save({[t.key]:o.value});Op(e,f);const p=e.read().values?.[t.key],h=Number.isInteger(p)?p:o.value;Ve(r("✅ 已保存:{label} {value}",{label:t.label,value:String(h)}))}catch(f){Ve(r("保存失败:{message}",{message:Ot(f)}),"err"),await ed(e)}finally{es()}}const nP={scope:"queue",fields:$I,consoleLabel:"读取排队等待设置",get:()=>tt().workbuddyDesktop?.getQueue(),save:e=>tt().workbuddyDesktop?.saveQueue(e),read:()=>ht.queue,write:e=>Xe({queue:e})};async function sP(){await ed(nP)}async function GW(e,t){await Fx(nP,e,t)}const rP={scope:"captchaPool",fields:QI,consoleLabel:"读取验证码令牌池设置",get:()=>tt().workbuddyDesktop?.getCaptchaPool(),save:e=>tt().workbuddyDesktop?.saveCaptchaPool(e),read:()=>ht.captchaPool,write:e=>Xe({captchaPool:e})};async function aP(){await ed(rP)}async function KW(e,t){await Fx(rP,e,t)}const lP="routingStrategy",oP="routingSticky",YW="routingFailoverBackoff",XW="routingSink",QW="routingBreakerEnabled",ZW={[lP]:new Set(_x.map(e=>e.value)),[oP]:new Set(Lx.map(e=>e.value))};function iP(e){const t=e&&typeof e=="object"?e:{},a=(c,d)=>{const f=t[c];return typeof f=="string"&&ZW[c].has(f)?f:d},o=(c,d)=>{const f=t[c];return typeof f=="boolean"?f:d};return{strategy:a(lP,"order"),sticky:a(oP,"auto"),failoverBackoff:o(YW,!0),sink:o(XW,!0),breakerEnabled:o(QW,!1)}}async function $x(){try{const e=await tt().workbuddyDesktop?.getRoutingConfig();if(e===void 0){Xe({routing:{...ht.routing,status:"unavailable"}});return}Xe({routing:{status:"ready",...iP(e)}})}catch(e){console.warn("读取路由设置失败:",Ot(e)),Xe({routing:{...ht.routing,status:"unavailable"}})}}async function wS(e){if(Sn)return;const t=tt().workbuddyDesktop;if(!t?.setRoutingConfig){Ve(r("桌面运行时不可用,暂时无法保存"),"err");return}is("routing");try{const a=await t.setRoutingConfig(e);a!==void 0?Xe({routing:{status:"ready",...iP(a)}}):await $x(),Ve(r("✅ 路由设置已保存"))}catch(a){Ve(r("保存失败:{message}",{message:Ot(a)}),"err"),await $x()}finally{es()}}const Mp={scope:"retry",fields:VI,consoleLabel:"读取请求重试设置",get:()=>tt().workbuddyDesktop?.getRetry(),save:e=>tt().workbuddyDesktop?.saveRetry(e),read:()=>ht.retry,write:e=>Xe({retry:e}),syncExtras:e=>{if(e===null){Xe({retryCodes:null});return}const t=e[qI];if(!Array.isArray(t))return;Xe({retryCodes:t.filter(o=>typeof o=="number"&&Number.isInteger(o)&&o>=mS&&o<=hS)})}};function WW(e){Op(Mp,e)}async function cP(){await ed(Mp)}async function JW(e,t){await Fx(Mp,e,t)}async function SS(e){if(!Sn){Xe({retryCodes:e}),is("codes");try{const t=await tt().workbuddyDesktop?.saveRetry({[qI]:e});Op(Mp,t),Ve(r("✅ 已保存:指定错误码直接换号"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await ed(Mp)}finally{es()}}}async function eJ(e){const t=ht.retryCodes;if(t===null)return;const a=String(e??"").trim();if(!a)return;if(!/^\d+$/.test(a)||Number(a)hS){Ve(r("状态码必须是 {min}–{max} 的整数(收到: {text})",{min:mS,max:hS,text:a}),"err");return}const o=Number(a);if(t.includes(o)){Ve(r("状态码 {code} 已在名单里",{code:o}));return}if(t.length>=GI){Ve(r("名单最多 {max} 个状态码",{max:GI}),"err");return}await SS([...t,o])}async function tJ(e){const t=ht.retryCodes;!t||!t.includes(e)||await SS(t.filter(a=>a!==e))}async function nJ(){const e=ht.retryCodes;e?.length&&await SS(e.slice(0,-1))}const uP={scope:"timeouts",fields:FI,consoleLabel:"读取请求超时设置",get:()=>tt().workbuddyDesktop?.getTimeouts(),save:e=>tt().workbuddyDesktop?.saveTimeouts(e),read:()=>ht.timeouts,write:e=>Xe({timeouts:e})};async function dP(){await ed(uP)}async function sJ(e,t){await Fx(uP,e,t)}function qx(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({debug:{status:"unavailable",on:!1,count:null,limit:null}});return}const t=e,a=Number(t.count),o=Number(t.limit);Xe({debug:{status:"ready",on:t.debugMode===!0,count:Number.isInteger(a)?a:null,limit:Number.isInteger(o)?o:null}})}async function NS(){try{qx(await tt().workbuddyDesktop?.getDebug())}catch(e){console.warn("读取调试模式设置失败:",Ot(e)),qx(null)}}async function rJ(e){if(Sn){Da();return}is("debug"),Xe({debug:{...ht.debug,on:e}});try{const t=await tt().workbuddyDesktop?.saveDebug(e);qx(t),Ve(r(e?"✅ 调试模式已开启":"✅ 调试模式已关闭"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await NS()}finally{es()}}function Gx(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({sanitize:{status:"unavailable",on:!1}});return}Xe({sanitize:{status:"ready",on:e.sanitizeBlacklistFingerprints===!0}})}async function kS(){try{Gx(await tt().workbuddyDesktop?.getSanitize())}catch(e){console.warn("读取出站指纹脱敏设置失败:",Ot(e)),Gx(null)}}async function aJ(e){if(Sn){Da();return}is("sanitize"),Xe({sanitize:{status:"ready",on:e}});try{const t=await tt().workbuddyDesktop?.saveSanitize(e);Gx(t),Ve(r(e?"✅ 出站指纹脱敏已开启":"已关闭出站指纹脱敏"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await kS()}finally{es()}}function CS(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({developerRoleCompat:{status:"unavailable",on:!1}});return}Xe({developerRoleCompat:{status:"ready",on:e.developerRoleCompat===!0}})}async function TS(){try{CS(await tt().workbuddyDesktop?.getDeveloperRoleCompat())}catch(e){console.warn("读取开发者角色兼容设置失败:",Ot(e)),CS(null)}}async function lJ(e){if(Sn){Da();return}is("developerRoleCompat"),Xe({developerRoleCompat:{status:"ready",on:e}});try{const t=await tt().workbuddyDesktop?.saveDeveloperRoleCompat(e);CS(t),Ve(r(e?"✅ 开发者角色兼容已开启":"已关闭开发者角色兼容"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await TS()}finally{es()}}function ES(e){if(!e||typeof e!="object")return{};const t={};for(const[a,o]of Object.entries(e))typeof o=="string"&&(t[a]=o);return t}function AS(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({clineHeaders:{status:"unavailable",defaults:{},overrides:{},effective:{}}});return}const t=e;Xe({clineHeaders:{status:"ready",defaults:ES(t.defaults),overrides:ES(t.overrides),effective:ES(t.effective)}})}async function RS(){try{AS(await tt().workbuddyDesktop?.getClineHeaders())}catch(e){console.warn("读取 Cline 伪装头失败:",Ot(e)),AS(null)}}async function oJ(){await RS(),Ve(r("Cline 伪装头已刷新"))}async function fP(e){if(Sn){Da();return}is("clineHeaders");try{const t=await tt().workbuddyDesktop?.saveClineHeaders(e);AS(t),Ve(r("✅ Cline 伪装头已保存"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await RS()}finally{es()}}function OS(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({cors:{status:"unavailable",on:!1}});return}Xe({cors:{status:"ready",on:e.corsEnabled===!0}})}async function MS(){try{OS(await tt().workbuddyDesktop?.getCors())}catch(e){console.warn("读取网关跨域访问设置失败:",Ot(e)),OS(null)}}async function iJ(e){if(Sn){Da();return}is("cors"),Xe({cors:{status:"ready",on:e}});try{const t=await tt().workbuddyDesktop?.saveCors(e);OS(t),Ve(r(e?"网关跨域访问已开启":"已关闭网关跨域访问"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await MS()}finally{es()}}async function pP(){try{const e=await tt().workbuddyDesktop?.getCaptchaSetting();Xe({captcha:{available:!0,enabled:e?.captchaEnabled===!0}})}catch(e){Xe({captcha:{available:!1,enabled:!1}}),console.warn("读取机器人校验设置失败:",Ot(e))}}async function cJ(e){if(Sn){Da();return}is("captcha"),Xe({captcha:{...ht.captcha,enabled:e}});try{const t=await tt().workbuddyDesktop?.saveCaptchaSetting(e);Xe({captcha:{available:!0,enabled:t?.captchaEnabled===!0}}),Ve(r(e?"✅ 机器人校验已开启":"⚠️ 机器人校验已关闭"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await pP()}finally{es()}}function DS(e){return!e||typeof e!="object"?{status:"unavailable",enabled:!0,source:"",updatedAt:0,count:0}:{status:"ready",enabled:e.modelsDevEnabled!==!1,source:typeof e.source=="string"?e.source:"",updatedAt:Number(e.updatedAt)||0,count:Number(e.count)||0}}async function IS(){try{const e=await tt().workbuddyDesktop?.getModelsDev?.();Xe({modelsDev:DS(e)})}catch(e){Xe({modelsDev:{...ht.modelsDev,status:"unavailable"}}),console.warn("读取 models.dev 元数据设置失败:",Ot(e))}}async function uJ(e){if(Sn){Da();return}is("modelsDev"),Xe({modelsDev:{...ht.modelsDev,enabled:e}});try{const t=await tt().workbuddyDesktop?.saveModelsDev?.(e);Xe({modelsDev:DS(t)}),Ve(r(e?"✅ models.dev 模型元数据已开启":"已关闭 models.dev 联网刷新"))}catch(t){Ve(r("保存失败:{message}",{message:Ot(t)}),"err"),await IS()}finally{es()}}async function dJ(){if(Sn){Da();return}is("modelsDevRefresh");try{const e=await tt().workbuddyDesktop?.refreshModelsDev?.();Xe({modelsDev:DS(e?.status)});const t=e?.result,a=String(t?.status||"");a==="refreshed"?Ve(r("models.dev 元数据已更新({count} 条)",{count:Number(t?.count)||0})):a==="failed"?Ve(r("刷新失败:{message}",{message:String(t?.message||"")}),"err"):Ve(String(t?.message||r("本次无需刷新")))}catch(e){Ve(r("刷新失败:{message}",{message:Ot(e)}),"err"),await IS()}finally{es()}}function td(e){if(e===void 0)return;if(!e||typeof e!="object"){Xe({prompt:{...ht.prompt,status:"unavailable"}});return}const t=e,a=mJ(t.promptGateway);Xe({prompt:{status:"ready",mode:String(t.promptMode||"passthrough"),file:String(t.promptFile||""),text:String(t.promptText||""),source:String(t.promptSource||""),lines:Number(t.promptLines)||0,fileError:String(t.promptFileError||""),degradeActive:t.degradeActive===!0,degradeUntilText:String(t.degradeUntilText||""),providers:fJ(t.promptProviders,a),gateway:a,gatewayText:hJ(t.promptGatewayText),options:pJ(t.promptProviderOptions)}})}function fJ(e,t){return!e||typeof e!="object"?[]:Object.entries(e).filter(([a,o])=>!!a&&!!o&&typeof o=="object").map(([a,o])=>{const c=o;return{id:a,mode:String(c.promptMode||"passthrough"),file:String(c.promptFile||""),text:String(c.promptText||""),source:String(c.promptSource||""),lines:Number(c.promptLines)||0,fileError:String(c.promptFileError||""),gateway:t[a]??!0,configured:!0}}).sort((a,o)=>a.id.localeCompare(o.id))}function pJ(e){return Array.isArray(e)?e.filter(t=>!!t&&typeof t=="object"&&String(t.id||"")).map(t=>{const a=t;return{id:String(a.id),label:String(a.label||a.id),gatewayNote:String(a.gatewayNote||""),gatewayChars:Number(a.gatewayChars)||0,gatewayBlocks:gJ(a.gatewayBlocks)}}):[]}function mJ(e){if(!e||typeof e!="object")return{};const t={};for(const[a,o]of Object.entries(e)){const c=String(a||"").trim();!c||typeof o!="boolean"||(t[c]=o)}return t}function hJ(e){if(!e||typeof e!="object")return{};const t={};for(const[a,o]of Object.entries(e)){const c=String(a||"").trim();if(!c||!o||typeof o!="object")continue;const d=o,f={identity:"",stable:"",dynamic:""};let p=!1;for(const h of["identity","stable","dynamic"]){const b=String(d[h]||"");f[h]=b,b.trim()&&(p=!0)}p&&(t[c]=f)}return t}function gJ(e){if(!e||typeof e!="object")return null;const t=e,a={identity:String(t.identity||""),stable:String(t.stable||""),dynamic:String(t.dynamic||"")};return!a.identity.trim()&&!a.stable.trim()&&!a.dynamic.trim()?null:a}async function fc(){try{td(await tt().workbuddyDesktop?.getPrompt())}catch(e){console.warn("读取系统提示词设置失败:",Ot(e)),td(null)}}async function Dp(e,t){if(Sn)return await fc(),!1;is("prompt");try{const a=await tt().workbuddyDesktop?.savePrompt(t);return td(a),Ve(r("✅ 已保存:{label}",{label:e})),!0}catch(a){return Ve(r("保存失败:{message}",{message:Ot(a)}),"err"),await fc(),!1}finally{es()}}async function xJ(e){const t=$o.find(a=>a.value===e);await Dp(r("模式改为「{mode}」",{mode:t?.toastLabel??e}),{promptMode:e})}async function bJ(e){await Dp(e.trim()?r("提示词文件已更新"):r("已改回内置默认提示词"),{promptFile:e})}async function vJ(e){const t=!e.trim();return Dp(r(t?"已清掉界面编辑的提示词(回落文件 / 内置默认)":"提示词正文已更新"),{promptText:t?"":e})}function qo(e,t){return e.options.find(a=>a.id===t)?.label||t}function pc(e){const t=e==null?"":String(e).trim();return t&&ht.prompt.options.some(a=>a.id===t)?t:""}async function Ip(e,t,a){return Dp(e,{promptProviders:{[t]:a}})}function Kx(e,t){const a=!t.configured;return{promptMode:t.mode,promptFile:t.file,promptText:a&&e.source==="inline"?e.text:""}}async function yJ(e){const t=pc(e);if(!t)return;const a=ht.prompt;await Ip(r("已为「{label}」单独配置提示词",{label:qo(a,t)}),t,Kx(a,{mode:a.mode,file:a.file,text:a.text,source:a.source,lines:a.lines,fileError:a.fileError,gateway:a.gateway[t]??!0,configured:!1}))}async function jJ(e,t){const a=pc(e.id);if(!a||!$o.some(c=>c.value===t))return;const o=$o.find(c=>c.value===t);await Ip(r("「{label}」的模式改为「{mode}」",{label:qo(ht.prompt,a),mode:o?.toastLabel??t}),a,{...Kx(ht.prompt,e),promptMode:t})}async function wJ(e,t){const a=pc(e.id);a&&await Ip(t.trim()?r("「{label}」的提示词文件已更新",{label:qo(ht.prompt,a)}):r("「{label}」改用内置默认提示词",{label:qo(ht.prompt,a)}),a,{...Kx(ht.prompt,e),promptFile:t})}async function SJ(e,t){const a=pc(e.id);if(!a)return!1;const o=!t.trim(),c=qo(ht.prompt,a);return Ip(o?r("已清掉「{label}」界面编辑的正文",{label:c}):r("「{label}」的提示词正文已更新",{label:c}),a,{...Kx(ht.prompt,e),promptText:o?"":t})}async function NJ(e){const t=pc(e);t&&await Ip(r("已取消「{label}」的单独配置",{label:qo(ht.prompt,t)}),t,null)}async function kJ(e,t){const a=pc(e);if(!a)return;const o=qo(ht.prompt,a);if(Sn){await fc();return}is("prompt");try{const c=await tt().workbuddyDesktop?.savePrompt({promptGateway:{[a]:t}});td(c),Ve(t?r("✅ 已为「{label}」装上网关自带提示词",{label:o}):r("已关闭「{label}」的网关自带提示词:能否通过上游校验取决于上游当前口径",{label:o}),t?"ok":"err")}catch(c){Ve(r("保存失败:{message}",{message:Ot(c)}),"err"),await fc()}finally{es()}}async function CJ(e,t){const a=pc(e);if(!a)return!1;const o=qo(ht.prompt,a),c=!t||!(t.identity.trim()||t.stable.trim()||t.dynamic.trim());return Dp(c?r("「{label}」的网关自带提示词已改回官方原文",{label:o}):r("「{label}」的网关自带提示词正文已更新",{label:o}),{promptGatewayText:{[a]:c?null:t}})}async function TJ(){if(!Sn){is("prompt");try{const e=await tt().workbuddyDesktop?.savePrompt({clearDegrade:!0});td(e),Ve(r("✅ 已解除内容拦截降级"))}catch(e){Ve(r("解除失败:{message}",{message:Ot(e)}),"err"),await fc()}finally{es()}}}function Pp(e){const t=Number(e);return Number.isFinite(t)?t:null}function PS(e){if(e===void 0)return;const t=e&&typeof e=="object"?e.database:null;if(!t||typeof t!="object"){Xe({storage:{...ht.storage,status:"unavailable"}});return}const a=t;Xe({storage:{status:"ready",available:a.available!==!1,file:String(a.file||""),bytes:Number(a.bytes)||0,accounts:Pp(a.accounts),logs:Pp(a.logs),requests:Pp(a.requests),dailyDays:Pp(a.dailyDays),debug:Pp(a.debug)}})}async function mP(){try{PS(await tt().workbuddyDesktop?.getStorage())}catch(e){console.warn("读取数据存储概况失败:",Ot(e)),PS(null)}}async function EJ(){try{return await tt().workbuddyDesktop?.panelLogout(),window.location.href="/login",!0}catch(e){return Ve(r("退出失败:{message}",{message:Ot(e)}),"err"),!1}}async function _S(){WI(),JI(),Xe({panelLogin:ZI()}),await Promise.all([eP(),OW(),Hx(),cP(),dP(),sP(),aP(),$x(),NS(),kS(),TS(),RS(),MS(),fc(),mP(),pP(),IS(),tt().wbUpdatePanel?.load?.()])}async function AJ(){await Hx(),Ve(r("保留天数已刷新"))}async function RJ(){await cP(),Ve(r("重试设置已刷新"))}async function OJ(){await dP(),Ve(r("超时设置已刷新"))}async function MJ(){await sP(),Ve(r("排队等待设置已刷新"))}async function DJ(){await aP(),Ve(r("验证码令牌池设置已刷新"))}async function IJ(){await $x(),Ve(r("路由设置已刷新"))}async function PJ(){await NS(),Ve(r("调试模式设置已刷新"))}async function _J(){await kS(),Ve(r("指纹脱敏设置已刷新"))}async function LJ(){await TS(),Ve(r("开发者角色兼容设置已刷新"))}async function zJ(){await MS(),Ve(r("网关跨域访问设置已刷新"))}async function BJ(){await fc(),Ve(r("系统提示词设置已刷新"))}async function HJ(){await mP(),Ve(r("存储概况已刷新"))}const Yx=[{key:"identity",label:r("第一段(身份句)"),short:r("第一段"),hint:r("官方原文只有一句:声明自己是 ZCode。")},{key:"stable",label:r("第二段(稳定段)"),short:r("第二段"),hint:r("工具用法与环境说明那一大段。")},{key:"dynamic",label:r("第三段(动态段)"),short:r("第三段"),hint:r("沟通方式 / 上下文管理 + Environment 段。")}];function UJ(e){return r(e==="inline"?"界面里编辑的正文":e==="file"?"提示词文件":e==="builtin"?"内置默认提示词":"(未生效)")}function hP({title:e,text:t,source:a,file:o,disabled:c,save:d,onClose:f}){const[p,h]=x.useState(t),[b,y]=x.useState(!1),v=b||c,j=p!==t;async function w(k){y(!0);try{await d(k)&&f()}finally{y(!1)}}return s.jsx(Yt,{open:!0,onOpenChange:k=>{k||v||f()},children:s.jsxs(Xt,{className:"w-[min(880px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:e})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("保存后以这里的文本为准")}),s.jsxs("p",{children:[r("这一份就是「替换 / 追加」模式下网关要发的 system 正文。"),a==="none"?r("当前是透传模式:存下来也不会发出,切成「替换 / 追加」之后才生效。"):r("当前生效的正文来自{source}{file}。保存后这一份会盖过提示词文件与内置默认{note}。",{source:UJ(a),file:o.trim()&&a!=="inline"?r("(文件:{path})",{path:o.trim()}):"",note:a!=="inline"&&o.trim()?r(",文件里后续的改动在清空这里之前不再生效"):""}),r("想回到原来那份,把这里清空再保存即可(不会删掉你配的文件路径)。")]})]}),s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsx(Je,{htmlFor:"settings-prompt-body",children:r("提示词正文")}),s.jsx(Mi,{id:"settings-prompt-body",rows:18,className:"min-h-[320px]",spellCheck:!1,disabled:v,value:p,onChange:k=>h(k.currentTarget.value)}),s.jsx("div",{className:"hint",children:p.trim()?r("{lines} 行、{chars} 字符(按当前草稿计)",{lines:p.split(` +`).length,chars:p.length}):r("空 = 不要这一份,回落提示词文件 / 内置默认提示词。")})]})]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",className:"mr-auto",disabled:v||a!=="inline",onClick:()=>{w("")},children:r("清除这里的正文")}),s.jsx(ne,{variant:"outline",disabled:v,onClick:f,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:v||!j,onClick:()=>{w(p)},children:r(b?"保存中…":"保存")})]})]})})}function VJ({prompt:e,locked:t,busy:a}){const[o,c]=x.useState(!1);return s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:"btn-prompt-edit-body",variant:"outline",disabled:t||a,onClick:()=>c(!0),children:r("编辑正文")}),o?s.jsx(hP,{title:r("编辑提示词正文 · 全局"),text:e.text,source:e.source,file:e.file,disabled:a,save:vJ,onClose:()=>c(!1)}):null]})}function FJ({item:e,label:t,locked:a,busy:o}){const[c,d]=x.useState(!1);return s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:`btn-prompt-edit-body-${e.id}`,variant:"outline",disabled:a||o,onClick:()=>d(!0),children:r("编辑正文")}),c?s.jsx(hP,{title:r("编辑提示词正文 · {label}",{label:t}),text:e.text,source:e.source,file:e.file,disabled:o,save:f=>SJ(e,f),onClose:()=>d(!1)}):null]})}function $J({id:e,title:t,official:a,over:o,enabled:c,disabled:d,onClose:f}){const[p,h]=x.useState(()=>({identity:o?.identity?.trim()?o.identity:a.identity,stable:o?.stable?.trim()?o.stable:a.stable,dynamic:o?.dynamic?.trim()?o.dynamic:a.dynamic})),[b,y]=x.useState(!1),v=b||d,j=Yx.some(S=>p[S.key]!==a[S.key]),w=Yx.filter(S=>o?.[S.key]?.trim()).map(S=>S.label);async function k(S){y(!0);try{await CJ(e,S)&&f()}finally{y(!1)}}return s.jsx(Yt,{open:!0,onOpenChange:S=>{S||v||f()},children:s.jsxs(Xt,{className:"w-[min(880px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:t})}),s.jsxs(Lt,{children:[s.jsxs(dn,{children:[s.jsx("h3",{children:r("三段各自成块,所以分开编辑")}),s.jsxs("p",{children:[r("上游按"),s.jsx("strong",{children:r("结构")}),r("校验身份:这三段必须各自成块排在最前(实测:三段并成一段会被回 405 / 3012)。因此这里按段编辑,不能合成一段。改过的段以你的文本为准,没改的段继续用官方原文;清空某一段 = 那一段恢复官方原文。"),w.length?r("当前已改过:{edited}。",{edited:w.join(r("、"))}):r("当前三段都是官方原文。"),c?"":r("注意:这一家的「网关自带」开关现在是关的,改过的正文要等开关打开才生效。")]}),s.jsx("p",{children:Un.promptGatewayText})]}),Yx.map(S=>s.jsxs("div",{className:"flex flex-col gap-1.5",children:[s.jsxs(Je,{htmlFor:`settings-prompt-block-${e}-${S.key}`,children:[S.label,s.jsx("span",{className:"ml-2 font-normal text-subtle",children:p[S.key]===a[S.key]?r("(官方原文)"):r("(已改)")})]}),s.jsx(Mi,{id:`settings-prompt-block-${e}-${S.key}`,rows:S.key==="identity"?2:10,className:S.key==="identity"?"min-h-[64px]":"min-h-[200px]",spellCheck:!1,disabled:v,value:p[S.key],onChange:N=>{const R=N.currentTarget.value;h(P=>({...P,[S.key]:R}))}}),s.jsx("div",{className:"hint",children:S.hint})]},S.key))]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",className:"mr-auto",disabled:v||!w.length,onClick:()=>{k(null)},children:r("恢复官方原文")}),s.jsx(ne,{variant:"outline",disabled:v,onClick:f,children:r("取消")}),s.jsx(ne,{variant:"default",disabled:v||!j,onClick:()=>{k(p)},children:r(b?"保存中…":"保存")})]})]})})}function qJ({item:e,option:t,over:a,locked:o,busy:c}){const[d,f]=x.useState(!1),p=t.gatewayBlocks;return p?s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:`btn-prompt-gateway-text-${e.id}`,variant:"outline",disabled:o||c,onClick:()=>f(!0),children:r("编辑正文")}),d?s.jsx($J,{id:e.id,title:r("编辑网关自带提示词 · {label}",{label:t.label}),official:p,over:a,enabled:e.gateway,disabled:c,onClose:()=>f(!1)}):null]}):null}function GJ(e){return e?Yx.filter(t=>(e[t.key]||"").trim()).map(t=>t.short).join(r("、")):""}function gP(e,t){return tt().wbIcons?.icon?.(e,t)||""}function Jt({tone:e,children:t}){const a=e==="ok"?"success":e==="bad"?"destructive":"outline";return s.jsx(ze,{variant:a,children:t})}function Gn({title:e,tip:t,badge:a,actions:o}){return s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:e}),t?s.jsx("span",{className:"tip-q","data-tip":t}):null,a,o?s.jsx("div",{className:"head-actions",children:o}):null]})}function KJ({title:e,tip:t,badge:a,actions:o,children:c}){function d(f){f.target.closest(".tip-q, .head-actions")&&f.preventDefault()}return s.jsxs("details",{className:"panel panel-fold",children:[s.jsxs("summary",{className:"panel-head",onClick:d,children:[s.jsx("span",{className:"fold-caret","aria-hidden":!0,dangerouslySetInnerHTML:{__html:gP("caretRight",14)}}),s.jsx("h2",{children:e}),t?s.jsx("span",{className:"tip-q","data-tip":t}):null,a,o?s.jsx("div",{className:"head-actions",children:o}):null]}),c]})}function Ur({id:e,label:t,checked:a,disabled:o,tip:c,onCheckedChange:d}){return s.jsxs("label",{className:"switch",children:[s.jsx(Zn,{id:e,checked:a,disabled:o,onCheckedChange:f=>d(f)}),s.jsx("span",{children:t}),c?s.jsx("span",{className:"tip-q","data-tip":c}):null]})}function _p({field:e,value:t,disabled:a,onCommit:o}){const[c,d]=x.useState(null),f=c!==null?c:t===null?"":String(t);async function p(){const h=c;if(h!==null)try{await o(h)}finally{d(null)}}return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:e.id,children:e.label}),s.jsxs("span",{className:"retention-input",children:[s.jsx(Fe,{id:e.id,type:"number",min:e.min,max:e.max,step:1,inputMode:"numeric",className:"w-[92px] max-w-[92px] text-center tabular-nums",value:f,disabled:a||t===null,onChange:h=>d(h.target.value),onFocus:()=>d(String(t??"")),onBlur:()=>{p()},onKeyDown:h=>{h.key==="Enter"&&h.currentTarget.blur()}}),s.jsx("span",{className:"unit",children:e.unit})]}),s.jsx("div",{className:"hint",children:e.hint})]})}function Lp(e){return e.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):e.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")})}function Cr({id:e,onClick:t}){return s.jsx(ne,{id:e,variant:"outline",onClick:t,children:r("刷新")})}function YJ(e){const{lanAccess:t,lanPanel:a,lanIp:o,port:c}=e.app;if(!t)return r("未开启:网关只监听 127.0.0.1,仅本机可以访问。");const d=`http://${o||r("<本机IP>")}${c?`:${c}`:""}`,f=a?r(";网页管理面板已一并开放(浏览器打开同一地址)"):"";return r("已开启:其他设备把 API 地址指向 {url}{panel}。",{url:`${d}/v1`,panel:f})}function XJ({snap:e}){const t=e.app,a=t.status==="unavailable"?kt.appUnavailable:t.status==="loading"?kt.appLoading:t.closeToTray?t.lightweightMode?kt.appLightOn:kt.appTrayOn:kt.appTrayOff;return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("启动与托盘"),tip:Jn.tray,badge:t.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已应用")}):t.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"settings-switches",children:[s.jsx(Ur,{id:"settings-close-to-tray",label:r("关闭窗口时最小化到托盘"),checked:t.closeToTray,disabled:e.busy==="app",onCheckedChange:o=>{vS("tray",o)}}),s.jsx(Ur,{id:"settings-lightweight",label:r("轻量模式(关窗释放界面内存)"),tip:Jn.lightweight,checked:t.lightweightMode,disabled:e.busy==="app"||!t.closeToTray,onCheckedChange:o=>{vS("lightweight",o)}}),s.jsx(Ur,{id:"settings-autostart",label:r("开机自动启动"),checked:t.autostart,disabled:e.busy==="app",onCheckedChange:o=>{vS("autostart",o)}})]}),s.jsx("div",{className:"settings-state",children:a})]})]}),!e.panelLogin&&s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("局域网访问"),tip:Jn.lan}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"settings-switches",children:[s.jsx(Ur,{id:"settings-lan-access",label:r("允许局域网内的设备访问网关"),checked:e.app.lanAccess,disabled:e.busy==="lan",onCheckedChange:MW}),s.jsx(Ur,{id:"settings-lan-panel",label:r("同时开放网页管理面板"),checked:e.app.lanPanel,disabled:e.busy==="lan"||!e.app.lanAccess,onCheckedChange:DW})]}),s.jsx("div",{className:"settings-state",children:YJ(e)})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("计量单位"),tip:Jn.units}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-chinese-units",label:r("使用中文单位(亿 / 万)"),checked:e.unitsChinese,onCheckedChange:RW})}),s.jsx("div",{className:"settings-state",children:e.unitsChinese?kt.unitsOn:kt.unitsOff})]})]})]})}function QJ(e){return e==="light"?kt.themeLight:e==="dark"?kt.themeDark:kt.themeSystem}function ZJ(){const[e,t]=x.useState(jW),[a,o]=x.useState(wW),c=tt().workbuddyDesktop?.platform==="web";x.useEffect(()=>{const f=h=>t(String(h.detail||"system")),p=h=>o(Number(h.detail)||100);return window.addEventListener(BI,f),window.addEventListener(HI,p),()=>{window.removeEventListener(BI,f),window.removeEventListener(HI,p)}},[]);const d=a===100?r("100%(默认)"):`${a}%`;return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("显示模式"),tip:Jn.displayTheme}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{children:s.jsx(En,{"aria-label":r("显示模式"),options:yW,value:e,onValueChange:f=>tt().wbApp?.applyTheme?.(f)})}),s.jsx("div",{className:"settings-state",children:QJ(e)})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("界面缩放"),tip:Jn.displayZoom}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-zoom",children:r("缩放比例")}),s.jsx("span",{className:"prompt-input",children:s.jsxs(dt,{value:String(a),onValueChange:f=>tt().wbApp?.applyZoom?.(Number(f)),children:[s.jsx(pt,{id:"settings-zoom",className:"w-[140px]",disabled:c,"aria-label":r("界面缩放比例"),children:s.jsx(ft,{children:d})}),s.jsx(mt,{children:vW.map(f=>s.jsx($e,{value:String(f),children:f===100?r("100%(默认)"):`${f}%`},f))})]})}),s.jsx("div",{className:"hint",children:r("放大或缩小整个界面(文字与控件一起变),效果与浏览器 Ctrl +/- 相同:共 11 档,立即生效并记住。")})]})}),s.jsx("div",{className:"settings-state",children:c?kt.zoomWeb:a===100?kt.zoomDefault:r("当前按 {n}% 显示。",{n:a})})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("语言设置"),tip:Jn.displayLanguage}),s.jsxs("div",{className:"panel-body",children:[s.jsx(WJ,{}),s.jsx("div",{className:"settings-state",children:kt.languageHint})]})]})]})}function WJ(){const e=window.wbI18n,t=e?.rawLocale?.()??"auto",a=e?.LOCALES??[],o=c=>c==="auto"?r("跟随系统"):a.find(d=>d.code===c)?.label??c;return s.jsx("div",{className:"retention-list",children:s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-language",children:r("界面语言")}),s.jsx("span",{className:"prompt-input",children:s.jsxs(dt,{value:t,onValueChange:c=>{c&&e?.setLocale(c)},children:[s.jsx(pt,{id:"settings-language",className:"w-[200px]","aria-label":r("界面语言"),children:s.jsx(ft,{children:o(t)})}),s.jsxs(mt,{children:[s.jsx($e,{value:"auto",children:r("跟随系统")}),a.map(c=>s.jsx($e,{value:c.code,children:c.label},c.code))]})]})})]})})}function JJ({codes:e,status:t,busy:a}){const[o,c]=x.useState(""),d=x.useRef(null),f=t==="unavailable";return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-retry-no-codes-input",children:r("指定错误码直接换号")}),s.jsx("div",{className:"retention-input",children:s.jsxs("div",{className:f?"tag-input disabled":"tag-input",onClick:()=>d.current?.focus(),children:[(e||[]).map(p=>s.jsxs("span",{className:"tag-chip",children:[s.jsx("span",{className:"v",children:p}),s.jsx(ne,{type:"button",variant:"ghost",size:"icon-2xs",className:"tag-x text-muted-foreground hover:bg-destructive-soft hover:text-destructive",title:r("删除 {code}",{code:p}),"aria-label":r("删除状态码 {code}",{code:p}),onClick:h=>{h.stopPropagation(),tJ(p)},children:"✕"})]},p)),s.jsx(Fe,{ref:d,id:"settings-retry-no-codes-input",type:"text",className:"tag-input-field h-auto border-0 bg-transparent px-0 shadow-none focus:shadow-none",placeholder:f?"—":r("输入状态码,回车添加"),inputMode:"numeric",autoComplete:"off",value:o,disabled:f||a,onChange:p=>c(p.target.value),onKeyDown:p=>{if(p.key==="Enter"){p.preventDefault(),eJ(o),c("");return}p.key==="Backspace"&&!o&&nJ()}})]})}),s.jsx("div",{className:"hint",children:Un.retryCodes})]})}function eee({prompt:e,locked:t,busy:a}){const[o,c]=x.useState(null);async function d(){const f=o;if(f!==null)try{await bJ(f)}finally{c(null)}}return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-prompt-file",children:r("提示词文件")}),s.jsx("span",{className:"prompt-input",children:s.jsx(Fe,{id:"settings-prompt-file",type:"text",placeholder:r("留空 = 用内置默认提示词"),value:o!==null?o:e.file,disabled:t||a,onChange:f=>c(f.target.value),onFocus:()=>c(e.file),onBlur:()=>{d()},onKeyDown:f=>{f.key==="Enter"&&f.currentTarget.blur()}})}),s.jsx("div",{className:"hint",children:Un.promptFile})]})}function tee(e){if(e.status==="loading")return kt.appLoading;if(e.status==="unavailable")return kt.promptUnavailable;const t=xP(e.source),a=[];return e.mode==="passthrough"?a.push(r("客户端 system 原样出站(只靠指纹脱敏改写模板句)。")):a.push(r("{mode}生效:上游收到的 system 来自{source}{lines}。",{mode:e.mode==="custom"?r("替换"):r("追加"),source:t,lines:e.lines?r("({n} 行)",{n:e.lines}):""})),e.fileError&&a.push(`⚠️ ${e.fileError}`),a.join("")}function xP(e){return e==="inline"?r("界面里编辑的正文"):e==="file"?r("提示词文件"):e==="builtin"?r("内置默认提示词"):""}function nee(e){return r("已自动切换到最小中性提示词(撞了上游内容拦截,多半是 system 指纹误报),到 {until} 自动解除。",{until:e.degradeUntilText||kt.degradeUntilFallback})+r("期间本模式自己的提示词不会发出;把提示词改好后可以立即解除。")}function see({item:e,label:t,locked:a,busy:o}){const[c,d]=x.useState(null);async function f(){const p=c;if(p!==null)try{p!==e.file&&await wJ(e,p)}finally{d(null)}}return s.jsx("span",{className:"prompt-input",children:s.jsx(Fe,{id:`settings-prompt-file-${e.id}`,type:"text",placeholder:r("留空 = 用内置默认提示词"),"aria-label":r("{label} 提示词文件",{label:t}),value:c!==null?c:e.file,disabled:a||o,onChange:p=>d(p.target.value),onFocus:()=>d(e.file),onBlur:()=>{f()},onKeyDown:p=>{p.key==="Enter"&&p.currentTarget.blur()}})})}function ree(e,t){if(!t)return r("未单独配置:模式、提示词文件与正文都跟随上面的全局配置(当前「{mode}」)。",{mode:$o.find(o=>o.value===e.mode)?.toastLabel??e.mode});if(e.mode==="passthrough")return r("客户端 system 原样出站。");const a=r("{mode}生效:上游收到的 system 来自{source}{lines}。",{mode:e.mode==="custom"?r("替换"):r("追加"),source:xP(e.source),lines:e.lines?r("({n} 行)",{n:e.lines}):""});return e.fileError?`${a} ⚠️ ${e.fileError}`:a}function aee({item:e,option:t,over:a,locked:o,busy:c}){const d=e.gateway,f=t.gatewayChars,p=f?r("约 {n} 字符",{n:f.toLocaleString("zh-CN")}):r("一段内置装配"),h=GJ(a);return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{className:"prompt-gateway-label",children:r("网关自带")}),s.jsxs("span",{className:"prompt-input",children:[s.jsx(Ur,{id:`settings-prompt-gateway-${e.id}`,label:r("装上{size}的官方身份提示词",{size:p}),checked:d,disabled:o||c,onCheckedChange:b=>{kJ(e.id,b)}}),s.jsx(qJ,{item:e,option:t,over:a,locked:o,busy:c})]}),s.jsxs("div",{className:d?"hint":"hint prompt-gateway-off",children:[d?t.gatewayNote:r("已关闭。{note}",{note:t.gatewayNote}),h?r(" 正文已改:{edited}(其余段用官方原文)。",{edited:h}):""]})]})}function lee({prompt:e,locked:t,busy:a}){const o=e.options,c=new Map(e.providers.map(w=>[w.id,w])),d=[];for(const w of o)w.gatewayNote&&d.push(c.get(w.id)??{id:w.id,mode:e.mode,file:e.file,text:e.text,source:e.source,lines:e.lines,fileError:e.fileError,gateway:e.gateway[w.id]??!0,configured:!1});for(const w of e.providers)d.some(k=>k.id===w.id)||d.push({...w,gateway:e.gateway[w.id]??!0,configured:!0});const f=new Set(d.map(w=>w.id)),p=o.filter(w=>!w.gatewayNote&&!f.has(w.id)),[h,b]=x.useState(""),y=w=>o.find(k=>k.id===w)?.label||w,v=w=>o.find(k=>k.id===w),j=w=>v(w)?.gatewayNote||"";return s.jsxs(s.Fragment,{children:[d.map(w=>{const k=y(w.id),S=$o.find(P=>P.value===w.mode)?.optionLabel??w.mode,N=j(w.id),R=v(w.id);return s.jsxs(x.Fragment,{children:[s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:`settings-prompt-mode-${w.id}`,children:k}),s.jsxs("span",{className:"prompt-input",children:[s.jsxs(dt,{value:w.mode,onValueChange:P=>{P!=null&&String(P)&&jJ(w,String(P))},children:[s.jsx(pt,{id:`settings-prompt-mode-${w.id}`,className:"w-[240px]",disabled:t||a,"aria-label":r("{label} 的提示词模式",{label:k}),children:s.jsx(ft,{children:S})}),s.jsx(mt,{children:$o.map(P=>s.jsx($e,{value:P.value,children:P.optionLabel},P.value))})]}),s.jsx(see,{item:w,label:k,locked:t,busy:a}),s.jsx(FJ,{item:w,label:k,locked:t,busy:a}),w.configured?s.jsx(ne,{variant:"outline",disabled:t||a,onClick:()=>{NJ(w.id)},children:r("跟随默认")}):null]}),s.jsx("div",{className:"hint",children:ree(w,w.configured)})]}),R&&N?s.jsx(aee,{item:w,option:R,over:e.gatewayText[w.id],locked:t,busy:a}):null]},w.id)}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-prompt-provider-add",children:r("添加提供商")}),s.jsx("span",{className:"prompt-input",children:s.jsxs(dt,{value:h,onValueChange:w=>{b("");const k=w==null?"":String(w);k&&yJ(k)},children:[s.jsx(pt,{id:"settings-prompt-provider-add",className:"w-[240px]",disabled:t||a||p.length===0,"aria-label":r("添加要单独配置的提供商"),children:s.jsx(ft,{children:h?y(h):p.length?r("添加提供商…"):r("全部已配置")})}),s.jsx(mt,{children:p.map(w=>s.jsx($e,{value:w.id,children:w.label},w.id))})]})}),s.jsx("div",{className:"hint",children:Un.promptProviders})]})]})}function oee({snap:e}){const t=e.prompt,a=t.status!=="ready",o=e.busy==="prompt",c=$o.find(d=>d.value===t.mode)?.optionLabel??t.mode;return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("系统提示词"),tip:Jn.prompt,badge:t.status==="ready"?s.jsx(Jt,{tone:"ok",children:t.mode==="passthrough"?r("透传"):r("已接管")}):t.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(Cr,{id:"btn-prompt-refresh",onClick:()=>{BJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[s.jsxs("div",{className:"prompt-group",children:[r("全局配置"),s.jsx("span",{className:"note",children:r("所有未单独配置的提供商都用这一份")})]}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-prompt-mode",children:r("模式")}),s.jsx("span",{className:"prompt-input",children:s.jsxs(dt,{value:t.mode,onValueChange:d=>{d!=null&&String(d)&&xJ(String(d))},children:[s.jsx(pt,{id:"settings-prompt-mode",className:"w-[240px]",disabled:a||o,"aria-label":r("系统提示词模式"),children:s.jsx(ft,{children:c})}),s.jsx(mt,{children:$o.map(d=>s.jsx($e,{value:d.value,children:d.optionLabel},d.value))})]})}),s.jsx("div",{className:"hint",children:Un.promptMode})]}),s.jsx(eee,{prompt:t,locked:a,busy:o}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"btn-prompt-edit-body",children:r("提示词正文")}),s.jsx("span",{className:"prompt-input",children:s.jsx(VJ,{prompt:t,locked:a,busy:o})}),s.jsxs("div",{className:"hint",children:[Un.promptText,t.source==="inline"?r("(当前生效的就是这一份,{n} 行)",{n:t.lines}):t.text.trim()?r("(已存一份正文,{n} 行;切成「替换 / 追加」后生效)",{n:t.lines}):""]})]}),s.jsxs("div",{className:"prompt-group",children:[r("按提供商配置"),s.jsx("span",{className:"note",children:r("只列单独配置过的家,其余沿用上面的全局配置")})]}),s.jsx(lee,{prompt:t,locked:a,busy:o}),t.status==="ready"&&t.degradeActive?s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{children:r("内容拦截降级")}),s.jsx("span",{className:"prompt-input",children:s.jsx(ne,{id:"btn-prompt-clear-degrade",variant:"outline",disabled:o,onClick:()=>{TJ()},children:r("立即解除")})}),s.jsx("div",{className:"hint",children:nee(t)})]}):null]}),s.jsx("div",{className:"settings-state",children:tee(t)}),s.jsx("div",{className:"hint retention-note",children:Un.prompt})]})]})}function iee(e){if(e.status==="loading")return kt.appLoading;if(e.status==="unavailable")return kt.debugUnavailable;const t=e.count!==null&&e.limit!==null?r("已保存 {count} / {limit} 条报文(超出后丢弃最旧的)。",{count:e.count,limit:e.limit}):"";return e.on?`${kt.debugOn}${t}${r("凭据类请求头已脱敏。")}`:kt.debugOff}function cee({snap:e}){return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("请求超时"),tip:Jn.timeouts,badge:Lp(e.timeouts),actions:s.jsx(Cr,{id:"btn-timeouts-refresh",onClick:()=>{OJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:FI.map(t=>s.jsx(_p,{field:t,value:e.timeouts.values?.[t.key]??null,disabled:e.busy==="timeouts",onCommit:a=>sJ(t,a)},t.key))}),s.jsx("div",{className:"hint retention-note",children:Un.timeouts})]})]})}function uee({snap:e}){return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("请求重试"),tip:Jn.retry,badge:Lp(e.retry),actions:s.jsx(Cr,{id:"btn-retry-refresh",onClick:()=>{RJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[VI.map(t=>s.jsx(_p,{field:t,value:e.retry.values?.[t.key]??null,disabled:e.busy==="retry",onCommit:a=>JW(t,a)},t.key)),s.jsx(JJ,{codes:e.retryCodes,status:e.retry.status,busy:e.busy==="codes"||e.busy==="retry"})]}),s.jsx("div",{className:"hint retention-note",children:Un.retry})]})]})}const dee={routingFailoverBackoff:"failoverBackoff",routingSink:"sink",routingBreakerEnabled:"breakerEnabled"};function fee({snap:e}){const t=e.routing,a=e.busy==="routing"||t.status!=="ready",o=_x.find(d=>d.value===t.strategy)?.value??"order",c=Lx.find(d=>d.value===t.sticky)?.value??"auto";return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("账号路由"),tip:Jn.routing,badge:t.status==="ready"?void 0:t.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(Cr,{id:"btn-routing-refresh",onClick:()=>{IJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[s.jsx("div",{className:"prompt-group",children:r("选路规则")}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{children:r("路由策略")}),s.jsxs("div",{className:"routing-row",children:[s.jsx("span",{className:"tip-q","data-tip":_x.find(d=>d.value===o)?.tip}),s.jsx(En,{options:_x.map(d=>({value:d.value,label:d.label})),value:o,disabled:a,"aria-label":r("路由策略"),onValueChange:d=>{wS({routingStrategy:String(d)})}})]})]}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{children:r("会话粘性")}),s.jsxs("div",{className:"routing-row",children:[s.jsx("span",{className:"tip-q","data-tip":Lx.find(d=>d.value===c)?.tip}),s.jsx(En,{options:Lx.map(d=>({value:d.value,label:d.label})),value:c,disabled:a,"aria-label":r("会话粘性"),onValueChange:d=>{wS({routingSticky:String(d)})}})]})]}),s.jsxs("div",{className:"prompt-group",children:[r("自愈保护"),s.jsx("span",{className:"note",children:r("默认值通常够用,出问题时才需要调")})]}),kW.map(d=>{const f=`route-protection-${d.key}`;return s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:f,children:d.label}),s.jsxs("div",{className:"routing-row",children:[s.jsx("span",{className:"tip-q","data-tip":d.tip}),s.jsx(Zn,{id:f,checked:t[dee[d.key]],disabled:a,onCheckedChange:p=>{wS({[d.key]:p})}})]})]},d.key)})]}),s.jsx("div",{className:"hint retention-note",children:Un.routing})]})]})}function pee({snap:e}){return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("排队等待"),tip:Jn.queue,badge:Lp(e.queue),actions:s.jsx(Cr,{id:"btn-queue-refresh",onClick:()=>{MJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:$I.map(t=>s.jsx(_p,{field:t,value:e.queue.values?.[t.key]??null,disabled:e.busy==="queue",onCommit:a=>GW(t,a)},t.key))}),s.jsx("div",{className:"hint retention-note",children:Un.queue})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("验证码令牌池"),tip:Jn.captchaPool,badge:Lp(e.captchaPool),actions:s.jsx(Cr,{id:"btn-captcha-pool-refresh",onClick:()=>{DJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:QI.map(t=>s.jsx(_p,{field:t,value:e.captchaPool.values?.[t.key]??null,disabled:e.busy==="captchaPool",onCommit:a=>KW(t,a)},t.key))}),s.jsx("div",{className:"hint retention-note",children:Un.captchaPool})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("models.dev 模型元数据"),tip:Jn.modelsDev,badge:e.modelsDev.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("{count} 条",{count:Number(e.modelsDev.count).toLocaleString("zh-CN")})}):e.modelsDev.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(Cr,{id:"btn-modelsdev-refresh",onClick:()=>{dJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx(Ur,{id:"settings-modelsdev",label:r("用 models.dev 补齐上游没声明的模型能力与思考档位(联网刷新,内嵌快照始终生效)"),checked:e.modelsDev.enabled,disabled:e.modelsDev.status!=="ready"||e.busy==="modelsDev",onCheckedChange:t=>{uJ(t)}}),s.jsx("div",{className:"settings-state",children:hW(e.modelsDev)}),s.jsx("div",{className:"hint retention-note",children:Un.modelsDev})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("指纹脱敏"),tip:Jn.sanitize,badge:e.sanitize.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):e.sanitize.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(Cr,{id:"btn-sanitize-refresh",onClick:()=>{_J()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-sanitize",label:r("剥离上游审核黑名单指纹(改写请求体里的模板句与表头)"),checked:e.sanitize.on,disabled:e.sanitize.status!=="ready"||e.busy==="sanitize",onCheckedChange:t=>{aJ(t)}})}),s.jsx("div",{className:"settings-state",children:e.sanitize.status==="loading"?kt.appLoading:e.sanitize.status==="unavailable"?kt.sanitizeUnavailable:e.sanitize.on?kt.sanitizeOn:kt.sanitizeOff}),s.jsx("div",{className:"hint retention-note",children:Un.sanitize})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("开发者角色兼容"),tip:Jn.developerRoleCompat,badge:e.developerRoleCompat.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):e.developerRoleCompat.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(Cr,{id:"btn-role-compat-refresh",onClick:()=>{LJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-developer-role-compat",label:r("转发前将 developer 角色消息转换为 system,兼容不支持 developer 角色的 OpenAI 兼容上游"),checked:e.developerRoleCompat.on,disabled:e.developerRoleCompat.status!=="ready"||e.busy==="developerRoleCompat",onCheckedChange:t=>{lJ(t)}})}),s.jsx("div",{className:"settings-state",children:e.developerRoleCompat.status==="loading"?kt.appLoading:e.developerRoleCompat.status==="unavailable"?kt.roleCompatUnavailable:e.developerRoleCompat.on?kt.roleCompatOn:kt.roleCompatOff}),s.jsx("div",{className:"hint retention-note",children:Un.developerRoleCompat})]})]}),s.jsx(hee,{snap:e}),s.jsx(oee,{snap:e}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("调试模式"),tip:Jn.debug,badge:e.debug.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):e.debug.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(Cr,{id:"btn-debug-refresh",onClick:()=>{PJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-debug-mode",label:r("保存上游原始报文(请求头、请求体、响应头、响应体)"),checked:e.debug.on,disabled:e.debug.status!=="ready"||e.busy==="debug",onCheckedChange:t=>{rJ(t)}})}),s.jsx("div",{className:"settings-state",children:iee(e.debug)}),s.jsx("div",{className:"hint retention-note",children:Un.debug})]})]})]})}function bP(e){const t=Object.entries(e.defaults).map(([a,o])=>({key:a,value:a in e.overrides?e.overrides[a]:o,isDefault:!0}));for(const[a,o]of Object.entries(e.overrides))a in e.defaults||t.push({key:a,value:o,isDefault:!1});return t}function mee(e,t){const a=Object.keys(e);return a.length!==Object.keys(t).length?!1:a.every(o=>e[o]===t[o])}function hee({snap:e}){const t=e.clineHeaders,[a,o]=x.useState(()=>bP(t));x.useEffect(()=>{o(bP(t))},[t]);const c=e.busy==="clineHeaders",d=t.status==="ready";function f(b,y){o(v=>v.map((j,w)=>w===b?{...j,...y}:j))}function p(){const b={};for(const y of a){const v=y.key.trim();v&&(y.isDefault?y.value!==(t.defaults[v]??"")&&(b[v]=y.value):y.value!==""&&(b[v]=y.value))}return b}const h=d&&!mee(p(),t.overrides);return s.jsx(KJ,{title:r("Cline 伪装头"),tip:Jn.clineHeaders,badge:t.status==="ready"?s.jsx(Jt,{tone:"ok",children:r("已生效")}):t.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(Cr,{id:"btn-cline-headers-refresh",onClick:()=>{oJ()}}),children:s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[d?a.map((b,y)=>s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(Fe,{className:"w-[190px] shrink-0 font-mono text-[13px]",value:b.key,readOnly:b.isDefault,disabled:c,placeholder:"X-Custom-Header",onChange:v=>f(y,{key:v.target.value})}),s.jsx(Fe,{className:"flex-1 font-mono text-[13px]",value:b.value,disabled:c,placeholder:b.isDefault?r("值(留空 = 不发送)"):r("值"),onChange:v=>f(y,{value:v.target.value})}),s.jsx(ne,{variant:"ghost",disabled:c,onClick:()=>{b.isDefault?f(y,{value:t.defaults[b.key]??""}):o(v=>v.filter((j,w)=>w!==y))},children:b.isDefault?r("还原"):r("删除")})]},String(y))):null,s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(ne,{variant:"outline",disabled:c||!d,onClick:()=>o(b=>[...b,{key:"",value:"",isDefault:!1}]),children:r("添加自定义头")}),s.jsx("div",{className:"flex-1"}),s.jsx(ne,{variant:"ghost",disabled:c||!d||Object.keys(t.overrides).length===0,onClick:()=>{fP({})},children:r("恢复默认")}),s.jsx(ne,{disabled:c||!d||!h,onClick:()=>{fP(p())},children:r("保存")})]})]}),s.jsx("div",{className:"settings-state",children:t.status==="loading"?kt.appLoading:t.status==="unavailable"?r("未能读取 Cline 伪装头设置,请稍后重试"):h?r("有未保存的修改"):r("{n} 个头将随每个 Cline 请求发送",{n:Object.keys(t.effective).length})+(Object.keys(t.overrides).length>0?r("({n} 项被覆盖)",{n:Object.keys(t.overrides).length}):r("(全部为默认值)"))}),s.jsx("div",{className:"hint retention-note",children:Un.clineHeaders})]})})}function gee({snap:e}){const[t,a]=x.useState(!1);async function o(){a(!0),await EJ()||a(!1)}return s.jsxs(s.Fragment,{children:[s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("网关跨域访问(CORS)"),tip:Jn.cors,badge:e.cors.status==="ready"?e.cors.on?s.jsx(Jt,{tone:"bad",children:r("已开启")}):s.jsx(Jt,{tone:"ok",children:r("已关闭")}):e.cors.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:"idle",children:r("检测中…")}),actions:s.jsx(Cr,{id:"btn-cors-refresh",onClick:()=>{zJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"settings-switches",children:s.jsx(Ur,{id:"settings-cors",label:r("允许浏览器里的页面跨来源调用网关(/v1/*)"),checked:e.cors.on,disabled:e.cors.status!=="ready"||e.busy==="cors",onCheckedChange:c=>{iJ(c)}})}),s.jsx("div",{className:"settings-state",children:e.cors.status==="loading"?kt.appLoading:e.cors.status==="unavailable"?kt.corsUnavailable:e.cors.on?kt.corsOn:kt.corsOff}),s.jsx("div",{className:"hint retention-note",children:Un.cors})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("机器人校验")}),s.jsxs("div",{className:"panel-body",children:[s.jsx(Ur,{id:"settings-captcha",label:r("登录 / 注册需要通过 ALTCHA 人机验证(工作量证明)"),checked:e.captcha.enabled,disabled:!e.captcha.available||e.busy==="captcha",onCheckedChange:c=>{cJ(c)}}),s.jsx("div",{className:"hint",children:Un.captcha})]})]}),e.panelLogin?s.jsxs("section",{className:"panel",id:"panel-login-section",children:[s.jsx(Gn,{title:r("面板登录")}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"hint",children:Un.panelLogin}),s.jsx("div",{className:"mt-2.5",children:s.jsx(ne,{id:"btn-panel-logout",variant:"outline",disabled:t,onClick:()=>{o()},children:r("退出登录")})})]})]}):null]})}function zp({label:e,value:t}){return s.jsxs("div",{className:"storage-count",children:[s.jsx("span",{className:"k",children:e}),s.jsx("span",{className:"v",children:t})]})}function xee(e){return e.status==="loading"?s.jsx(Jt,{tone:"idle",children:r("检测中…")}):e.status==="unavailable"?s.jsx(Jt,{tone:"bad",children:r("不可用")}):s.jsx(Jt,{tone:e.available?"ok":"bad",children:e.available?r("已生效"):r("数据库不可用")})}function bee({snap:e}){const t=e.busy,a=e.storage,o=tt().workbuddyDesktop?.platform==="web",c=a.status==="ready",d=c&&a.available,f=c&&a.file?a.file:"—",p=h=>d&&h!==null?NW(h):"—";return s.jsxs(s.Fragment,{children:[!o&&s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("整库备份 / 恢复"),tip:Jn.backup,actions:s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:"btn-settings-db-export",variant:"outline",disabled:t==="dbExport"||t==="dbImport",onClick:()=>{BW()},children:r(t==="dbExport"?"备份中…":"备份整库")}),s.jsx(ne,{id:"btn-settings-db-restore",variant:"destructive",disabled:t==="dbExport"||t==="dbImport",onClick:()=>HW(),children:r(t==="dbImport"?"恢复中…":"恢复整库")})]})}),s.jsxs("div",{className:"panel-body",children:[e.dbWarning?s.jsxs("div",{className:"danger-zone",id:"settings-db-warning",children:[s.jsx("strong",{children:r("⚠️ 密钥警告")}),s.jsx("br",{}),e.dbWarning]}):null,s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"settings-db-include-logs",children:r("包含日志与调试报文")}),s.jsx(Zn,{id:"settings-db-include-logs",checked:e.dbIncludeLogs,disabled:t!==null,onCheckedChange:zW}),s.jsx("div",{className:"hint",children:r("取消勾选后只备份业务数据(账号、配置与余额记录),文件显著变小;事件日志、请求统计与调试报文不会进备份文件。")})]}),s.jsx("div",{className:"danger-zone",children:s.jsx("strong",{children:Un.backupDanger})})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("账号导入 / 导出"),tip:Jn.io,actions:s.jsxs(s.Fragment,{children:[s.jsx(ne,{id:"btn-settings-export",variant:"outline",disabled:t==="export",onClick:()=>{_W()},children:r(t==="export"?"导出中…":"导出账号")}),s.jsx(ne,{id:"btn-settings-import",variant:"default",disabled:t==="import",onClick:()=>{LW()},children:r(t==="import"?"导入中…":"导入账号")})]})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"danger-zone",children:[s.jsx("strong",{children:r("导出文件内含 accessToken / refreshToken / apiKey 等凭证与自定义提供商定义")}),r(",可直接用于登录。请妥善保管,不要外传或上传到公共位置。")]}),e.ioFailure?s.jsx("div",{className:"io-result",children:s.jsxs("span",{className:"text-destructive",children:[r("失败 {n} 个:{detail}",{n:e.ioFailure.failed,detail:e.ioFailure.detail}),e.ioFailure.more?r(" 等"):""]})}):null]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("数据保留"),tip:Jn.retention,badge:Lp(e.retention),actions:s.jsx(Cr,{id:"btn-retention-refresh",onClick:()=>{AJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"retention-list",children:pS.map(h=>s.jsx(_p,{field:h,value:e.retention.values?.[h.key]??null,disabled:e.busy==="retention",onCommit:b=>$W(h,b)},h.key))}),s.jsx("div",{className:"hint retention-note",children:Un.retention})]})]}),s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("数据存储"),tip:Jn.storage,badge:xee(a),actions:s.jsx(Cr,{id:"btn-storage-refresh",onClick:()=>{HJ()}})}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"retention-list",children:[s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"storage-db-path",children:r("数据库文件")}),s.jsx("span",{className:"storage-line",children:s.jsx("span",{className:"storage-path",id:"storage-db-path",title:f,children:f})}),s.jsx("div",{className:"hint",children:Un.storageFile})]}),s.jsxs("div",{className:"retention-row",children:[s.jsx("label",{htmlFor:"storage-db-size",children:r("占用大小")}),s.jsx("span",{className:"storage-line",children:s.jsx("span",{className:"storage-path",id:"storage-db-size",children:d?XI(a.bytes):"—"})}),s.jsx("div",{className:"hint",children:Un.storageSize})]})]}),s.jsxs("div",{className:"retention-list storage-counts",children:[s.jsx(zp,{label:r("账号"),value:p(a.accounts)}),s.jsx(zp,{label:r("事件日志"),value:p(a.logs)}),s.jsx(zp,{label:r("请求记录"),value:p(a.requests)}),s.jsx(zp,{label:r("报表天数"),value:p(a.dailyDays)}),s.jsx(zp,{label:r("调试报文"),value:p(a.debug)})]}),s.jsx("div",{className:"hint retention-note",children:Un.storage})]})]})]})}const vee=[{title:r("问题反馈"),desc:r("遇到 Bug、报错或异常行为"),cta:r("去反馈"),url:"https://github.com/aimod-cc/agent2api/issues/new?template=bug_report.yml"},{title:r("功能建议"),desc:r("想要的新功能或改进想法"),cta:r("提建议"),url:"https://github.com/aimod-cc/agent2api/issues/new?template=feature_request.yml"},{title:r("请求提供商 / 模型支持"),desc:r("希望接入新的提供商或模型"),cta:r("去申请"),url:"https://github.com/aimod-cc/agent2api/issues/new?template=provider_request.yml"}];function yee(){return s.jsxs("section",{className:"panel",children:[s.jsx(Gn,{title:r("反馈与需求")}),s.jsxs("div",{className:"panel-body",children:[s.jsx("div",{className:"hint",children:r("点下面的入口会用系统默认浏览器打开 GitHub 的对应表单(需要 GitHub 账号,模板已预设好,填完直接提交即可)。")}),s.jsx("div",{className:"mt-3 flex flex-col gap-2",children:vee.map(e=>s.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-md border border-hairline bg-surface-2 px-3 py-2.5",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsx("div",{className:"text-[12.5px] text-foreground",children:e.title}),s.jsx("div",{className:"mt-0.5 text-[12px] text-subtle",children:e.desc})]}),s.jsx(ne,{variant:"outline",size:"sm",onClick:()=>{gW(e.url)},children:e.cta})]},e.url))})]})]})}function jee({confirm:e}){const t=x.useRef(null);return s.jsx(Yt,{open:e!==null,onOpenChange:a=>{a||Vx(!1)},children:s.jsxs(Xt,{className:"w-[min(440px,calc(100vw-48px))]",initialFocus:t,children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("确认缩短保留天数")})}),s.jsx(Lt,{children:s.jsxs("div",{className:"danger-zone",children:[e?.head,s.jsx("br",{}),s.jsx("strong",{children:r("超出的历史数据会被立即删除,且不可恢复。")}),r("确定继续?")]})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:t,variant:"outline",onClick:()=>Vx(!1),children:r("取消")}),s.jsx(ne,{variant:"destructive",onClick:()=>Vx(!0),children:r("继续并清理")})]})]})})}const LS={enable:{title:r("开启局域网访问"),body:()=>s.jsxs(s.Fragment,{children:[r("为了安全,开启前需要先注册一个"),s.jsx("b",{children:r("面板管理员账号")}),r("(已注册过会跳过这一步,直接生效)。"),s.jsx("br",{}),r("开启后网关将监听所有网卡,同一局域网内的设备即可把 API 地址指向本机 IP 一起使用;管理接口从此要求管理员会话或网关 Key,转发接口在没有一把启用的 Key 时也会拒绝服务(届时会自动创建一把名为「默认」的 Key)。"),s.jsx("br",{}),s.jsx("strong",{children:r("保存后应用将重启以生效。")}),r("确定继续?")]}),label:r("继续")},disable:{title:r("关闭局域网访问"),body:()=>s.jsxs(s.Fragment,{children:[r("关闭后网关回到只监听 127.0.0.1,局域网内的设备将无法继续访问;已配置的网关 Key 与账号都不受影响。"),s.jsx("br",{}),s.jsx("strong",{children:r("保存后应用将重启以生效。")}),r("确定继续?")]}),label:r("关闭并重启")},panel:{title:r("变更网页管理面板"),body:e=>e?s.jsxs(s.Fragment,{children:[r("开放后,局域网内其他设备的浏览器打开本机 IP 即可进入管理面板(需管理员账号登录)。"),s.jsx("br",{}),s.jsx("strong",{children:r("保存后应用将重启以生效。")}),r("确定继续?")]}):s.jsxs(s.Fragment,{children:[r("关闭后,管理界面不再从局域网提供,只有本机的桌面程序可以管理;已开启的 API 转发不受影响。"),s.jsx("br",{}),s.jsx("strong",{children:r("保存后应用将重启以生效。")}),r("确定继续?")]}),label:r("保存并重启")}};function wee({confirm:e}){const t=x.useRef(null);return s.jsx(Yt,{open:e!==null,onOpenChange:a=>{a||jS(!1)},children:s.jsxs(Xt,{className:"w-[min(440px,calc(100vw-48px))]",initialFocus:t,children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("恢复整库备份")})}),s.jsx(Lt,{children:s.jsxs("div",{className:"danger-zone",children:[r("本机的全部数据(账号、网关配置、日志统计与桌面设置)将被所选备份文件"),s.jsx("strong",{children:r("整体替换")}),r(",包括恢复后需要重新登录管理面板。"),s.jsx("br",{}),s.jsx("strong",{children:r("替换前会自动把当前数据备份到配置目录的 backups/ 文件夹。")}),r("确定继续?")]})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:t,variant:"outline",onClick:()=>jS(!1),children:r("取消")}),s.jsx(ne,{variant:"destructive",onClick:()=>jS(!0),children:r("选择备份文件并恢复")})]})]})})}function See({confirm:e,register:t}){const a=x.useRef(null),o=x.useRef(null),c=x.useRef(null),d=e!==null||t!==null,f=()=>{t!==null?tP():yS(!1)},p=()=>{PW(o.current?.value??"",c.current?.value??"")};return s.jsx(Yt,{open:d,onOpenChange:h=>{h||f()},children:s.jsx(Xt,{className:"w-[min(480px,calc(100vw-48px))]",initialFocus:a,children:t!==null?s.jsxs(s.Fragment,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("注册管理员账号")})}),s.jsxs(Lt,{children:[s.jsx("div",{children:r("局域网开放后,管理接口要求登录。请设置管理员账号与密码,注册完成会直接继续开启流程。")}),s.jsxs("form",{onSubmit:h=>{h.preventDefault(),t.busy||p()},children:[s.jsx(Je,{htmlFor:"lan-admin-name",className:"mt-3.5 mb-[5px] block text-[12.5px]",children:r("账号")}),s.jsx(Fe,{ref:o,id:"lan-admin-name",autoComplete:"username",placeholder:r("管理员账号"),disabled:t.busy}),s.jsx(Je,{htmlFor:"lan-admin-password",className:"mt-3.5 mb-[5px] block text-[12.5px]",children:r("密码")}),s.jsx(Fe,{ref:c,id:"lan-admin-password",type:"password",autoComplete:"new-password",placeholder:r("至少 8 位"),disabled:t.busy})]}),s.jsx("div",{className:"mt-3 min-h-5 text-[13px] whitespace-pre-wrap text-destructive",children:t.error})]}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:a,variant:"outline",onClick:tP,disabled:t.busy,children:r("取消")}),s.jsx(ne,{onClick:p,disabled:t.busy,children:t.busy?r("正在注册…"):r("注册并开启")})]})]}):s.jsxs(s.Fragment,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:e?LS[e.mode].title:""})}),s.jsx(Lt,{children:s.jsx("div",{children:e?LS[e.mode].body(e.panel):null})}),s.jsxs(tn,{children:[s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{ref:a,variant:"outline",onClick:()=>yS(!1),children:r("取消")}),s.jsx(ne,{onClick:()=>yS(!0),children:e?LS[e.mode].label:r("继续")})]})]})})})}function Nee(){const e=EW(),t=x.useRef(null);x.useEffect(()=>{const o=t.current;o&&(o.scrollTop=0)},[e.scrollReset]);const a=o=>e.category===o?"settings-pane active":"settings-pane";return s.jsxs("div",{className:"settings-layout",children:[s.jsx("nav",{className:"settings-nav",id:"settings-nav",children:Ix.map(o=>s.jsxs("button",{type:"button",className:e.category===o.id?"settings-nav-item active":"settings-nav-item","data-cat":o.id,onClick:()=>AW(o.id),children:[s.jsx("span",{className:"ico",dangerouslySetInnerHTML:{__html:gP(o.icon,17)}}),o.label]},o.id))}),s.jsxs("div",{className:"settings-panes",ref:t,children:[s.jsx("div",{className:a("general"),"data-cat":"general",children:s.jsx(XJ,{snap:e})}),s.jsx("div",{className:a("assistant"),"data-cat":"assistant",children:s.jsx(q7,{})}),s.jsx("div",{className:a("display"),"data-cat":"display",children:s.jsx(ZJ,{})}),s.jsx("div",{className:a("gateway"),"data-cat":"gateway",children:s.jsx(pee,{snap:e})}),s.jsx("div",{className:a("routing"),"data-cat":"routing",children:s.jsx(fee,{snap:e})}),s.jsx("div",{className:a("retry"),"data-cat":"retry",children:s.jsx(uee,{snap:e})}),s.jsx("div",{className:a("timeout"),"data-cat":"timeout",children:s.jsx(cee,{snap:e})}),s.jsx("div",{className:a("security"),"data-cat":"security",children:s.jsx(gee,{snap:e})}),s.jsx("div",{className:a("data"),"data-cat":"data",children:s.jsx(bee,{snap:e})}),s.jsx("div",{className:a("feedback"),"data-cat":"feedback",children:s.jsx(yee,{})}),s.jsx("div",{className:a("about"),"data-cat":"about"})]}),s.jsx(jee,{confirm:e.retentionConfirm}),s.jsx(wee,{confirm:e.dbBackupConfirm}),s.jsx(See,{confirm:e.lanConfirm,register:e.lanRegister})]})}const vP='.page[data-page="settings"]';let zS=null;function yP(){if(zS)return;const e=document.querySelector(vP);e&&(e.replaceChildren(),zS=jn.createRoot(e),Ts.flushSync(()=>{zS?.render(s.jsx(Nee,{}))}))}WI(),document.querySelector(vP)?yP():document.addEventListener("DOMContentLoaded",yP,{once:!0}),window.wbSettingsPanel={load:_S,render:bS,renderRetention:Bx,renderRetry:WW,renderDebug:qx,renderSanitize:Gx,renderPrompt:td,renderStorage:PS,showCategory:xS},tt().wbApp?.currentPage==="settings"&&_S();const jP="agent2api-col-config:",BS=[{value:"left",label:r("左")},{value:"center",label:r("中")},{value:"right",label:r("右")}],kee=e=>BS.some(t=>t.value===e),Cee=BS.map(e=>`ta-${e.value}`),wP="colset-dragging",SP="open";let HS=null;const NP="grid grid-cols-[18px_minmax(78px,1fr)_44px_minmax(106px,auto)] items-center gap-2";function kP(){return window}const Xx=new Map;function US(e){return e.columns.map(t=>({key:t.key,visible:t.visible!==!1,align:t.align||"left"}))}function Tee(e,t){const a=Array.isArray(t),o=!a&&t&&typeof t=="object"?t:null,c=a?t:Array.isArray(o?.items)?o.items:[],d=o?.defaults&&typeof o.defaults=="object"?o.defaults:null,f=new Map(e.columns.map(y=>[y.key,y])),p=new Map(US(e).map(y=>[y.key,y])),h=[],b=new Set;for(const y of c){const v=y&&typeof y=="object"?y:{},j=String(v.key||"");if(!f.has(j)||b.has(j))continue;b.add(j);const w=f.get(j),k=w.align||"left",S=d?d[j]??k:w.legacyAlign??k,N=kee(v.align)?v.align:null;h.push({key:j,visible:v.visible!==!1,align:N&&N!==S?N:k})}for(const y of e.columns)b.has(y.key)||Eee(h,e,{...p.get(y.key)});return h}function Eee(e,t,a){const o=t.columns.findIndex(c=>c.key===a.key);for(let c=o-1;c>=0;c-=1){const d=e.findIndex(f=>f.key===t.columns[c].key);if(d>=0){e.splice(d+1,0,a);return}}e.unshift(a)}function Aee(e){try{const t=localStorage.getItem(jP+e.id);return Tee(e,t?JSON.parse(t):[])}catch{return US(e)}}function Ree(e){try{const t={};for(const a of e.columns)t[a.key]=a.align||"left";localStorage.setItem(jP+e.id,JSON.stringify({v:2,defaults:t,items:e.config}))}catch{}}const Oee=e=>Xx.get(e)?.config||null,Mee=(e,t)=>e.columns.find(a=>a.key===t)?.label||t;function CP(e,t){const a=Xx.get(e);if(!a)return t;const o=new Map(t.map(c=>[c.key,c]));return a.config.filter(c=>c.visible&&o.has(c.key)).map(c=>({...o.get(c.key),align:c.align}))}function Bp(e,{silent:t=!1}={}){Ree(e),t||e.onChange?.(e.config),Ll&&Ll.id===e.id&&Ll.repaint()}let Ll=null;function Qx(){if(!Ll)return;const e=Ll;Ll=null,e.destroy()}function Dee(e,t){Qx();const a=document.createElement("div");document.body.append(a);const o=jn.createRoot(a),c={current:null};Ll={id:e.id,spec:e,repaint:()=>c.current?.(),destroy:()=>{o.unmount(),a.remove()}},o.render(s.jsx(zee,{spec:e,anchor:t,repaintRef:c,onClose:Qx}))}function Iee(e,t){Ll&&Ll.id===e.id?Qx():Dee(e,t)}function Pee(e,t,a){const o=[...e],[c]=o.splice(t,1);return o.splice(a,0,c),o}function _ee(e,t,a,o){const c=document.elementFromPoint(e,t)?.closest?.("[data-col-key]");if(!c||!a||!a.contains(c))return"";const d=c.getAttribute("data-col-key")||"";return o.some(f=>f.key===d)?d:""}const Lee=s.jsxs("svg",{viewBox:"0 0 24 24",width:13,height:13,fill:"currentColor","aria-hidden":"true",className:"block",children:[s.jsx("circle",{cx:"9",cy:"6",r:"1.6"}),s.jsx("circle",{cx:"15",cy:"6",r:"1.6"}),s.jsx("circle",{cx:"9",cy:"12",r:"1.6"}),s.jsx("circle",{cx:"15",cy:"12",r:"1.6"}),s.jsx("circle",{cx:"9",cy:"18",r:"1.6"}),s.jsx("circle",{cx:"15",cy:"18",r:"1.6"})]});function zee({spec:e,anchor:t,repaintRef:a,onClose:o}){const c=t,d=x.useRef(null),[f,p]=x.useState(null),h=x.useRef(null),[,b]=x.useState(0),y=x.useCallback(()=>b(S=>S+1),[]);x.useLayoutEffect(()=>(a.current=y,()=>{a.current=null}),[y,a]),x.useEffect(()=>(c.classList.add(SP),c.setAttribute("aria-expanded","true"),()=>{c.classList.remove(SP),c.setAttribute("aria-expanded","false")}),[c]),x.useEffect(()=>{const S=()=>{const N=c.getBoundingClientRect();(!c.isConnected||!N.width||N.bottom<=0||N.top>=window.innerHeight)&&o()};return window.addEventListener("scroll",S,!0),window.addEventListener("resize",S),()=>{window.removeEventListener("scroll",S,!0),window.removeEventListener("resize",S)}},[c,o]),x.useEffect(()=>()=>{const S=h.current;S&&(S.teardown(),Bp(e))},[e]);function v(S,N){const R=e.config.find(P=>P.key===S);R&&(!N&&e.config.filter(P=>P.visible).length<=1||(R.visible=N,Bp(e)))}function j(S,N){const R=e.config.find(P=>P.key===S);!R||R.align===N||(R.align=N,Bp(e))}function w(){e.config=US(e),Bp(e)}function k(S,N){N.preventDefault(),h.current?.teardown(),p(S),document.body.classList.add(wP);const R=d.current;function P(){window.removeEventListener("pointermove",T),window.removeEventListener("pointerup",C),document.body.classList.remove(wP),h.current=null,p(null)}function T(E){const D=_ee(E.clientX,E.clientY,R,e.config);if(!D||D===S)return;const I=e.config.findIndex(_=>_.key===S),O=e.config.findIndex(_=>_.key===D);I<0||O<0||(e.config=Pee(e.config,I,O),y())}function C(){P(),Bp(e)}h.current={teardown:P},window.addEventListener("pointermove",T),window.addEventListener("pointerup",C)}return s.jsx(wf,{open:!0,modal:!1,onOpenChange:(S,N)=>{S||(N?.reason==="outside-press"&&(HS=N.event??null),o())},children:s.jsxs(Sf,{anchor:c,side:"bottom",align:"end",sideOffset:6,collisionPadding:8,className:"w-[336px]","aria-label":r("{name}的列设置",{name:e.label||e.id}),children:[s.jsxs("div",{className:Ue(NP,"border-b border-hairline px-3 pt-[9px] pb-[7px]","text-[10.5px] font-semibold tracking-[.05em] text-muted-foreground"),children:[s.jsx("span",{}),s.jsx("span",{className:"text-center",children:r("列")}),s.jsx("span",{className:"text-center",children:r("显示")}),s.jsx("span",{className:"text-center",children:r("对齐")})]}),s.jsx("div",{ref:d,className:"min-h-0 flex-1 overflow-y-auto px-3 py-1",children:e.config.map(S=>{const N=Mee(e,S.key),R=f===S.key;return s.jsxs("div",{"data-col-key":S.key,className:Ue(NP,"rounded-sm py-[5px] hover:bg-nav-hover",R&&"opacity-50"),children:[s.jsx("span",{className:"flex cursor-grab items-center justify-center text-muted-foreground opacity-50 hover:opacity-100",title:r("按住拖动调整列顺序"),onPointerDown:P=>k(S.key,P),children:Lee}),s.jsx("span",{className:"min-w-0 truncate text-xs text-foreground",title:N,children:N}),s.jsx(Zn,{className:"justify-self-center",checked:S.visible,onCheckedChange:P=>v(S.key,P),"aria-label":r("显示「{label}」列",{label:N}),title:S.visible?r("这一列正在显示"):r("这一列已隐藏")}),s.jsx(En,{className:"w-full justify-center",options:BS,value:S.align,onValueChange:P=>j(S.key,P),"aria-label":r("「{label}」列的对齐",{label:N})})]},S.key)})}),s.jsxs("div",{className:"flex items-center gap-2 border-t border-hairline px-3 pt-2 pb-[9px]",children:[s.jsx("span",{className:"flex-1 text-[11px] text-muted-foreground",children:r("拖动 ⋮⋮ 调整顺序")}),s.jsx(ne,{variant:"outline",size:"sm",onClick:w,children:r("恢复默认")})]})]})})}function Bee(e,t){e&&(e.classList.remove(...Cee),e.classList.add(`ta-${t}`))}const TP=new Map;function Hee(e,t){const a=TP.get(e);if(a&&a.table===t&&a.row.isConnected)return a;const o=t?.querySelector("thead tr");if(!o)return null;const c=t?.querySelector("colgroup")??null,d={table:t,row:o,group:c,ths:new Map([...o.querySelectorAll("th[data-col]")].map(f=>[f.getAttribute("data-col")||"",f])),cols:new Map([...c?.querySelectorAll("col[data-col]")||[]].map(f=>[f.getAttribute("data-col")||"",f]))};return TP.set(e,d),d}function Uee(e,t,a){const o=Xx.get(e);if(!o||!t)return;const c=Hee(e,t);if(!c)return;const{row:d,group:f,ths:p,cols:h}=c;for(const b of o.config){const y=p.get(b.key);if(!y)continue;const v=h.get(b.key);if(!b.visible||a?.has(b.key)){y.remove(),v?.remove();continue}Bee(y,b.align),d.appendChild(y),v&&f&&f.appendChild(v)}kP().wbTableColumns?.repaint?.(e)}function Vee(e){const t=document.createElement("button");return t.type="button",t.className=`sm colset-btn${e.buttonClass?` ${e.buttonClass}`:""}`,t.id=`btn-colset-${e.id}`,t.title=r("调整「{name}」的列:显示 / 隐藏、顺序、对齐",{name:e.label||e.id}),t.innerHTML=`${kP().wbIcons?.icon?.("settings",14)||""}${r("列设置")}`,t.setAttribute("aria-haspopup","dialog"),t.setAttribute("aria-expanded","false"),t.addEventListener("click",a=>{if(HS===a){HS=null;return}Iee(e,t)}),t}function Fee(e){return(typeof e.mount=="function"?e.mount():e.mount?document.querySelector(e.mount):null)||null}function $ee(e){const t={...e,config:Aee(e)};Xx.set(e.id,t);const a=Fee(e),o=Vee(t);return a&&(e.buttonPlacement==="last"?a.appendChild(o):a.insertBefore(o,a.firstChild)),{apply:c=>CP(e.id,c),config:()=>t.config}}window.wbColSettings={register:$ee,apply:CP,configOf:Oee,syncStaticHead:Uee,close:Qx};function rl(){return window}const qee=new Set(["updateCheck"]);function EP(e){return(Array.isArray(e?.tasks)?e.tasks:[]).filter(a=>!qee.has(a.id))}const Gee=2e4,AP=1,Kee=" · ";function nd(e,t){rl().wbApp?.toast?.(e,t)}function Zx(e){return e instanceof Error?e.message:String(e)}function RP(e){return r(e==="seconds"?"秒":"分钟")}function OP(e){const t=Number(e)||0;return t?new Date(t).toLocaleTimeString("zh-CN",{hour12:!1}):""}function MP(e){const t=Number(e)||0;if(!t)return"";const a=t-Date.now();if(a<=0)return r("即将执行");const o=Math.round(a/1e3);if(o<60)return r("{n} 秒后",{n:o});const c=Math.round(o/60);if(c<60)return r("{n} 分钟后",{n:c});const d=Math.round(c/60);return d<24?r("{n} 小时后",{n:d}):r("{n} 天后",{n:Math.round(d/24)})}function Yee(e){const t=e.runner==="backend",a=[];if(e.lastRunAt){const o=OP(e.lastRunAt);a.push(e.lastResult?r("上次执行 {time}({result})",{time:o,result:e.lastResult}):r("上次执行 {time}",{time:o}))}else a.push(r(t?"还没有执行记录":"由页面按间隔自动刷新"));return t&&e.enabled&&e.nextRunAt&&a.push(r("下次执行 {time}({relative})",{time:OP(e.nextRunAt),relative:MP(e.nextRunAt)})),t&&e.retryAt&&e.retryAt>Date.now()&&a.push(r("冷却中,{relative}重试",{relative:MP(e.retryAt)})),a.join(Kee)}function Xee(e,t){const a=String(t??"").trim(),o=RP(e.unit);if(!a)return{ok:!1,message:r("间隔不能为空(可填 {min}–{max} {unit})",{min:e.min,max:e.max,unit:o})};if(!/^\d+$/.test(a))return{ok:!1,message:r("间隔必须是整数")};const c=Number(a);return ce.max?{ok:!1,message:r("间隔必须在 {min}–{max} {unit} 之间(当前填的是 {value})",{min:e.min,max:e.max,unit:o,value:a})}:{ok:!0,value:c}}function Qee(e){const t=rl();e.id==="logsAutoRefresh"?t.wbLogsPanel?.applyAutoRefresh?.(e):e.id==="requestsAutoRefresh"?t.wbRequestsPanel?.applyAutoRefresh?.(e):e.id==="reportAutoRefresh"&&t.wbReport?.applyAutoRefresh?.(e)}let mc=!1,Wx=null,VS=!1;async function DP(){if(!Wx){VS=!0;return}await Wx()}function Zee(){const[e,t]=x.useState([]),[a,o]=x.useState(!1),[c,d]=x.useState(null),[f,p]=x.useState({});function h(D){p(I=>{if(!(D in I))return I;const O={...I};return delete O[D],O})}const b=x.useCallback(async()=>{const D=rl().workbuddyDesktop;try{if(!D)throw new Error(r("后端桥不可用"));const I=await D.getScheduledTasks();t(EP(I)),o(!0)}catch(I){console.warn("读取定时任务失败:",Zx(I)),t([]),o(!0)}},[]),y=x.useCallback(async()=>{if(mc||document.hidden||rl().wbApp?.currentPage!=="tasks")return;const D=rl().workbuddyDesktop;if(D)try{const I=await D.getScheduledTasks();t(EP(I))}catch(I){console.warn("同步定时任务状态失败:",Zx(I))}},[]);x.useEffect(()=>{const D=window.setInterval(()=>{y()},Gee);return()=>{window.clearInterval(D)}},[y]),x.useEffect(()=>{rl().wbApp?.renderTopbarStatus?.()},[e,a]),x.useEffect(()=>(Wx=b,VS&&(VS=!1,b()),()=>{Wx=null}),[b]);async function v(D,I,O){if(mc)return;const _=rl().workbuddyDesktop;if(_){mc=!0;try{const z=await _.saveScheduledTask(D,I);t(H=>H.map(B=>B.id===D?z:B)),Qee(z),nd(r("✅ 已更新「{label}」",{label:O}))}catch(z){nd(r("保存失败:{reason}",{reason:Zx(z)}),"err"),await b()}finally{mc=!1}}}async function j(D,I){const O=Xee(D,I);if(!O.ok){nd(O.message,"err"),h(D.id);return}if(O.value===D.interval){h(D.id);return}await v(D.id,{interval:O.value},r("{name}间隔",{name:r(D.label)})),h(D.id)}async function w(D){if(mc)return;const I=rl().workbuddyDesktop;if(I){mc=!0,d(D.id);try{const O=await I.runScheduledTask(D.id);if(O?.task){const _=O.task;t(z=>z.map(H=>H.id===D.id?_:H))}nd(r("✅ {task}:{summary}",{task:r(D.label),summary:O?.summary||r("已执行")})),D.id==="credentialMaintenance"&&await rl().wbApp?.refresh?.()}catch(O){nd(r("执行失败:{reason}",{reason:Zx(O)}),"err"),await b()}finally{mc=!1,d(null)}}}function k(D){const I=RP(D.unit),O=c===D.id;return s.jsxs("div",{className:"task-item","data-task":D.id,children:[s.jsxs("div",{className:"task-main",children:[s.jsxs("div",{className:"task-title",children:[s.jsxs("label",{className:"switch",children:[s.jsx(Zn,{checked:D.enabled===!0,onCheckedChange:_=>{v(D.id,{enabled:_},r("{name}开关",{name:r(D.label)}))}}),s.jsx("span",{className:"task-name",children:r(D.label)})]}),s.jsx("span",{className:"tip-q","data-tip":r(D.description)}),s.jsx(ze,{className:"task-badge",variant:D.enabled?"success":"outline",children:D.enabled?r("已开启"):r("已关闭")}),D.running?s.jsx(ze,{className:"task-badge",variant:"warning",children:r("执行中…")}):null]}),s.jsx("div",{className:"task-state",children:Yee(D)})]}),s.jsxs("div",{className:"task-actions",children:[s.jsxs("span",{className:"task-interval",children:[s.jsx("span",{className:"task-interval-label",children:r("每")}),s.jsx(Fe,{type:"number",inputMode:"numeric",min:D.min,max:D.max,step:1,className:"w-[74px] max-w-[74px] text-center tabular-nums",value:f[D.id]??String(D.interval),title:r("可填 {min}–{max} {unit}(默认 {def} {unit})",{min:D.min,max:D.max,unit:I,def:D.defaultInterval}),onChange:_=>{const z=_.currentTarget.value;p(H=>({...H,[D.id]:z}))},onBlur:_=>{j(D,_.currentTarget.value)},onKeyDown:_=>{_.key==="Enter"&&_.currentTarget.blur()}}),s.jsx("span",{className:"task-interval-unit",children:I})]}),D.canRun===!0?s.jsx(ne,{size:"sm",variant:"outline",disabled:O||D.running===!0,onClick:()=>{w(D)},children:r(O?"执行中…":"立即执行")}):null]})]},D.id)}const S=e.length===0,N=e.filter(D=>D.enabled).length,R=S?a?r("不可用"):"—":r("{enabled} / {total} 个已开启",{enabled:N,total:e.length}),P=S?a?"destructive":"outline":N?"success":"outline",T=P==="destructive"?"bad":P==="success"?"ok":"",C=e.map(D=>k(D)),E=C.slice(AP);return s.jsxs("section",{className:"panel",children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("任务清单")}),s.jsx(ze,{id:"tasks-badge",variant:P,"data-tone":T,children:R}),s.jsx("span",{className:"panel-sub",children:r("状态每 20 秒自动同步")}),s.jsx("div",{className:"head-actions",children:s.jsx(ne,{variant:"outline",onClick:()=>{b().then(()=>nd(r("定时任务已刷新")))},children:r("刷新")})})]}),s.jsx("div",{className:"panel-body",children:s.jsx("div",{className:"task-list",children:S?s.jsx("div",{className:"log-empty",children:r(a?"没有可显示的定时任务。后端未返回任务清单,请确认网关正在运行。":"正在加载定时任务…")}):s.jsxs(s.Fragment,{children:[C.slice(0,AP),E.length?s.jsx("div",{className:"task-grid",children:E}):null]})})}),s.jsxs("div",{className:"panel-foot",children:[s.jsxs("span",{children:[r("任务配置保存在 "),s.jsx("code",{children:"~/.agent2api/config.json"}),r(" 的 "),s.jsx("code",{children:"scheduledTasks"}),r(" 字段")]}),s.jsx("span",{children:r("改动立即生效,不需要重启程序")})]})]})}const IP='.page[data-page="tasks"]';let PP=!1;function _P(){if(PP)return;const e=document.querySelector(IP);e&&(PP=!0,e.replaceChildren(),jn.createRoot(e).render(s.jsx(Zee,{})))}document.querySelector(IP)?_P():document.addEventListener("DOMContentLoaded",_P,{once:!0}),window.wbTasksPanel={load:DP},rl().wbApp?.currentPage==="tasks"&&DP();const LP="workbuddy-desktop-update-skip";function Wee(){try{return localStorage.getItem(LP)||""}catch{return""}}function Jee(e){try{localStorage.setItem(LP,e)}catch{}}let zP="";function Jx(e,t){if(!e||e.hasUpdate!==!0||e.pendingRestart===!0)return;const a=String(e.latestVersion||"").trim();a&&nn().wbApp?.currentPage!=="settings"&&(a===Wee()||a===zP||(zP=a,BP(),sd=document.createElement("div"),document.body.append(sd),Hp=jn.createRoot(sd),Hp.render(s.jsx(ete,{info:e,onGoUpdate:t,onClose:BP}))))}function ete({info:e,onGoUpdate:t,onClose:a}){const o=String(e.latestVersion||""),c=String(e.notes||"").trim(),d=c?pD(c):"";function f(){Jee(o),a()}function p(){a();const h=nn();h.wbApp?.showPage?.("settings"),h.wbSettingsPanel?.showCategory?.("about"),t(e)}return s.jsx(Yt,{open:!0,onOpenChange:h=>{h||a()},children:s.jsxs(Xt,{children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("检测到更新")})}),s.jsxs(Lt,{children:[s.jsxs("p",{className:"text-[12.5px] leading-[1.6] text-subtle",children:[r("新版本 "),s.jsx("strong",{className:"text-foreground",children:o}),r(" 已发布(当前 {current}),更新日志如下:",{current:e.currentVersion||r("未知")})]}),s.jsx("div",{className:"max-h-[46vh] overflow-y-auto overscroll-contain pr-1.5",onClick:Xu,children:d?s.jsx("div",{className:"md-body",dangerouslySetInnerHTML:{__html:d}}):s.jsx("div",{className:"md-body",children:s.jsx("p",{className:"md-body-empty",children:r("这个版本没有填写发布说明。")})})})]}),s.jsxs(tn,{children:[s.jsx(ne,{variant:"outline",size:"sm",onClick:f,children:r("跳过此次更新")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:a,children:r("取消")}),s.jsx(ne,{variant:"default",onClick:p,children:r("去更新")})]})]})})}let Hp=null,sd=null;function BP(){Hp&&(Hp.unmount(),Hp=null),sd&&(sd.remove(),sd=null)}const HP="updateCheck",rd=1,eb=1440,tte="https://github.com/settings/tokens/new?description="+encodeURIComponent("Agent2API 更新检查");function nte(e){return e?e.error?{badge:s.jsx(ze,{shape:"tag",variant:"destructive",title:e.error,children:r("无法解密")}),hint:r("重新粘贴保存一次即可自愈")}:e.filled&&e.origin==="stored"?{badge:s.jsx(ze,{shape:"tag",variant:"success",children:r("已填写")}),hint:r("已加密存储在本地,不显示具体值;粘贴新令牌可覆盖")}:e.filled?{badge:s.jsx(ze,{shape:"tag",variant:"secondary",children:r("环境变量")}),hint:r("已配置 GITHUB_TOKEN 环境变量,界面保存的令牌优先于它")}:{badge:s.jsx(ze,{shape:"tag",variant:"outline",children:r("未填写")}),hint:r("填写后检查限额 60 → 5000 次/小时(创建令牌无需勾选任何权限)")}:{badge:s.jsx(ze,{shape:"tag",variant:"outline",children:r("读取中")}),hint:""}}function ste({open:e,onClose:t}){const[a,o]=x.useState(mD),[c,d]=x.useState(null),[f,p]=x.useState(""),[h,b]=x.useState(!1),[y,v]=x.useState(null),[j,w]=x.useState(""),[k,S]=x.useState(!1),[N,R]=x.useState(null),[P,T]=x.useState(!1),C=hD(a);x.useEffect(()=>{e&&(p(""),CX().then(o),(async()=>{try{d(await nn().workbuddyDesktop?.getUpdateToken()??null)}catch{}})(),(async()=>{try{const F=await nn().workbuddyDesktop?.getUpdateBeta();R({enabled:F?.enabled===!0})}catch{}})(),(async()=>{try{const $=((await nn().workbuddyDesktop?.getScheduledTasks?.())?.tasks??[]).find(q=>q.id===HP),X=$?.enabled===!0,K=Math.max(rd,Math.round(Number($?.interval)||0));v({enabled:X,interval:K}),w(String(K))}catch{}})())},[e]);async function E(F){if(!k){S(!0);try{const $=await nn().workbuddyDesktop?.saveScheduledTask?.(HP,F),X=$?.enabled===!0,K=Math.max(rd,Math.round(Number($?.interval)||0));v({enabled:X,interval:K}),w(String(K)),Es(r("✅ 自动检查更新已保存"))}catch($){Es(r("保存失败:{error}",{error:mr($)}),"err")}finally{S(!1)}}}async function D(){const F=Math.round(Number(j));if(!Number.isFinite(F)||Feb){Es(r("检查间隔必须是 {min} ~ {max} 分钟",{min:rd,max:eb}),"err");return}y&&F===y.interval||await E({interval:F})}async function I(F){if(P)return;T(!0);let $=!1;try{const X=await nn().workbuddyDesktop?.setUpdateBeta({enabled:F});R({enabled:X?.enabled===!0}),$=!0,X?.saved===!1?Es(r("通道已切换,但写入磁盘失败(重启后会回到原设置)"),"err"):Es(r(F?"✅ 已加入 beta 版,之后的检查会包含 beta 版":"✅ 已退出 beta 版,之后的检查只看正式版"))}catch(X){Es(r("保存失败:{error}",{error:mr(X)}),"err")}finally{T(!1)}if($)try{await nn().workbuddyDesktop?.checkUpdate(),await kX()}catch{}}async function O(F){const $=await TX(F);$&&o(X=>({...X,proxyChoice:$.choice}))}async function _(){const F=f.trim();if(!F){Es(r("请先粘贴 GitHub 令牌"),"err");return}b(!0);try{const $=await nn().workbuddyDesktop?.setUpdateToken({token:F});d($??null),p(""),$?.saved===!1?Es(r("令牌已生效,但写入磁盘失败(重启后会丢失)"),"err"):Es(r("✅ GitHub 令牌已保存(加密存储,界面不再显示)"))}catch($){Es(r("保存失败:{error}",{error:mr($)}),"err")}finally{b(!1)}}async function z(){b(!0);try{const F=await nn().workbuddyDesktop?.setUpdateToken({token:null});d(F??null),Es(r("✅ 已清除界面保存的 GitHub 令牌(环境变量若配置过则继续生效)"))}catch(F){Es(r("清除失败:{error}",{error:mr(F)}),"err")}finally{b(!1)}}const H=nte(c),B=!!c?.error||c?.origin==="stored",L=c?.filled&&c?.origin!=="env"?r("已填写(粘贴新令牌可覆盖)"):r("粘贴 GitHub 令牌(ghp_… / github_pat_…)");return s.jsx(Yt,{open:e,onOpenChange:F=>{F||t()},children:s.jsxs(Xt,{className:"w-[min(460px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("更新设置")})}),s.jsxs(Lt,{className:"gap-3.5",children:[s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center justify-between gap-2",children:[s.jsx("div",{className:"text-[13px] font-semibold text-foreground",children:r("自动检查更新")}),s.jsx(Zn,{checked:y?.enabled===!0,disabled:k||!y,onCheckedChange:F=>{E({enabled:F===!0})},"aria-label":r("自动检查更新")})]}),s.jsxs("div",{className:"mt-1.5 flex items-center gap-2",children:[s.jsx(Fe,{type:"number",min:rd,max:eb,step:1,className:"w-[110px]",disabled:k||!y||y.enabled!==!0,value:j,onChange:F=>w(F.currentTarget.value),onKeyDown:F=>{F.key==="Enter"&&(F.preventDefault(),D())},"aria-label":r("检查间隔(分钟)")}),s.jsx("span",{className:"text-[12px] text-subtle",children:r("分钟({min} ~ {max})",{min:rd,max:eb})}),s.jsx(ne,{variant:"outline",size:"sm",disabled:k||!y||Math.round(Number(j))===y.interval,onClick:()=>{D()},children:r("保存")})]}),s.jsx("div",{className:"mt-1.5 text-[12px] text-subtle",children:r("到点自动向 GitHub 查询新版本,查到就走「检测到更新」弹窗;关闭后「检查更新」按钮仍可手动触发")})]}),s.jsx("div",{className:"h-px bg-hairline"}),s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center justify-between gap-2",children:[s.jsx("div",{className:"text-[13px] font-semibold text-foreground",children:r("加入 beta 版")}),s.jsx(Zn,{checked:N?.enabled===!0,disabled:P||!N,onCheckedChange:F=>{I(F===!0)},"aria-label":r("加入 beta 版")})]}),s.jsx("div",{className:"mt-1.5 text-[12px] text-subtle",children:r("开启后只更新到 beta 版(预发布),取版本最高的一个;beta 版可能不稳定。开启期间不会因为正式版发布而自动切回正式版 —— 想切回请关闭本开关。关闭后只更新到正式版,且不会降级到版本号更低的版本。")})]}),s.jsx("div",{className:"h-px bg-hairline"}),s.jsxs("div",{children:[s.jsx("div",{className:"text-[13px] font-semibold text-foreground",children:r("出网代理")}),s.jsx("div",{className:"mt-1.5",children:s.jsxs(dt,{value:C.current,onValueChange:F=>{O(String(F))},children:[s.jsx(pt,{className:Ue("w-full",C.broken&&"border-destructive-bd"),title:C.title,"aria-label":r("更新出网代理"),children:s.jsx(ft,{className:"min-w-0 truncate",children:C.selected?.label||r("直连")})}),s.jsx(mt,{children:C.items.map(F=>s.jsx($e,{value:F.value,disabled:F.disabled,children:F.label},F.value))})]})})]}),s.jsx("div",{className:"h-px bg-hairline"}),s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center justify-between gap-2",children:[s.jsx("div",{className:"text-[13px] font-semibold text-foreground",children:r("GitHub 令牌")}),s.jsx(ne,{variant:"outline",size:"xs",title:r("在默认浏览器中打开 GitHub 的令牌创建页(备注已预设,无需勾选任何权限,直接点 Generate token)"),onClick:()=>{fD(tte)},children:r("打开 GitHub 令牌页面")})]}),s.jsxs("div",{className:"mt-1.5 flex items-center gap-2",children:[H.badge,s.jsx("span",{className:"text-[12px] text-subtle",children:H.hint})]}),s.jsxs("div",{className:"mt-2 flex items-center gap-2",children:[s.jsx(Fe,{type:"password",className:"flex-1",placeholder:L,autoComplete:"new-password",spellCheck:!1,value:f,onChange:F=>p(F.currentTarget.value),onKeyDown:F=>{F.key==="Enter"&&(F.preventDefault(),_())}}),s.jsx(ne,{variant:"default",size:"sm",disabled:h||!f.trim(),onClick:()=>{_()},children:r("保存")}),B?s.jsx(ne,{variant:"outline",size:"sm",disabled:h,onClick:()=>{z()},children:r("清除")}):null]})]})]})]})})}function rte({open:e,onClose:t}){return s.jsx(Yt,{open:e,onOpenChange:a=>{a||t()},children:s.jsxs(Xt,{className:"w-[min(320px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("加入 QQ 群")})}),s.jsxs(Lt,{className:"items-center gap-3 text-center",children:[s.jsx("img",{className:"qq-qr",src:NX,alt:r("QQ 群二维码")}),s.jsxs("div",{className:"qq-no",children:[s.jsx("span",{className:"k",children:r("群号")}),s.jsx("code",{children:lx}),s.jsx(ne,{type:"button",size:"sm",variant:"ghost","data-copy":lx,children:r("复制")})]}),s.jsx("p",{className:"qq-hint",children:r("用手机 QQ 扫上面的二维码,或在 QQ 里搜索群号加入。")})]})]})})}const ate=1e3,UP=8,lte=10,ote=1e3,ite={"":"outline",ok:"success",warn:"warning",bad:"destructive"},cte={info:null,checkedAt:0,repository:"",badgeText:r("未检查"),badgeTone:"",stateText:r("点击「检查更新」查询最新发布版本。"),stateError:!1,percent:0,phase:"idle",readyPath:"",checking:!1,actionBusy:!1,restartSeconds:0,tokenFilled:null};function zl(e){return String(e).padStart(2,"0")}function ute(e){const t=new Date(String(e??""));return!e||Number.isNaN(t.getTime())?"":`${t.getFullYear()}-${zl(t.getMonth()+1)}-${zl(t.getDate())} ${zl(t.getHours())}:${zl(t.getMinutes())}`}function VP(e){const t=new Date(e);if(!e||Number.isNaN(t.getTime()))return"";const a=new Date,o=t.getFullYear()===a.getFullYear()&&t.getMonth()===a.getMonth()&&t.getDate()===a.getDate(),c=`${zl(t.getHours())}:${zl(t.getMinutes())}:${zl(t.getSeconds())}`;return o?c:`${zl(t.getMonth()+1)}-${zl(t.getDate())} ${c}`}function Up(e){const t=e?.installerKind;if(t==="dmg"||t==="deb"||t==="appimage"||t==="nsis")return t;const a=navigator.userAgent||"";return/Mac|iPhone|iPad/.test(a)?"dmg":/Linux/.test(a)?"deb":"nsis"}function Ia(e){return e?.selfUpdate===!0}function FP(e){return e?Ia(e)?e.serverAsset??null:e.asset??null:null}function dte(e){if(Ia(e))return r("正在下载服务端更新包…(下载完成后由面板完成替换,重启容器内的服务后生效)");switch(Up(e)){case"dmg":return r("正在下载安装包…(下载完成后会挂载磁盘映像,把应用拖进「应用程序」即可完成安装)");case"deb":return r("正在下载安装包…(下载完成后会交给系统安装器,按提示输入密码即可完成安装)");case"appimage":return r("正在下载安装包…(下载完成后会启动新的 AppImage;把它替换掉旧文件即完成升级)");default:return r("正在下载安装包…(下载完成后启动安装程序需要管理员权限,会弹出 UAC 确认框)")}}function $P(e,t){if(Ia(e))return r("更新包已就绪:{name}。点「安装并重启」后,面板会校验并替换容器内的程序与界面文件,然后重启服务(页面会自动刷新)。",{name:t});switch(Up(e)){case"dmg":return r("安装包已就绪:{name}。点击「打开安装包」后会挂载磁盘映像,把应用拖进「应用程序」即可完成安装。",{name:t});case"deb":return r("安装包已就绪:{name}。点击「打开安装包」后会交给系统安装器,按提示输入密码即可完成安装(本程序无需退出)。",{name:t});case"appimage":return r("安装包已就绪:{name}。点击「安装并重启」后会启动新的 AppImage;把它移动到你的应用目录并替换旧文件即完成升级(本程序会先退出以释放文件占用)。",{name:t});default:return r("安装包已就绪:{name}。点击「安装并重启」后需要管理员权限,会弹出 UAC 确认框。",{name:t})}}function fte(e){if(Ia(e))return r("安装并重启");const t=Up(e);return r(t==="dmg"||t==="deb"?"打开安装包":"安装并重启")}let Vr=cte;const FS=new Set;function $S(){return Vr}function pte(e){return FS.add(e),()=>{FS.delete(e)}}function zn(e){Vr={...Vr,...e};for(const t of FS)t()}async function qS(){try{const e=await nn().workbuddyDesktop?.getUpdateToken();zn({tokenFilled:e?.filled===!0})}catch{}}let Tr=!1,GS=null,tb=null;function ad(){tb!==null&&(window.clearInterval(tb),tb=null)}function Rs(e,t=""){zn({badgeText:e,badgeTone:t})}function Mn(e,t=!1){zn({stateText:e,stateError:t})}function nb(){const{info:e,checkedAt:t}=Vr;if(!e)return;const a=t?r("(检查于 {time})",{time:VP(t)}):"";if(e.pendingRestart===!0){Rs(r("待重启"),"warn"),Mn(r("更新已应用到容器内,重启服务后生效。{at}",{at:a}));return}if(e.hasUpdate===!0){if(Rs(r("有新版本"),"warn"),Ia(e)&&!e.serverAsset){Mn(r("发现新版本 {latest}(当前 {current}),但该版本没有提供容器内更新包;请在宿主机执行 docker compose pull && docker compose up -d 升级。{at}",{latest:String(e.latestVersion||""),current:String(e.currentVersion||""),at:a}));return}Mn(r("发现新版本 {latest}(当前 {current})。{at}",{latest:String(e.latestVersion||""),current:String(e.currentVersion||""),at:a}))}else e.hasUpdate===!1?(Rs(r("已是最新"),"ok"),Mn(r("当前已是最新版本({current})。{at}",{current:String(e.currentVersion||""),at:a}))):(Rs(r("无法比较"),"warn"),Mn(e.latestVersion?r("最新发布版本为 {latest},但当前版本号「{current}」无法解析,未做新旧判断。{at}",{latest:e.latestVersion,current:e.currentVersion||r("未知"),at:a}):r("仓库暂无发布版本。{at}",{at:a})))}function qP(e){!e||e.checked===!1||(zn({info:e,checkedAt:Number(e.checkedAt)||0}),e.repository&&KS(e.repository),Vr.phase==="idle"&&nb())}function KS(e){const t=String(e||"").trim();/^[\w.-]+\/[\w.-]+$/.test(t)&&zn({repository:t})}function YS(e){if(!e)return!1;if(e.active){const t=Math.max(0,Math.min(100,Number(e.percent)||0)),a=(Number(e.received)||0)/1024/1024,o=(Number(e.total)||0)/1024/1024;return zn({phase:"downloading",percent:t}),Rs(r("下载中"),"warn"),Mn(r("正在下载 {name}:{percent}%({received} / {total} MB)",{name:e.filename||r("安装包"),percent:t,received:a.toFixed(1),total:o.toFixed(1)})),!0}if(ad(),zn({percent:0}),e.error)return Rs(r("下载失败"),"bad"),Mn(r("下载失败:{error}",{error:e.error}),!0),zn({phase:"failed"}),!0;if(e.canceled)return Rs(r("已取消"),"warn"),Mn(Ia(Vr.info)?r("下载已取消,可重新点击「下载并更新」。"):r("下载已取消,可重新点击「下载并安装」。")),zn({phase:"idle"}),!0;if(e.done&&e.path){const t=e.path,a=e.filename||t;if(Rs(r("可安装"),"ok"),zn({phase:"ready",readyPath:t}),Ia(Vr.info))return Mn($P(Vr.info,a)),!0;if(t!==GS){GS=t;const o=Up(Vr.info);Mn(r(o==="dmg"?"安装包已下载完成,正在挂载磁盘映像…":o==="deb"?"安装包已下载完成,正在打开系统安装器…":o==="appimage"?"安装包已下载完成,正在启动新的 AppImage…":"安装包已下载完成,正在启动安装程序(需要管理员权限,会弹出 UAC 确认框)…")),KP(t)}else Mn($P(Vr.info,a));return!0}return!1}async function mte(){try{const e=await nn().workbuddyDesktop?.updateProgress();if(!e){ad();return}YS(e)}catch(e){ad(),Mn(r("读取下载进度失败:{error}",{error:mr(e)}),!0)}}function GP(){ad(),tb=window.setInterval(()=>{mte()},ate)}async function KP(e){const t=nn().workbuddyDesktop;if(t)try{const o=(await t.runInstaller(e,!0))?.restart!==!1,c=Up(Vr.info)==="deb"?r("已打开系统安装器,请在它弹出的窗口里完成安装。安装完成后重新打开本程序即可。"):r("安装包已挂载,请在弹出的窗口里把应用拖进「应用程序」完成安装。安装完成后重新打开本程序即可。");Mn(o?r("安装程序已启动,本程序将退出以便完成覆盖安装。安装程序需要管理员权限,会弹出 UAC 确认框,请选择「是」。"):c)}catch(a){Rs(r("启动失败"),"bad"),Mn(r("启动安装程序失败:{error}",{error:mr(a)}),!0)}}async function hte(){const e=nn().workbuddyDesktop;if(e?.installUpdate)try{Rs(r("安装中"),"warn"),Mn(r("正在校验并替换容器内的程序与界面文件…"));const t=await e.installUpdate(),a=String(t?.version||"").trim();Mn(a?r("已替换为 {version},正在重启服务…",{version:a}):r("替换完成,正在重启服务…")),await e.restartService?.().catch(()=>{}),XS(a)}catch(t){Rs(r("安装失败"),"bad"),Mn(r("安装失败:{error}",{error:mr(t)}),!0)}}async function gte(){const e=nn().workbuddyDesktop;if(!(!e?.rollbackUpdate||Tr)){Tr=!0,zn({actionBusy:!0});try{Rs(r("回滚中"),"warn"),Mn(r("正在回滚到上一版本…")),await e.rollbackUpdate(),Mn(r("已还原上一版本,正在重启服务…")),await e.restartService?.().catch(()=>{}),XS("")}catch(t){Rs(r("回滚失败"),"bad"),Mn(r("回滚失败:{error}",{error:mr(t)}),!0)}finally{Tr=!1,zn({actionBusy:!1})}}}function XS(e){ad(),zn({phase:"restarting",restartSeconds:UP,readyPath:""}),Rs(r("重启中"),"warn");let t=UP;const a=()=>{if(Mn(e?r("{version} 已就位,服务正在重启,页面会在恢复后自动刷新…({seconds}s)",{version:e,seconds:Math.max(0,t)}):r("服务正在重启,页面会在恢复后自动刷新…({seconds}s)",{seconds:Math.max(0,t)})),t<=0){window.clearInterval(o),xte();return}t-=1,zn({restartSeconds:t})},o=window.setInterval(a,1e3);a()}async function xte(){for(let e=0;e{window.setTimeout(t,ote)})}window.location.reload()}async function YP(){if(Tr)return null;Tr=!0,zn({checking:!0}),Rs(r("检查中"),"warn"),Mn(r("正在查询 GitHub 上的最新发布版本…"));let e=null;try{const t=nn().workbuddyDesktop;if(!t)throw new Error(r("后端桥不可用"));e=await t.checkUpdate()??null,zn({info:e,checkedAt:Number(e?.checkedAt)||Date.now()}),e?.repository&&KS(e.repository),nb()}catch(t){e=null,zn({info:null,checkedAt:0}),Rs(r("检查失败"),"bad"),Mn(r("检查更新失败:{error}",{error:mr(t)}),!0)}finally{Tr=!1,zn({checking:!1})}return nn().wbApp?.updateUpdateBadge?.(e),Jx(e,Vp),e}async function XP(){let e=null;try{e=await nn().workbuddyDesktop?.getUpdateStatus()??null}catch{}if(e&&e.checked!==!1){qP(e),nn().wbApp?.updateUpdateBadge?.(e),Jx(e,Vp);return}Vr.info||(Rs(r("未检查")),Mn(r("点击「检查更新」查询 GitHub 上的最新发布版本。")))}async function QS(){if(Tr)return;const e=$S();if(e.info?.pendingRestart===!0&&e.phase!=="downloading"){Tr=!0,zn({actionBusy:!0});try{await nn().workbuddyDesktop?.restartService?.().catch(()=>{}),XS("")}finally{Tr=!1,zn({actionBusy:!1})}return}if(e.phase!=="downloading"&&e.readyPath){Tr=!0,zn({actionBusy:!0});try{Ia(e.info)?await hte():await KP(e.readyPath)}finally{Tr=!1,zn({actionBusy:!1})}return}if(e.phase==="downloading"){try{await nn().workbuddyDesktop?.cancelUpdate(),Mn(r("正在取消下载…"))}catch(a){Es(r("取消失败:{error}",{error:mr(a)}),"err")}return}const t=FP(e.info);if(!t?.url){Es(Ia(e.info)?r("这一版没有提供容器内更新包"):r("没有可下载的安装包"),"err");return}if(ZP(e)){Tr=!0,zn({actionBusy:!0});try{await nn().workbuddyDesktop?.downloadUpdate({url:t.url,name:t.name}),GS=null,zn({phase:"downloading",readyPath:"",percent:0}),Rs(r("下载中"),"warn"),Mn(dte(e.info)),GP()}catch(a){Rs(r("下载失败"),"bad"),Mn(r("下载失败:{error}",{error:mr(a)}),!0)}finally{Tr=!1,zn({actionBusy:!1})}}}async function QP(){nb(),qS(),await XP();try{const e=await nn().workbuddyDesktop?.updateProgress();if(e?.active){YS(e),GP();return}if(e?.done&&e.path){YS(e);return}}catch{}}async function Vp(e){if(e?.pendingRestart===!0){await QS();return}e?.hasUpdate===!0&&(zn({info:e,checkedAt:Number(e.checkedAt)||Vr.checkedAt}),e.repository&&KS(e.repository),nb(),nn().wbApp?.updateUpdateBadge?.(e),Jx(e,Vp)),await QP();const t=$S();if(!(t.phase==="downloading"||t.readyPath)&&t.info?.hasUpdate)for(let a=0;a<3;a+=1){if(Tr){await new Promise(o=>{window.setTimeout(o,400)});continue}await QS();return}}function ZP(e){return e.phase==="restarting"?null:e.info?.pendingRestart===!0&&e.phase==="idle"?{label:r("立即重启"),disabled:e.actionBusy}:!(e.info?.hasUpdate===!0&&!!FP(e.info)?.url)&&e.phase!=="downloading"&&e.phase!=="ready"?null:{label:e.phase==="downloading"?r("取消下载"):e.phase==="failed"?r("重试下载"):e.phase==="ready"?fte(e.info):Ia(e.info)?r("下载并更新"):r("下载并安装"),disabled:e.actionBusy}}function bte(e,t){const a=e.info,o=String(a?.notes||"").trim();if(!o)return s.jsx("div",{className:"update-log-hint",children:r(a?"这个版本没有填写发布说明。":"点击「检查更新」后,这里会显示最新版本的更新说明。")});const c=pD(o),d=dD(a?.pageUrl),f=ute(a?.publishedAt);return s.jsxs("div",{className:"rel-note",children:[s.jsxs("div",{className:"rel-note-head",children:[s.jsx("span",{className:"rel-tag",children:String(a?.latestVersion||r("最新版本"))}),a?.prerelease===!0?s.jsx(ze,{shape:"tag",variant:"warning",children:r("预发布")}):null,f?s.jsx("span",{className:"rel-date",children:f}):null]}),s.jsxs("div",{className:"rel-note-body",children:[c?s.jsx("div",{className:"md-body",dangerouslySetInnerHTML:{__html:c}}):s.jsx("div",{className:"md-body",children:s.jsx("p",{className:"md-body-empty",children:r("这个版本没有填写发布说明。")})}),s.jsxs("div",{className:"rel-foot",children:[d?s.jsx("a",{href:d,"data-external":d,target:"_blank",rel:"noopener",children:r("在 GitHub 查看完整说明")}):null,s.jsx(ne,{type:"button",variant:"link",size:"sm",className:"h-auto border-0 px-0 text-[11.5px] font-semibold text-primary-fg underline-offset-auto",title:r("群号:{group}",{group:lx}),onClick:t,children:r("加入 QQ 群")})]})]})]})}function vte(){const e=x.useSyncExternalStore(pte,$S),t=ZP(e),[a,o]=x.useState(!1),[c,d]=x.useState(!1);x.useEffect(()=>()=>{ad()},[]),x.useEffect(()=>{qS()},[]);const f=e.repository?`https://github.com/${e.repository}`:"",p=e.repository?`https://github.com/${e.repository.split("/")[0]}`:"",h=Ia(e.info),b=h&&e.info?.backupAvailable===!0&&e.phase!=="downloading"&&e.phase!=="ready"&&e.phase!=="restarting",y=e.info?.latestVersion?e.info.prerelease?r("{version}(预发布)",{version:e.info.latestVersion}):e.info.latestVersion:"—",v=String(e.info?.latestVersion||"").trim(),j=v?`${v}${e.checkedAt?r(" · 检查于 {time}",{time:VP(e.checkedAt)}):""}`:"";return s.jsxs("section",{className:"panel",onClick:Xu,children:[s.jsxs("div",{className:"panel-head",children:[s.jsx("h2",{children:r("软件更新")}),s.jsx("span",{className:"tip-q","data-tip":r(h?"容器内更新:更新包从 GitHub 发布页下载,校验 sha256 后由面板替换容器内的程序与界面文件,再重启服务(容器由 restart 策略拉起,页面会自动刷新)。更新的是容器里的文件,compose 里的镜像标签不变 —— 之后执行 docker compose pull && up -d 会回到镜像里的版本;更新失败可一键回滚到上一版本。检查更新与下载的出网线路、GitHub 令牌都在「更新设置」里。":"更新包从 GitHub 发布页下载,下载完成后可直接启动安装程序并自动重启本程序。安装包会先校验来源域名与文件完整性。检查更新与下载安装包的出网线路、GitHub 令牌都在「更新设置」里:线路默认直连(直连失败时自动借 Clash Verge 的混合端口重试一次),选定指定出口后只走该出口;填写 GitHub 令牌可把检查限额从 60 次/小时提高到 5000 次/小时。")}),s.jsx(ze,{id:"update-badge",variant:ite[e.badgeTone],"data-tone":e.badgeTone,children:e.badgeText}),s.jsxs("div",{className:"head-actions",children:[e.tokenFilled===!1?s.jsx("span",{className:"text-[12px] font-semibold text-warning",title:r("填写后检查限额 60 → 5000 次/小时(创建令牌无需勾选任何权限)"),children:r("GitHub Token 未填写")}):null,s.jsx(ne,{id:"btn-update-settings",variant:"outline",title:r("出网线路与 GitHub 令牌设置"),onClick:()=>o(!0),children:r("更新设置")}),s.jsx(ne,{id:"btn-update-check",variant:"outline",disabled:e.checking||e.phase==="restarting",onClick:()=>{YP()},children:e.checking?r("检查中…"):r("检查更新")}),b?s.jsx(ne,{id:"btn-update-rollback",variant:"outline",disabled:e.actionBusy,title:r("把容器内的程序与界面文件还原到更新前的版本,并重启服务"),onClick:()=>{gte()},children:r("回滚到上一版本")}):null,t?s.jsx(ne,{id:"btn-update-download",variant:"default",disabled:t.disabled,onClick:()=>{QS()},children:t.label}):null]})]}),s.jsxs("div",{className:"panel-body",children:[s.jsxs("div",{className:"update-version",children:[s.jsxs("span",{className:"version-pill",children:[s.jsx("span",{className:"k",children:r("当前版本")}),s.jsx("span",{className:"v",id:"update-current",children:e.info?.currentVersion||"—"})]}),s.jsx("span",{className:"version-arrow",children:"→"}),s.jsxs("span",{className:"version-pill new",children:[s.jsx("span",{className:"k",children:r("最新版本")}),s.jsx("span",{className:"v",id:"update-latest",children:y})]})]}),s.jsx("div",{className:"detail",id:"update-state",style:e.stateError?{color:"var(--danger)"}:void 0,children:e.stateText}),e.phase==="downloading"&&e.percent>0&&e.percent<100?s.jsx(cf,{value:e.percent}):null,p&&f?s.jsxs("div",{className:"update-author",id:"update-author",children:[s.jsxs("div",{className:"update-author-text",children:[s.jsx("strong",{children:r("关于作者")}),s.jsxs("span",{children:[r("本工具由")," ",s.jsx("a",{id:"update-author-link",href:p,"data-external":p,target:"_blank",rel:"noopener",children:e.repository.split("/")[0]})," ",r("个人开发并开源维护,免费使用,也不会收集你的账号数据。如果它帮到了你,欢迎到项目仓库点个 Star 支持一下。")]})]}),s.jsx("div",{className:"update-author-actions",children:s.jsx(ne,{id:"btn-update-favorite",type:"button",size:"sm",variant:"outline","data-external":f,title:r("在浏览器中打开项目仓库,点 Star 支持作者"),children:r("收藏项目")})})]}):null,s.jsxs("div",{className:"update-log",id:"update-notes",children:[s.jsxs("div",{className:"update-log-head",children:[s.jsx("span",{className:"update-log-title",children:r("更新日志")}),s.jsx("span",{className:"update-log-meta",id:"update-log-meta",children:j})]}),s.jsx("div",{className:"update-log-body",id:"update-log-body",children:bte(e,()=>d(!0))})]})]}),a?s.jsx(ste,{open:!0,onClose:()=>{o(!1),qS()}}):null,c?s.jsx(rte,{open:!0,onClose:()=>d(!1)}):null]})}const WP='.settings-pane[data-cat="about"]';let ZS=null;function JP(){if(ZS)return;const e=document.querySelector(WP);e&&(e.replaceChildren(),ZS=jn.createRoot(e),ZS.render(s.jsx(vte,{})))}document.querySelector(WP)?JP():document.addEventListener("DOMContentLoaded",JP,{once:!0}),window.wbUpdatePanel={load:QP,check:YP,syncFromCache:XP,openAndDownload:Vp,applyStatus:qP,showUpdateModal:e=>Jx(e,Vp)};const yte="zcode.z.ai/billing",jte={active:"success",pending:"warning",expired:"ghost",unknown:"outline"};function wte(e){const t=String(e||"").trim().toLowerCase();return t==="daily"?r("每日"):t==="weekly"?r("每周"):t==="monthly"?r("每月"):""}function Ste(e){const t=Number(e);if(!Number.isFinite(t)||t<=0)return"";const a=window.wbUnits;return a?.formatTokens?a.formatTokens(t):String(t)}function hc(e){const t=Number(e);return!Number.isFinite(t)||t<=0?"":Pe().wbApp?.formatTime?.(t*1e3)||new Date(t*1e3).toLocaleString()}function Nte(e){const t=Ste(e.grantUnits),a=String(e.unitType||"").trim(),o=t?[t,a].filter(Boolean).join(" "):"",c=wte(e.period),d=[String(e.showName||"").trim(),o].filter(Boolean).join(" ");return d?c?r("{body}({period})",{body:d,period:c}):d:""}function e_(e){return(e.entitlements||[]).map(Nte).filter(Boolean).join(r("、"))}function kte(e){const t=hc(e.startsAt),a=hc(e.endsAt);return t&&a?`${t} → ${a}`:a?r("到期 {time}",{time:a}):t?r("开始 {time}",{time:t}):""}function Cte(e){const t=new Date(e*1e3);if(Number.isNaN(t.getTime()))return"";const a=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`,o=d=>Math.floor(Date.UTC(d.getFullYear(),d.getMonth(),d.getDate())/864e5),c=o(t)-o(new Date);return c===0?r("今天 {time}",{time:a}):c===1?r("明天 {time}",{time:a}):hc(e)}function Tte(e){const t=[],a=Number(e.pendingUntil);if(Number.isFinite(a)&&a>0){const c=Cte(a);c&&t.push(r("待生效 {time}",{time:c}))}const o=hc(e.endsAt);if(o&&t.push(r("到期 {time}",{time:o})),t.length===0){const c=hc(e.startsAt);c&&t.push(r("开始 {time}",{time:c}))}return t.join(" · ")}function Ete({options:e,onClose:t}){const a=e.id,[,o]=x.useState(0);x.useEffect(()=>sR(()=>o(I=>I+1)),[]);const[c,d]=x.useState([]),[f,p]=x.useState({status:"loading"}),[h,b]=x.useState(""),y=Aa(a),v=String(y?.name||e.name||a),j=tg(y),w=[...new Set([...j,...c])],k=y?.claimPlans&&typeof y.claimPlans=="object"&&!Array.isArray(y.claimPlans)?y.claimPlans:{},S=y?Wa(y):void 0,N=S&&typeof S=="object"&&!Array.isArray(S)?S:null,R=N&&Array.isArray(N.plans)?N.plans:[],P=w.filter(I=>I&&!R.some(O=>String(O.planId||"")===I)),T=Gs().usageInflight.has(a),C=Pe().wbZcodeClaim,E=x.useCallback(async()=>{if(!C?.preview){p({status:"error",message:r("当前环境不支持领取(桥接方法缺失)")});return}p({status:"loading"});try{const I=await C.preview(a);p({status:"ready",result:I||{}})}catch(I){p({status:"error",message:ut(I)})}},[C,a]);x.useEffect(()=>{E();const I=Aa(a);I&&Wa(I)===void 0&&cg(a)},[a,E]);async function D(I){if(!(!C?.claim||h)){b(I);try{const O=await C.claim(a,I);if(O?.ok||O?.failure==="already_claimed"){const _=O.planId||I;_&&d(z=>z.includes(_)?z:[...z,_]),cg(a),Pe().wbApp?.refresh?.(),E()}}finally{b("")}}}return s.jsx(Yt,{open:!0,onOpenChange:(I,O)=>{if(!I){if(h){O.cancel();return}t()}},children:s.jsxs(Xt,{className:"w-[min(560px,calc(100vw-48px))]",children:[s.jsx(Vt,{children:s.jsx(Ut,{children:r("ZCode 套餐明细 — {name}",{name:v})})}),s.jsxs(Lt,{className:"space-y-4",children:[s.jsxs("section",{children:[s.jsxs("div",{className:"mb-1.5 flex items-center gap-2 text-[12px] font-semibold text-muted-foreground",children:[r("可领取的套餐"),s.jsx(ze,{variant:"outline",shape:"tag",children:r("官方限时活动")})]}),f.status==="loading"?s.jsxs("div",{className:"flex items-center gap-2 py-2 text-[12.5px] text-muted-foreground",children:[s.jsx(of,{className:"size-3"}),r("正在探测可领取的套餐…")]}):f.status==="error"?s.jsxs("div",{className:"py-1 text-[12.5px] text-destructive",children:[r("探测失败:{message}",{message:f.message}),s.jsx(ne,{variant:"outline",size:"xs",className:"ml-2",onClick:()=>{E()},children:r("重试")})]}):f.result.deployed?(f.result.plans||[]).length===0?s.jsx("p",{className:"py-1 text-[12.5px] text-muted-foreground",children:r("当前没有可领取的套餐(活动期内每天发一份,明天可再领)")}):s.jsx("ul",{className:"m-0 list-none p-0",children:(f.result.plans||[]).map(I=>{const O=String(I.planId||""),_=w.includes(O),z=e_(I),H=kte(I);return s.jsxs("li",{className:"flex items-start justify-between gap-3 border-b border-hairline py-2 last:border-b-0",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsxs("div",{className:"flex items-center gap-2 text-[13px] font-medium",children:[s.jsx("span",{className:"truncate",children:I.name||O||r("套餐")}),_?s.jsx(ze,{variant:"success",shape:"tag",children:r("今日已领")}):null]}),H?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:H}):null,z?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:z}):null,I.description?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:I.description}):null]}),s.jsx(ne,{variant:"outline",size:"xs",className:"flex-none",title:_?r("这一份今天已经领过了(重复领取上游会回「已领取过」)"):void 0,disabled:h!=="",onClick:()=>{D(O)},children:r(h===O?"领取中…":_?"再领一次":"领取")})]},O||I.name)})}):s.jsx("p",{className:"py-1 text-[12.5px] text-muted-foreground",children:r("当前没有可领取的套餐(活动尚未开始)")}),s.jsx("p",{className:"mt-1.5 text-[11.5px] text-muted-foreground",children:r("活动期内每天发一份新套餐;同一份当天重复领取会提示「已领取过」,次日可再领。领取要走一次人机验证(滑块)。")}),f.status==="ready"&&f.result.activationError?s.jsx("p",{className:"text-[11.5px] text-muted-foreground",children:r("(激活事件补报失败,可能影响领取资格:{message})",{message:f.result.activationError})}):null]}),s.jsxs("section",{children:[s.jsxs("div",{className:"mb-1.5 flex items-center gap-2 text-[12px] font-semibold text-muted-foreground",children:[r("我的套餐"),Array.isArray(N?.wallets)&&N.wallets.length>0&&N.availableView?s.jsx(ze,{variant:"outline",shape:"tag",children:String(N.walletsFrom||"")==="monitor"?String(N.availableView):r("可用 {value}",{value:String(N.availableView)})}):null,s.jsx("div",{className:"ml-auto",children:s.jsx(ne,{variant:"outline",size:"xs",disabled:T,title:r("重新读取该账号的余额与套餐(走余额查询那条链)"),onClick:()=>{cg(a)},children:r(T?"查询中…":"查询余额")})})]}),R.length>0?s.jsx("ul",{className:"m-0 list-none p-0",children:R.map(I=>{const O=String(I.planId||""),_=String(I.state||"unknown"),z=e_(I),H=Tte(I),B=O&&y?.claimPlans&&Number(y.claimPlans[O])||0;return s.jsxs("li",{className:"flex items-start justify-between gap-3 border-b border-hairline py-2 last:border-b-0",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsxs("div",{className:"flex items-center gap-2 text-[13px] font-medium",children:[s.jsx("span",{className:"truncate",children:I.name||O||r("套餐")}),s.jsx(ze,{variant:jte[_]||"outline",shape:"tag",children:qA(_)})]}),H?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:H}):null,z?s.jsx("div",{className:"text-[12px] text-muted-foreground",children:z}):null]}),B>0?s.jsx("span",{className:"flex-none text-[11.5px] text-muted-foreground",children:r("本地领取于 {time}",{time:hc(B/1e3)})}):null]},O||I.name)})}):s.jsx("p",{className:"py-1 text-[12.5px] text-muted-foreground",children:S===void 0?r("还没有余额读数(已自动查询一次,稍候;也可以点右上角「查询余额」重读)"):N&&N.source&&N.source!==yte?r("这个账号的余额走窗口限额通道(只配了编码套餐 API Key):只有每 N 小时的剩余比例,读不到套餐清单"):r("读数里没有套餐清单(免费账号、或套餐的上游状态还没刷新;可点右上角「查询余额」重读)")}),P.length>0?s.jsx("p",{className:"mt-1.5 text-[11.5px] text-muted-foreground",children:r("本地台账里今天还领过这些,但上面的读数里还没有:{plans}(读数刷新可能有延迟)",{plans:P.map(I=>{const O=Number(k[I])||0,_=O>0?hc(O/1e3):"";return _?r("{plan}({time} 领取)",{plan:I,time:_}):I}).join(r("、"))})}):null]})]}),s.jsxs(tn,{children:[s.jsx("span",{className:"min-w-0 text-[11.5px] text-muted-foreground",children:w.length>0?r("今天(北京时间)已领取 {n} 份:{plans}",{n:w.length,plans:w.join(r("、"))}):r("今天还没有领过:上面「可领取的套餐」里逐份点「领取」即可")}),s.jsx("div",{className:"mr-auto"}),s.jsx(ne,{variant:"outline",onClick:t,children:r("关闭")})]})]})})}let Fp=null,ld=null;function t_(){Fp&&(Fp.unmount(),Fp=null),ld&&(ld.remove(),ld=null)}function Ate(e){e?.id&&(t_(),ld=document.createElement("div"),document.body.append(ld),Fp=jn.createRoot(ld),Fp.render(s.jsx(Ete,{options:e,onClose:t_})))}window.wbZcodePlans={open:Ate};const n_="w-auto flex-auto";function s_({onInput:e,domRef:t,icon:a,className:o,inputClassName:c,...d}){const f=h=>{t.current=h},p=h=>{e?.(h.currentTarget.value)};return a?s.jsxs(Di,{className:Ue(n_,o),children:[s.jsx(Pi,{ref:f,className:c,onInput:p,...d}),s.jsx(Ii,{"aria-hidden":"true",children:a})]}):s.jsx(Fe,{ref:f,className:Ue(n_,c),onInput:p,...d})}function Rte(e,t){const a=jn.createRoot(e),o={current:null};return a.render(s.jsx(s_,{domRef:o,defaultValue:t.value,placeholder:t.placeholder,type:t.type??"search",icon:t.icon,"aria-label":t.ariaLabel,onInput:t.onInput})),{setValue(c){const d=o.current;d&&d.value!==c&&(d.value=c)},getValue(){return o.current?.value??""},focus(){o.current?.focus()},unmount(){a.unmount()}}}const Ote=[["id","id"],["type","type"],["name","name"],["title","title"],["placeholder","placeholder"],["min","min"],["max","max"],["step","step"],["autocomplete","autoComplete"]];function Mte(e){const t={defaultValue:e.value||void 0,inputClassName:e.className||void 0};for(const[f,p]of Ote){const h=e.getAttribute(f);h!=null&&(t[p]=h)}const a=e.getAttribute("maxlength");a!=null&&(t.maxLength=Number(a));const o=e.getAttribute("inputmode");o!=null&&(t.inputMode=o),e.hasAttribute("spellcheck")&&(t.spellCheck=e.spellcheck),e.disabled&&(t.disabled=!0),e.readOnly&&(t.readOnly=!0),e.hidden&&(t.hidden=!0);const c=e.getAttribute("aria-label");c!=null&&(t["aria-label"]=c);for(const f of e.getAttributeNames())!f.startsWith("data-")||f.startsWith("data-island-")||(t[f]=e.getAttribute(f)??"");const d=e.getAttribute("data-island-icon");return d!=null&&(t.icon=d),t}function r_(e){if(e.dataset.islandUpgraded)return;e.dataset.islandUpgraded="1";const t=Mte(e),a=e.parentElement?.classList.contains("input-affix")?e.parentElement:null;let o;a?(a.className=a.className.replace(/\binput-affix\b/,"").trim(),a.style.display="flex",a.style.alignItems="center",o=a):(o=document.createElement("span"),o.style.display="contents",e.replaceWith(o));const c={current:null},d=jn.createRoot(o);Ts.flushSync(()=>{d.render(s.jsx(s_,{...t,domRef:c}))})}function a_(e=document){if(e instanceof HTMLInputElement&&e.matches("[data-island-input]")){r_(e);return}e.querySelectorAll("input[data-island-input]").forEach(r_)}function Dte(){a_();const e=new MutationObserver(t=>{for(const a of t)for(const o of a.addedNodes)o instanceof Element&&a_(o)});return e.observe(document.body,{childList:!0,subtree:!0}),e}function Ite(e,t){const a=jn.createRoot(e);let o={options:t.options,value:t.value,ariaLabel:t.ariaLabel,className:t.className};const c=()=>{a.render(s.jsx(En,{options:o.options,value:o.value,onValueChange:t.onChange,"aria-label":o.ariaLabel,className:o.className}))};return c(),{setValue(d){d!==o.value&&(o={...o,value:d},c())},setOptions(d){o={...o,options:d},c()},unmount(){a.unmount()}}}window.wbSegmented={mount:Ite},window.wbInput={mount:Rte},Dte()})(); diff --git a/docs/README.en.md b/docs/README.en.md index 6624966f..ac95873a 100644 --- a/docs/README.en.md +++ b/docs/README.en.md @@ -76,6 +76,7 @@ Reverse-proxy capabilities at a glance (✓ supported · ✗ not supported · | Antigravity (Google, Gemini / Claude / GPT-OSS) | ✓ | ✓ | ✓ | — | — | — | | OfficeAce (Huawei Cloud, OfficeClaw) | ✓ | ✓ | ✓ | ✓ | ✓ | — | | OrcaTerm (Tencent Cloud) | ✓ | ✓ | ✓ | ✓ | — | — | +| ModelScope (ModelScope.cn / ModelScope Intl) | ✓ | ✗ token does not expire | ✓ remote only | ✓ free-credit balance | ✓ daily credits (calling the login endpoint triggers it) | — | | Zhipu Qingyan | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Custom providers | ✓ | — | ✓ | — | — | — | @@ -252,7 +253,7 @@ The macOS `.dmg` **can only be built on macOS** (`npm --prefix desktop-tauri run ### For learning and discussion only -This project is a hands-on exercise in HTTP reverse proxying, SSE streaming passthrough, multi-upstream protocol adaptation and desktop packaging (Tauri), and is **for personal learning and research only**. It is not an official product and has no affiliation with, endorsement from or sponsorship by Tencent and WorkBuddy / CodeBuddy, Meituan and CatPaw, SenseTime and Raccoon, Zhipu and AutoClaw / autoglm, Alibaba and Qoder / Accio, Huawei Cloud and CodeArts / OfficeAce, ByteDance and Trae, iFlytek and Loomy, Baidu Wenku and KukuAI, Chaitin and MonkeyCode, Command Code, or Google and Antigravity. +This project is a hands-on exercise in HTTP reverse proxying, SSE streaming passthrough, multi-upstream protocol adaptation and desktop packaging (Tauri), and is **for personal learning and research only**. It is not an official product and has no affiliation with, endorsement from or sponsorship by Tencent and WorkBuddy / CodeBuddy, Meituan and CatPaw, SenseTime and Raccoon, Zhipu and AutoClaw / autoglm, Alibaba and Qoder / Accio, Huawei Cloud and CodeArts / OfficeAce, ByteDance and Trae, iFlytek and Loomy, Baidu Wenku and KukuAI, Chaitin and MonkeyCode, Command Code, Google and Antigravity, or Alibaba and ModelScope. ### About the reverse-proxy behaviour diff --git a/docs/README.ja.md b/docs/README.ja.md index 15d270cd..5897823a 100644 --- a/docs/README.ja.md +++ b/docs/README.ja.md @@ -76,6 +76,7 @@ Agent2API は、複数の AI デスクトップクライアントでログイン | Antigravity(Google、Gemini / Claude / GPT-OSS) | ✓ | ✓ | ✓ | — | — | — | | OfficeAce(Huawei Cloud、OfficeClaw) | ✓ | ✓ | ✓ | ✓ | ✓ | — | | OrcaTerm(Tencent Cloud) | ✓ | ✓ | ✓ | ✓ | — | — | +| ModelScope(魔搭、中国版 / 国際版) | ✓ | ✗ トークンは長期有効 | ✓ リモートのみ | ✓ 魔粒残高 | ✓ 毎日の魔粒(ログイン API 呼び出しで発火) | — | | 智谱清言(Zhipu Qingyan) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | カスタムプロバイダー | ✓ | — | ✓ | — | — | — | @@ -251,7 +252,7 @@ macOS の `.dmg` は **macOS 上でしかビルドできません**(`npm --pre ### 学習・交流目的に限る -本プロジェクトは、HTTP リバースプロキシ、SSE ストリーミングのパススルー、複数アップストリームのプロトコル適応、デスクトップパッケージング(Tauri)といった技術テーマを学ぶための実践プロジェクトであり、**個人の学習・研究目的のみ**を対象としています。公式製品ではなく、Tencent および WorkBuddy / CodeBuddy、Meituan および CatPaw、SenseTime および小浣熊、Zhipu および AutoClaw / autoglm、Alibaba および Qoder / Accio、Huawei Cloud および CodeArts / OfficeAce、ByteDance および Trae、iFlytek および Loomy、Baidu Wenku および KukuAI、長亭科技 および MonkeyCode、Command Code、Google および Antigravity のいずれとも一切の関係がなく、その承認やスポンサーシップも受けていません。 +本プロジェクトは、HTTP リバースプロキシ、SSE ストリーミングのパススルー、複数アップストリームのプロトコル適応、デスクトップパッケージング(Tauri)といった技術テーマを学ぶための実践プロジェクトであり、**個人の学習・研究目的のみ**を対象としています。公式製品ではなく、Tencent および WorkBuddy / CodeBuddy、Meituan および CatPaw、SenseTime および小浣熊、Zhipu および AutoClaw / autoglm、Alibaba および Qoder / Accio、Huawei Cloud および CodeArts / OfficeAce、ByteDance および Trae、iFlytek および Loomy、Baidu Wenku および KukuAI、長亭科技 および MonkeyCode、Command Code、Google および Antigravity、Alibaba および ModelScope(魔搭)のいずれとも一切の関係がなく、その承認やスポンサーシップも受けていません。 ### リバースプロキシの挙動について diff --git a/docs/README.ko.md b/docs/README.ko.md index 413d22ec..9dcac94d 100644 --- a/docs/README.ko.md +++ b/docs/README.ko.md @@ -76,6 +76,7 @@ Agent2API는 여러 AI 데스크톱 클라이언트에 로그인된 계정을 | Antigravity(Google, Gemini / Claude / GPT-OSS) | ✓ | ✓ | ✓ | — | — | — | | OfficeAce(Huawei Cloud, OfficeClaw) | ✓ | ✓ | ✓ | ✓ | ✓ | — | | OrcaTerm(Tencent Cloud) | ✓ | ✓ | ✓ | ✓ | — | — | +| ModelScope(魔搭, 중국판 / 국제판) | ✓ | ✗ 토큰 장기 유효 | ✓ 원격 전용 | ✓ 마립 잔액 | ✓ 매일 마립(로그인 API 호출로 발동) | — | | 智谱清言(Zhipu Qingyan) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | 사용자 지정 프로바이더 | ✓ | — | ✓ | — | — | — | @@ -251,7 +252,7 @@ macOS 의 `.dmg` 는 **macOS 에서만 빌드할 수 있습니다**(`npm --prefi ### 학습과 교류 목적에 한정 -이 프로젝트는 HTTP 리버스 프록시, SSE 스트리밍 패스스루, 다중 업스트림 프로토콜 적응, 데스크톱 패키징(Tauri) 같은 기술 주제를 익히기 위한 실습 프로젝트이며, **개인 학습과 연구 목적으로만** 제공됩니다. 공식 제품이 아니며 Tencent 및 WorkBuddy / CodeBuddy, Meituan 및 CatPaw, SenseTime 및 小浣熊, Zhipu 및 AutoClaw / autoglm, Alibaba 및 Qoder / Accio, Huawei Cloud 및 CodeArts / OfficeAce, ByteDance 및 Trae, iFlytek 및 Loomy, Baidu Wenku 및 KukuAI, 长亭科技 및 MonkeyCode, Command Code, Google 및 Antigravity 와 아무런 관련이 없고, 그 승인이나 후원도 받지 않았습니다. +이 프로젝트는 HTTP 리버스 프록시, SSE 스트리밍 패스스루, 다중 업스트림 프로토콜 적응, 데스크톱 패키징(Tauri) 같은 기술 주제를 익히기 위한 실습 프로젝트이며, **개인 학습과 연구 목적으로만** 제공됩니다. 공식 제품이 아니며 Tencent 및 WorkBuddy / CodeBuddy, Meituan 및 CatPaw, SenseTime 및 小浣熊, Zhipu 및 AutoClaw / autoglm, Alibaba 및 Qoder / Accio, Huawei Cloud 및 CodeArts / OfficeAce, ByteDance 및 Trae, iFlytek 및 Loomy, Baidu Wenku 및 KukuAI, 长亭科技 및 MonkeyCode, Command Code, Google 및 Antigravity, Alibaba 및 ModelScope(魔搭) 와 아무런 관련이 없고, 그 승인이나 후원도 받지 않았습니다. ### 리버스 프록시 동작에 대하여 diff --git a/docs/README.pt-BR.md b/docs/README.pt-BR.md index e6ced18f..d1d784db 100644 --- a/docs/README.pt-BR.md +++ b/docs/README.pt-BR.md @@ -76,6 +76,7 @@ Panorama dos recursos de proxy reverso por plataforma (✓ suportado · ✗ não | Antigravity (Google, Gemini / Claude / GPT-OSS) | ✓ | ✓ | ✓ | — | — | — | | OfficeAce (Huawei Cloud, OfficeClaw) | ✓ | ✓ | ✓ | ✓ | ✓ | — | | OrcaTerm (Tencent Cloud) | ✓ | ✓ | ✓ | ✓ | — | — | +| ModelScope (ModelScope.cn / ModelScope Intl) | ✓ | ✗ token não expira | ✓ somente remoto | ✓ saldo de créditos | ✓ créditos diários (chamar o endpoint de login dispara) | — | | Zhipu Qingyan | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Provedores personalizados | ✓ | — | ✓ | — | — | — | @@ -251,7 +252,7 @@ O `.dmg` do macOS **só pode ser compilado no macOS** (`npm --prefix desktop-tau ### Apenas para aprendizado e discussão -Este projeto é um exercício prático de proxy reverso HTTP, passthrough de streaming SSE, adaptação de protocolos de múltiplos upstreams e empacotamento desktop (Tauri), e destina-se **apenas a aprendizado e pesquisa pessoal**. Não é um produto oficial e não tem qualquer vínculo, endosso ou patrocínio de Tencent e WorkBuddy / CodeBuddy, Meituan e CatPaw, SenseTime e 小浣熊, Zhipu e AutoClaw / autoglm, Alibaba e Qoder / Accio, Huawei Cloud e CodeArts / OfficeAce, ByteDance e Trae, iFlytek e Loomy, Baidu Wenku e KukuAI, 长亭科技 e MonkeyCode, Command Code, ou Google e Antigravity. +Este projeto é um exercício prático de proxy reverso HTTP, passthrough de streaming SSE, adaptação de protocolos de múltiplos upstreams e empacotamento desktop (Tauri), e destina-se **apenas a aprendizado e pesquisa pessoal**. Não é um produto oficial e não tem qualquer vínculo, endosso ou patrocínio de Tencent e WorkBuddy / CodeBuddy, Meituan e CatPaw, SenseTime e 小浣熊, Zhipu e AutoClaw / autoglm, Alibaba e Qoder / Accio, Huawei Cloud e CodeArts / OfficeAce, ByteDance e Trae, iFlytek e Loomy, Baidu Wenku e KukuAI, 长亭科技 e MonkeyCode, Command Code, ou Google e Antigravity, ou Alibaba e ModelScope. ### Sobre o comportamento de proxy reverso diff --git a/docs/README.zh-Hant.md b/docs/README.zh-Hant.md index 8f1b5f4c..2b00de33 100644 --- a/docs/README.zh-Hant.md +++ b/docs/README.zh-Hant.md @@ -76,6 +76,7 @@ Agent2API 把多家 AI 桌面客戶端裡已登入的帳號接到一起,共用 | Antigravity(Google,Gemini / Claude / GPT-OSS) | ✓ | ✓ | ✓ | — | — | — | | OfficeAce(華為雲果辦 / OfficeClaw) | ✓ | ✓ | ✓ | ✓ | ✓ | — | | OrcaTerm(騰訊雲遨馳終端) | ✓ | ✓ | ✓ | ✓ | — | — | +| ModelScope(魔搭,國內版 / 國際版) | ✓ | ✗ 權杖長期有效 | ✓ 僅遠端 | ✓ 魔粒餘額 | ✓ 每日魔粒(呼叫登入介面即觸發) | — | | 智譜清言 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | 自訂供應商 | ✓ | — | ✓ | — | — | — |