@forsion/extend 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # 更新日志
2
2
 
3
+ ## 0.5.0 — 2026-09-29
4
+
5
+ - 设置里新增「Forsion 云端」,和账号有关的事在桌面端就能办完:
6
+ - 账号:头像、昵称、绑定的手机和邮箱、会员档位与到期日,以及这台电脑上登录过的账号;
7
+ - 额度与积分:今日和本周的 AI 额度、额度重置卡(使用和用积分兑换)、积分余额与充值、后台额度(Muse 与自动化使用)、邀请码和兑换码;
8
+ - 安全:绑定或更换手机和邮箱、修改密码、退出所有设备、注销账号;
9
+ - 用量记录:最近 7、30、90 天的请求次数、成功率和 AI 额度消耗;
10
+ - 反馈:提交问题和建议,并直接在桌面上看到回复。
11
+ - AI 额度统一只显示剩余百分比,进度条按剩余填充;额度为 0 时显示 0%,不再误显示成「不限」。
12
+ - 改密码的规则与服务端一致并写在界面上;只绑定了邮箱也能用验证码改密码,也可以直接用当前密码修改。
13
+ - 充值积分会直接打开充值页;已下线的周重置卡不再出现。
14
+ - 需要较新的 Forsion 桌面端,这些页面才会出现;旧桌面端上本包不显示它们,账号设置照旧用桌面端自带的那一页。
15
+
16
+ - Settings now has a Forsion Cloud section, so you can take care of your account without leaving the desktop app:
17
+ - Account: your photo, nickname, linked phone and email, membership tier and expiry date, and the accounts you've signed in with on this computer;
18
+ - Quota & points: today's and this week's AI quota, quota reset cards (use one or exchange points for more), your points balance and top-ups, the background quota used by Muse and automations, invite codes and redemption codes;
19
+ - Security: link or change your phone and email, change your password, sign out everywhere, delete your account;
20
+ - Usage: requests, success rate and AI quota used over the last 7, 30 or 90 days;
21
+ - Feedback: send issues and suggestions, and read replies right in the app.
22
+ - AI quota is always shown as the percentage left, and the bars show what remains; a quota of 0 now reads 0% instead of Unlimited.
23
+ - Password rules match the server and are listed on screen. You can change your password with a verification code even if you only linked an email, or directly with your current password.
24
+ - Buying points opens the points page directly, and the retired weekly reset card no longer appears.
25
+ - These pages need a newer Forsion Desktop build. On older desktops this package doesn't show them, and account settings stay on the page the desktop already has.
26
+
27
+ ## 0.4.0 — 2026-09-28
28
+
29
+ - 笔记的云端同步与协作从 Forsion 本体搬入本包:云端笔记库镜像、按条目同步、与我共享、页面分享 / 发布 / 在线成员,行为与之前一致。没装本包的桌面端不再显示云端笔记库、云同步与分享入口。
30
+ - 需要较新的 Forsion 桌面端才会启用;旧桌面端上本包只提供 0.3 的功能,不影响使用。
31
+
32
+ Cloud sync and collaboration for notes now ship in this package, moved over from Forsion itself with their behavior unchanged: the cloud vault mirror, per-item sync, shared-with-me, page sharing / publishing / presence. Desktops without this package no longer show the cloud vault, cloud sync or sharing entry points.
33
+ This needs a newer Forsion Desktop build; on older desktops this package keeps providing the 0.3 features and nothing else changes.
34
+
3
35
  ## 0.3.0 — 2026-09-28
4
36
 
5
37
  - 账号登录态从 Forsion 本体搬入本包:登录、登出、切换账号、账号状态与登录态自动续期都由本包提供,行为与之前一致。没装本包的桌面端不再显示账号卡、Forsion 设置页与登录入口。
package/README.md CHANGED
@@ -1,27 +1,47 @@
1
1
  # Forsion Extend
2
2
 
3
- Forsion 桌面端里**跟云端账号打交道的那一半**:账号登录 / 登出 / 切换与登录态续期(0.3 起),个人中心 / 会员页入口、额度视图与重置卡、后台额度转换、反馈中心提交,插件以当前账号身份调 Forsion 云端 API 的通用接缝 `cloud:fetch`,Forsion Connect(0.2 起)—— Coding Space 项目发布、应用商店上架申请、预览态 AI 代理(预览页的 `window.forsion` SDK 与 `/__forsion/*` 云端代理),以及本地库远程同步的 Forsion 云端后端(0.3 起)。它是一个 Forsion 捆绑包(manifest.json + 渲染半身 + 主进程半身),编译产物以 npm 包 `@forsion/extend` 发布。
3
+ Forsion Extend 是 Forsion 桌面端内置的扩展,负责和你的 Forsion 云端账号有关的一切。它随桌面端一起安装,在后台自动更新,不需要单独下载或设置。
4
4
 
5
- The **cloud-account half of Forsion Desktop**: account sign-in, sign-out, switching and staying signed in (since 0.3), the account center and membership page shortcuts, the quota view and reset cards, background quota conversion, feedback submission, `cloud:fetch` (the shared seam plugins use to call the Forsion cloud API as the signed-in account), Forsion Connect (since 0.2): Coding Space project publishing, app store listing requests, and the preview-mode AI proxy (the `window.forsion` SDK served to preview pages plus the `/__forsion/*` cloud proxy), and the Forsion cloud backend for remote sync of the local vault (since 0.3). It is a Forsion bundle (manifest.json + a renderer half + a main-process half), published as the npm package `@forsion/extend`.
5
+ ## 它能做什么
6
6
 
7
- ## Forsion 桌面端怎么装载它 / How Forsion Desktop loads it
7
+ - **登录与账号**:登录 Forsion,在这台电脑登录过的账号之间切换,退出登录。登录状态会自动续期,经常使用就不用反复登录。
8
+ - **设置里的「Forsion 云端」**:
9
+ - **账号**:头像、昵称、绑定的手机和邮箱,会员档位与到期日,这台电脑上的账号。
10
+ - **额度与积分**:今日和本周还剩多少 AI 额度,额度重置卡,积分余额与充值,后台额度(Muse 与自动化使用),邀请码和兑换码。
11
+ - **安全**:绑定或更换手机和邮箱,修改密码,退出所有设备,注销账号。
12
+ - **用量记录**:最近 7、30、90 天的请求次数、成功率和 AI 额度消耗。
13
+ - **反馈**:提交问题和建议,在桌面上查看回复。
14
+ - **笔记云同步与协作**:云端笔记库、按条目同步、与我共享,以及页面分享、发布和在线成员。
15
+ - **Forsion Connect**:把 Coding Space 里的项目发布成网页、申请上架应用商店;预览项目时也能用上 Forsion 的 AI。
8
16
 
9
- Forsion 桌面端把本包当**内置捆绑包**:随桌面安装包带一份,启动时播种进 `<home>/plugins/forsion-extend/`,之后由 npm 更新器在后台下载新版、下次启动换上。带主进程半身的包比普通捆绑包多一道闸:播种 / 换版前,桌面端用钉在自己代码里的 ed25519 公钥核对包内 `SIGNATURE`(每个打包文件的 sha256 + 签名),验不过的那份不换、不载;验过后 `import()` `dist/desktop.mjs`,调用 `registerCloud(host)` 注册 8 个云端账号 IPC 通道;桌面端够新(提供对应的宿主接缝)时再注册 7 个 `connect:*` 通道与预览挂钩(0.2)、5 个 `auth:*` 登录态通道与远程同步的 penzor 后端(0.3),旧桌面端上缺接缝的那块自动跳过、其余功能照常。桌面端的界面按这些通道是否存在显示或隐藏:没装本包就没有账号卡、Forsion 设置页、登录入口与「Forsion 云端」同步后端。
17
+ ## 设置在哪里
10
18
 
11
- Forsion Desktop treats this package as a **built-in bundle**: a copy ships inside the desktop installer, is seeded into `<home>/plugins/forsion-extend/` on startup, and the npm updater downloads newer versions in the background and switches to them on the next launch. A bundle with a main-process half has one extra gate: before seeding or switching, the desktop checks the in-package `SIGNATURE` (sha256 of every packed file plus an ed25519 signature) against the public key pinned in its own code; a copy that fails is neither installed nor loaded. Once verified, the desktop `import()`s `dist/desktop.mjs` and calls `registerCloud(host)`, which registers the 8 cloud-account IPC channels and, when the desktop is new enough to provide the matching host seam, the 7 `connect:*` channels plus the preview hooks (0.2) and the 5 `auth:*` sign-in channels plus the penzor remote-sync backend (0.3); on older desktops the parts without a seam are skipped and the rest works as before. The desktop shows or hides its UI by whether these channels exist: without this package there is no account card, Forsion settings page, sign-in entry point or "Forsion cloud" sync backend.
19
+ 打开「设置 → Forsion 云端」:左侧是账号、额度与积分、安全、用量记录、反馈这几页,同步与云端地址也在这里。云空间、AI 大脑、投稿和主题在网页个人中心管理,账号页底部有「在浏览器中打开个人中心」。
12
20
 
13
- | 包内文件 / file | 用途 / role |
14
- |---|---|
15
- | `manifest.json` | 捆绑包清单:`id` = `forsion-extend`,`main` = `dist/main.js` / bundle manifest |
16
- | `dist/main.js` | 渲染半身(iife,宿主 `new Function('ctx', code)` 装载;目前为空)/ renderer half, currently empty |
17
- | `dist/desktop.mjs` | 主进程半身(ESM,验签后 `import()`)/ main-process half, imported after signature check |
18
- | `SIGNATURE` | 包内签名 / in-package signature |
19
- | `CHANGELOG.md` | 显示在桌面「设置 → 插件」详情页 / shown in Settings → Plugins |
21
+ 没看到「Forsion 云端」?到「设置 → 插件」确认 Forsion Extend 已启用(启用或停用后要重启 Forsion 才生效)。较早版本的 Forsion 桌面端会把这几页显示在插件详情页里。
20
22
 
21
- 这个包不能单独安装或运行:它只在 Forsion 桌面端里作为内置包使用,更新由桌面端自己完成。
23
+ ---
22
24
 
23
- This package is not installed or run on its own: it is used only as a built-in bundle inside Forsion Desktop, which updates it by itself.
25
+ Forsion Extend is built into Forsion Desktop and takes care of everything to do with your Forsion cloud account. It is installed with the desktop app and updates itself in the background, so there is nothing to download or set up.
26
+
27
+ ## What it does
28
+
29
+ - **Signing in**: sign in to Forsion, switch between the accounts you've used on this computer, and sign out. Your sign-in renews itself, so regular use doesn't keep asking you to sign in.
30
+ - **Forsion Cloud in Settings**:
31
+ - **Account**: your photo, nickname, linked phone and email, membership tier and expiry date, and the accounts on this computer.
32
+ - **Quota & points**: how much AI quota is left today and this week, quota reset cards, your points balance and top-ups, the background quota used by Muse and automations, invite codes and redemption codes.
33
+ - **Security**: link or change your phone and email, change your password, sign out everywhere, delete your account.
34
+ - **Usage**: requests, success rate and AI quota used over the last 7, 30 or 90 days.
35
+ - **Feedback**: send issues and suggestions, and read replies in the app.
36
+ - **Note sync and collaboration**: the cloud vault, per-item sync, shared with me, and page sharing, publishing and presence.
37
+ - **Forsion Connect**: publish Coding Space projects as web pages and apply for an app store listing; project previews can use Forsion's AI too.
38
+
39
+ ## Where to find it
40
+
41
+ Open Settings → Forsion Cloud. The pages on the left are Account, Quota & points, Security, Usage and Feedback, and sync and the cloud address live there too. Cloud storage, AI Brain, submissions and themes are managed in the web account center; the Account page has a link that opens it in your browser.
42
+
43
+ Don't see Forsion Cloud? Check that Forsion Extend is turned on under Settings → Plugins (turning it on or off takes effect after you restart Forsion). Older versions of Forsion Desktop show these pages on the plugin's detail page instead.
24
44
 
25
45
  ## License
26
46
 
27
- 专有授权,见 [LICENSE](./LICENSE):仅允许作为 Forsion 的一部分使用与再分发。Proprietary, see [LICENSE](./LICENSE): use and redistribution only as part of Forsion.
47
+ 专有授权,见 [LICENSE](./LICENSE):仅允许作为 Forsion 的一部分使用与再分发。Proprietary, see [LICENSE](./LICENSE): use and redistribution only as part of Forsion.
package/SIGNATURE CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "alg": "ed25519",
3
3
  "files": {
4
- "CHANGELOG.md": "00eab66ddc784373fa030c7f88885dac39e894fec99d1a9a192efba14e272eca",
4
+ "CHANGELOG.md": "d3300df76fd7858fce4a5ccc5e0662f4987e3012b93345d5d552115c35d644c5",
5
5
  "LICENSE": "5594544ee08011ed5785ee26410f1f2ef005f66e9283833e8d435e34c10de1ed",
6
- "README.md": "2e47ea40144d4b49ad23bfb550b7acbb64f7eac2004bebdebfbc02184333314c",
7
- "dist/desktop.mjs": "652418d8a89ad3a9f7e306ed830b698df9b871147d58a9d5856b62e0f58b33fc",
8
- "dist/main.js": "8669f048a0e9a5d47dc657306109ab437da6683ad925fbd6a451aef72542a787",
9
- "manifest.json": "619832ba87b6d239244d51062537601ff84181ee00e6baabba6e3867ebcd9de7",
10
- "package.json": "27cf696785b46a722f9efd4d7f114aeea02d7cf664ce343193f6ccc3efd9cfdf"
6
+ "README.md": "a17ef4b3c8adefcbee2efda0c1bbca1fc8aa63dce323295708c321a9d322a80c",
7
+ "dist/desktop.mjs": "f4f688fcb1c3d386d22a91beec1a986020d08a95f3bceada2e145ea54cc80ad5",
8
+ "dist/main.js": "b5a698729f080d9e257d047f4740e39c143c39ea435ba5f941004e60e56957a8",
9
+ "manifest.json": "9ce8552cd16bd5e66b4369c8551b67c8c527f00836af258c47db0227f1b9bb61",
10
+ "package.json": "44215e4007227ef3ab4b27396c70bba422523086cc173f29e87f57ff5263e5ed"
11
11
  },
12
- "sig": "IrYOnk4++zOfgv9C/bm+Bcq27QnCRwe011X3Wste3V4aeib5Aa6HAsWK9Vh4EtdDlRnLxq5kA5hYajktDfnCCQ=="
12
+ "sig": "JReR+GdnrUTrg/0CD/aVi2ve7dbnDawMx3DftqjUKMyiR+diG24q4rN/2wPv6sXvr3DZAJEqjeN0sqzkXbE0Dw=="
13
13
  }
package/dist/desktop.mjs CHANGED
@@ -1,7 +1,7 @@
1
- function N(e,o){if(typeof o!="string"||!o.startsWith("/"))return null;let t=String(e||"").replace(/\/+$/,"").replace(/\/api$/,"");if(!t)return null;let r,n;try{r=new URL(t),n=new URL(t+"/api"+o)}catch{return null}return r.protocol!=="http:"&&r.protocol!=="https:"||n.origin!==r.origin||!n.pathname.startsWith("/api/")?null:n.toString()}async function w(e,o,t,r,n=6e4){let s=await fetch(e.base+t,{method:o,headers:{"Content-Type":"application/json","X-Project-Source":"connect",...e.token?{Authorization:`Bearer ${e.token}`}:{}},body:r===void 0?void 0:JSON.stringify(r),signal:AbortSignal.timeout(n)}),c=await s.json().catch(()=>({}));return{status:s.status,json:c}}import{readdirSync as ie,lstatSync as ce,readFileSync as E,writeFileSync as ue,realpathSync as L}from"node:fs";import{join as x,extname as le,sep as de}from"node:path";var A=300,H=5*1024*1024,z=20*1024*1024,fe=50*1024*1024,me=new Set(["node_modules"]),ge=new Set([".ts",".tsx",".jsx",".mts",".cts"]);function D(e,o){let t=[],r=0,n=(s,c)=>{for(let a of ie(s)){if(a.startsWith("."))continue;let i=x(s,a),l;try{l=ce(i)}catch{continue}if(l.isSymbolicLink())continue;let m=c?`${c}/${a}`:a;if(l.isDirectory()){me.has(a)||n(i,m);continue}if(!l.isFile()||a.endsWith(".d.ts"))continue;if(t.length>=A)throw new Error(`\u6587\u4EF6\u6570\u8D85\u8FC7 ${A}\uFF0C\u8BF7\u7CBE\u7B80\u9879\u76EE\uFF08node_modules \u4E0E\u9690\u85CF\u6587\u4EF6\u5DF2\u81EA\u52A8\u8DF3\u8FC7\uFF09`);let u=le(a).toLowerCase(),d,p=o.mimeOf(u)??"application/octet-stream";if(ge.has(u)){let f=o.transpile(E(i,"utf8"),u,m);d=Buffer.from(f??"","utf8"),p="text/javascript"}else d=E(i);if(d.length>H)throw new Error(`\u5355\u6587\u4EF6\u8D85\u8FC7 5MB\uFF1A${m}`);if(r+=d.length,r>z)throw new Error("\u9879\u76EE\u603B\u5927\u5C0F\u8D85\u8FC7 20MB\uFF0C\u65E0\u6CD5\u53D1\u5E03");t.push({path:m,content_b64:d.toString("base64"),content_type:p,size:d.length})}};if(n(e,""),!t.length)throw new Error("\u9879\u76EE\u4E3A\u7A7A\uFF0C\u6CA1\u6709\u53EF\u53D1\u5E03\u7684\u6587\u4EF6");return{files:t,totalBytes:r}}var B=".forsion-connect.json";function J(e){try{return JSON.parse(E(x(e,B),"utf8"))}catch{return{}}}function q(e,o){try{ue(x(e,B),JSON.stringify(o,null,2)+`
2
- `,"utf8")}catch{}}function W(e){let o={"/__forsion/chat":{method:"POST",path:"/api/chat/completions",auth:!0},"/__forsion/images":{method:"POST",path:"/api/images/generations",auth:!0},"/__forsion/user":{method:"GET",path:"/api/brain/users/me",auth:!0},"/__forsion/models":{method:"GET",path:"/api/models",auth:!1},"/__forsion/config":{method:"GET",path:"/api/connect/config",auth:!1},"/__forsion/agent":{method:"POST",path:"/api/agent/runs",auth:!0,agentRun:!0}};function t(r){if(o[r])return o[r];let n="/__forsion/agent-events/";if(r.startsWith(n)){let s=r.slice(n.length);if(/^[A-Za-z0-9-]{1,64}$/.test(s))return{method:"GET",path:`/api/agent/runs/${s}/events`,auth:!0,timeoutMs:9e5}}}return async(r,n)=>{let[s,c]=(r.url||"").split("?"),a=(f,g)=>{n.headersSent||(n.statusCode=f,n.setHeader("Content-Type","application/json")),n.end(JSON.stringify({detail:g}))},i=t(s);if(!i)return a(404,"unknown connect endpoint");if((r.method||"GET")!==i.method)return a(405,"method not allowed");let l="",m="";try{({base:l,token:m}=await e())}catch{}if(!l)return a(502,"\u672A\u914D\u7F6E Forsion \u4E91\u7AEF\u5730\u5740");if(i.auth&&!m)return a(401,"\u8BF7\u5148\u5728 Forsion Desktop \u4E2D\u767B\u5F55 Forsion \u8D26\u53F7");let u;if(i.method==="POST"){let f=[],g=0;try{for await(let h of r){if(g+=h.length,g>fe)return r.destroy(),a(413,"\u8BF7\u6C42\u4F53\u8FC7\u5927");f.push(h)}}catch(h){return a(400,`\u8BF7\u6C42\u4F53\u8BFB\u53D6\u5931\u8D25\uFF1A${h?.message||String(h)}`)}u=Buffer.concat(f)}if(i.agentRun){let f;try{f=JSON.parse((u||Buffer.alloc(0)).toString("utf8")||"{}")}catch{return a(400,"agent \u8BF7\u6C42\u4F53\u5FC5\u987B\u662F JSON")}u=Buffer.from(JSON.stringify({session_id:typeof f.session_id=="string"?f.session_id:"",message:typeof f.message=="string"?f.message:"",app_id:"connect",agent_config:{}}))}let d=new AbortController,p=setTimeout(()=>d.abort(new Error("proxy timeout")),i.timeoutMs??3e5);r.on("close",()=>d.abort());try{let f=await fetch(l+i.path+(c?`?${c}`:""),{method:i.method,headers:{"Content-Type":"application/json","X-Project-Source":"connect",...m?{Authorization:`Bearer ${m}`}:{}},body:u&&u.length?new Uint8Array(u):void 0,signal:d.signal});if(n.statusCode=f.status,n.setHeader("Content-Type",f.headers.get("content-type")||"application/json"),n.setHeader("Cache-Control","no-store"),f.body)for await(let g of f.body)n.write(g);n.end()}catch(f){let g=`\u4E91\u7AEF\u8BF7\u6C42\u4E2D\u65AD\uFF1A${f?.message||String(f)}`;if(n.headersSent){try{n.write(`data: ${JSON.stringify({error:g})}
1
+ function Tn(t,e){if(typeof e!="string"||!e.startsWith("/"))return null;let n=String(t||"").replace(/\/+$/,"").replace(/\/api$/,"");if(!n)return null;let s,r;try{s=new URL(n),r=new URL(n+"/api"+e)}catch{return null}return s.protocol!=="http:"&&s.protocol!=="https:"||r.origin!==s.origin||!r.pathname.startsWith("/api/")?null:r.toString()}async function me(t,e,n,s,r=6e4){let o=await fetch(t.base+n,{method:e,headers:{"Content-Type":"application/json","X-Project-Source":"connect",...t.token?{Authorization:`Bearer ${t.token}`}:{}},body:s===void 0?void 0:JSON.stringify(s),signal:AbortSignal.timeout(r)}),a=await o.json().catch(()=>({}));return{status:o.status,json:a}}import{readdirSync as Vr,lstatSync as Gr,readFileSync as Ft,writeFileSync as Yr,realpathSync as Rn}from"node:fs";import{join as Lt,extname as Jr,sep as Kr}from"node:path";var Ot=300,In=5*1024*1024,An=20*1024*1024,Xr=50*1024*1024,Qr=new Set(["node_modules"]),Zr=new Set([".ts",".tsx",".jsx",".mts",".cts"]);function Pn(t,e){let n=[],s=0,r=(o,a)=>{for(let c of Vr(o)){if(c.startsWith("."))continue;let l=Lt(o,c),m;try{m=Gr(l)}catch{continue}if(m.isSymbolicLink())continue;let h=a?`${a}/${c}`:c;if(m.isDirectory()){Qr.has(c)||r(l,h);continue}if(!m.isFile()||c.endsWith(".d.ts"))continue;if(n.length>=Ot)throw new Error(`\u6587\u4EF6\u6570\u8D85\u8FC7 ${Ot}\uFF0C\u8BF7\u7CBE\u7B80\u9879\u76EE\uFF08node_modules \u4E0E\u9690\u85CF\u6587\u4EF6\u5DF2\u81EA\u52A8\u8DF3\u8FC7\uFF09`);let f=Jr(c).toLowerCase(),u,y=e.mimeOf(f)??"application/octet-stream";if(Zr.has(f)){let _=e.transpile(Ft(l,"utf8"),f,h);u=Buffer.from(_??"","utf8"),y="text/javascript"}else u=Ft(l);if(u.length>In)throw new Error(`\u5355\u6587\u4EF6\u8D85\u8FC7 5MB\uFF1A${h}`);if(s+=u.length,s>An)throw new Error("\u9879\u76EE\u603B\u5927\u5C0F\u8D85\u8FC7 20MB\uFF0C\u65E0\u6CD5\u53D1\u5E03");n.push({path:h,content_b64:u.toString("base64"),content_type:y,size:u.length})}};if(r(t,""),!n.length)throw new Error("\u9879\u76EE\u4E3A\u7A7A\uFF0C\u6CA1\u6709\u53EF\u53D1\u5E03\u7684\u6587\u4EF6");return{files:n,totalBytes:s}}var Dn=".forsion-connect.json";function $n(t){try{return JSON.parse(Ft(Lt(t,Dn),"utf8"))}catch{return{}}}function Mn(t,e){try{Yr(Lt(t,Dn),JSON.stringify(e,null,2)+`
2
+ `,"utf8")}catch{}}function Nn(t){let e={"/__forsion/chat":{method:"POST",path:"/api/chat/completions",auth:!0},"/__forsion/images":{method:"POST",path:"/api/images/generations",auth:!0},"/__forsion/user":{method:"GET",path:"/api/brain/users/me",auth:!0},"/__forsion/models":{method:"GET",path:"/api/models",auth:!1},"/__forsion/config":{method:"GET",path:"/api/connect/config",auth:!1},"/__forsion/agent":{method:"POST",path:"/api/agent/runs",auth:!0,agentRun:!0}};function n(s){if(e[s])return e[s];let r="/__forsion/agent-events/";if(s.startsWith(r)){let o=s.slice(r.length);if(/^[A-Za-z0-9-]{1,64}$/.test(o))return{method:"GET",path:`/api/agent/runs/${o}/events`,auth:!0,timeoutMs:9e5}}}return async(s,r)=>{let[o,a]=(s.url||"").split("?"),c=(_,T)=>{r.headersSent||(r.statusCode=_,r.setHeader("Content-Type","application/json")),r.end(JSON.stringify({detail:T}))},l=n(o);if(!l)return c(404,"unknown connect endpoint");if((s.method||"GET")!==l.method)return c(405,"method not allowed");let m="",h="";try{({base:m,token:h}=await t())}catch{}if(!m)return c(502,"\u672A\u914D\u7F6E Forsion \u4E91\u7AEF\u5730\u5740");if(l.auth&&!h)return c(401,"\u8BF7\u5148\u5728 Forsion Desktop \u4E2D\u767B\u5F55 Forsion \u8D26\u53F7");let f;if(l.method==="POST"){let _=[],T=0;try{for await(let E of s){if(T+=E.length,T>Xr)return s.destroy(),c(413,"\u8BF7\u6C42\u4F53\u8FC7\u5927");_.push(E)}}catch(E){return c(400,`\u8BF7\u6C42\u4F53\u8BFB\u53D6\u5931\u8D25\uFF1A${E?.message||String(E)}`)}f=Buffer.concat(_)}if(l.agentRun){let _;try{_=JSON.parse((f||Buffer.alloc(0)).toString("utf8")||"{}")}catch{return c(400,"agent \u8BF7\u6C42\u4F53\u5FC5\u987B\u662F JSON")}f=Buffer.from(JSON.stringify({session_id:typeof _.session_id=="string"?_.session_id:"",message:typeof _.message=="string"?_.message:"",app_id:"connect",agent_config:{}}))}let u=new AbortController,y=setTimeout(()=>u.abort(new Error("proxy timeout")),l.timeoutMs??3e5);s.on("close",()=>u.abort());try{let _=await fetch(m+l.path+(a?`?${a}`:""),{method:l.method,headers:{"Content-Type":"application/json","X-Project-Source":"connect",...h?{Authorization:`Bearer ${h}`}:{}},body:f&&f.length?new Uint8Array(f):void 0,signal:u.signal});if(r.statusCode=_.status,r.setHeader("Content-Type",_.headers.get("content-type")||"application/json"),r.setHeader("Cache-Control","no-store"),_.body)for await(let T of _.body)r.write(T);r.end()}catch(_){let T=`\u4E91\u7AEF\u8BF7\u6C42\u4E2D\u65AD\uFF1A${_?.message||String(_)}`;if(r.headersSent){try{r.write(`data: ${JSON.stringify({error:T})}
3
3
 
4
- `)}catch{}n.end()}else a(502,g)}finally{clearTimeout(p)}}}var G=`
4
+ `)}catch{}r.end()}else c(502,T)}finally{clearTimeout(y)}}}var Fn=`
5
5
  (function () {
6
6
  'use strict';
7
7
  if (window.forsion) return;
@@ -190,4 +190,15 @@ function N(e,o){if(typeof o!="string"||!o.startsWith("/"))return null;let t=Stri
190
190
  ai: { chat: chat, agent: agentRun, generateImage: generateImage }
191
191
  };
192
192
  })();
193
- `,pe=e=>({transpile:(o,t,r)=>e.transpileForServe(o,t,r),mimeOf:o=>e.mimeOf(o)});function j(e){let o=e;return typeof o.projectsRoot=="function"&&typeof o.transpileForServe=="function"&&typeof o.mimeOf=="function"&&typeof o.setPreviewHooks=="function"}function P(e){e.setPreviewHooks({sdkJs:G,proxy:W(()=>e.getCloud())}),e.handle("connect:meta",(o,t)=>typeof t=="string"&&t?J(t):{}),e.handle("connect:list",async()=>{let o=await e.getCloud();if(!o.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{status:t,json:r}=await w(o,"GET","/api/connect/apps");return t===401||t===403?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:t!==200?{ok:!1,code:"error",detail:r?.detail||`HTTP ${t}`}:{ok:!0,base:o.base,...r}}catch(t){return{ok:!1,code:"error",detail:t?.message||String(t)}}}),e.handle("connect:publish",async(o,t)=>{if(!t||typeof t.dir!="string"||!t.dir||!t.name||!t.slug||!t.entry)return{ok:!1,code:"error",detail:"\u53C2\u6570\u4E0D\u5B8C\u6574"};let r;try{let s=L(e.projectsRoot());if(r=L(t.dir),r!==s&&!r.startsWith(s+de))return{ok:!1,code:"error",detail:"\u53EA\u80FD\u53D1\u5E03 Coding Space \u9879\u76EE\u76EE\u5F55"}}catch{return{ok:!1,code:"error",detail:"\u9879\u76EE\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u8BBF\u95EE"}}let n=await e.getCloud();if(!n.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{files:s,totalBytes:c}=D(r,pe(e));if(!s.some(l=>l.path===t.entry))return{ok:!1,code:"error",detail:`\u5165\u53E3\u6587\u4EF6\u4E0D\u5B58\u5728:${t.entry}`};let{status:a,json:i}=await w(n,"POST","/api/connect/apps",{slug:t.slug,name:t.name,entry:t.entry,files:s},3e5);return a===401?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:a!==200?{ok:!1,code:i?.code||"error",detail:i?.detail||`HTTP ${a}`,used:i?.used,limit:i?.limit}:(q(r,{slug:String(i.slug)}),{ok:!0,slug:i.slug,handle:i.handle,url:`${n.base}${i.url}`,totalBytes:c})}catch(s){return{ok:!1,code:"error",detail:s?.message||String(s)}}}),e.handle("connect:unpublish",async(o,t)=>{if(!t||typeof t!="string")return{ok:!1,code:"error",detail:"\u53C2\u6570\u4E0D\u5B8C\u6574"};let r=await e.getCloud();if(!r.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{status:n,json:s}=await w(r,"DELETE",`/api/connect/apps/${encodeURIComponent(t)}`);return n===401||n===403?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:n!==200&&n!==404?{ok:!1,code:"error",detail:s?.detail||`HTTP ${n}`}:{ok:!0}}catch(n){return{ok:!1,code:"error",detail:n?.message||String(n)}}}),e.handle("connect:listingApply",async(o,t)=>{if(!t||typeof t.slug!="string"||!t.slug||typeof t.summary!="string"||!t.summary.trim())return{ok:!1,code:"error",detail:"\u53C2\u6570\u4E0D\u5B8C\u6574"};let r=await e.getCloud();if(!r.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{status:n,json:s}=await w(r,"PUT",`/api/connect/apps/${encodeURIComponent(t.slug)}/listing`,{summary:t.summary});return n===401?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:n!==200?{ok:!1,code:s?.code||"error",detail:s?.detail||`HTTP ${n}`}:{ok:!0,status:s.status}}catch(n){return{ok:!1,code:"error",detail:n?.message||String(n)}}}),e.handle("connect:listingWithdraw",async(o,t)=>{if(!t||typeof t!="string")return{ok:!1,code:"error",detail:"\u53C2\u6570\u4E0D\u5B8C\u6574"};let r=await e.getCloud();if(!r.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{status:n,json:s}=await w(r,"DELETE",`/api/connect/apps/${encodeURIComponent(t)}/listing`);return n===401?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:n!==200&&n!==404?{ok:!1,code:"error",detail:s?.detail||`HTTP ${n}`}:{ok:!0}}catch(n){return{ok:!1,code:"error",detail:n?.message||String(n)}}}),e.handle("connect:store",async()=>{let o=await e.getCloud();try{let{status:t,json:r}=await w(o,"GET","/api/connect/store");return t!==200?{ok:!1,detail:r?.detail||`HTTP ${t}`}:{ok:!0,base:o.base,items:Array.isArray(r.items)?r.items:[]}}catch(t){return{ok:!1,detail:t?.message||String(t)}}}),e.log("[forsion-extend] connect handlers registered")}import{createHash as he}from"node:crypto";async function v(e,o){if(!e||!o)return{status:"offline"};let t=e.replace(/\/+$/,"");try{let r=await fetch(`${t}/api/brain/users/me`,{headers:{Authorization:`Bearer ${o}`},signal:AbortSignal.timeout(5e3)});if(r.status===401||r.status===403)return{status:(r.headers.get("content-type")||"").includes("application/json")?"expired":"offline"};if(!r.ok)return{status:"offline"};let n=await r.json();if(!n)return{status:"offline"};let s=n.avatar||n.avatarUrl||n.avatar_url||void 0;return s&&/^\/(?!\/)/.test(s)&&(s=t+s),{status:"ok",user:{username:n.username||n.nickname||void 0,nickname:n.nickname||void 0,avatar:s,membershipTier:n.membershipTier||n.membership_tier||void 0}}}catch{return{status:"offline"}}}var X=e=>`${e.seq}:${e.hash}`,ye=e=>he("sha256").update(e).digest("hex");function $(e){if(e===null)return{baseSeq:0,baseHash:null};if(typeof e!="string")return;let o=e.indexOf(":"),t=Number(o===-1?e:e.slice(0,o));if(!Number.isInteger(t)||t<=0)return;let r=o===-1?"":e.slice(o+1);return{baseSeq:t,baseHash:/^[0-9a-f]{64}$/.test(r)?r:null}}function V(e){let o=e.baseUrl.replace(/\/+$/,""),t=n=>`${o}/api/remotesync/vaults/${encodeURIComponent(e.vault)}${n}`,r=async(n,s)=>{let c=e.getToken();if(!c)throw new Error("penzor-not-logged-in");let a=await fetch(n,{...s,headers:{...s.headers,Authorization:`Bearer ${c}`}});if(a.status===409){let i=await a.json().catch(()=>({}));throw new Error(`cas-conflict ${String(i.code??"")}: seq=${String(i.seq??"?")}`)}if(!a.ok){let i=await a.text().catch(()=>"");throw new Error(`penzor ${s.method??"GET"} ${a.status}: ${i.slice(0,200)}`)}return a};return{kind:"penzor",async walk(n){let s=await r(t("/manifest"),{method:"GET",signal:n}),{files:c}=await s.json();return c.map(a=>({key:a.path,size:a.size,mtimeMs:a.mtimeMs,id:X(a)}))},async readFile(n,s){let a=await(await r(t(`/file?path=${encodeURIComponent(n)}`),{method:"GET",signal:s})).json(),i=await fetch(a.url,{signal:s});if(!i.ok)throw new Error(`penzor blob GET ${i.status}: ${n}`);let l=Buffer.from(await i.arrayBuffer());if(ye(l)!==a.hash)throw new Error(`penzor hash mismatch: ${n}`);return l},async writeFile(n,s,c,a,i){let l=$(i),m=new URLSearchParams({path:n,mtimeMs:String(Math.floor(c)||0)});l&&(m.set("baseSeq",String(l.baseSeq)),l.baseHash&&m.set("baseHash",l.baseHash));let d=await(await r(t(`/file?${m.toString()}`),{method:"PUT",body:new Uint8Array(s),headers:{"Content-Type":"application/octet-stream"},signal:a})).json();return{key:n,size:d.size,mtimeMs:d.mtimeMs,id:X(d)}},async rm(n,s,c){let a=$(c),i=new URLSearchParams({path:n});a&&a.baseSeq>0&&(i.set("baseSeq",String(a.baseSeq)),a.baseHash&&i.set("baseHash",a.baseHash)),await r(t(`/file?${i.toString()}`),{method:"DELETE",signal:s})},async check(){try{return await r(t("/manifest"),{method:"GET"}),{ok:!0}}catch(n){return{ok:!1,error:String(n?.message||n)}}}}}var Y=50*1024*1024,K=new Map;async function we(e,o){let t=K.get(o);if(t)return{id:t};let r=await v(e,o);if(r.status==="offline")return{error:"penzor-offline"};if(r.status!=="ok")return{error:"penzor-not-logged-in"};let n=r.user?.username?.trim();return n?(K.set(o,n),{id:n}):{error:"penzor-auth-unverified"}}var R=e=>typeof e.registerRemoteSyncBackend=="function"&&typeof e.readCreds=="function";function O(e){e.registerRemoteSyncBackend("penzor",async o=>{let t=e.readCreds();if(!t.token||!t.cloudUrl)return{error:"penzor-not-logged-in"};let r=o?.vault,n=(typeof r=="string"?r:"default").trim()||"default";if(!/^[A-Za-z0-9_-]{1,64}$/.test(n))return{error:"penzor-bad-vault"};let s=await we(t.cloudUrl,t.token);if("error"in s)return s;let c=t.token;return{remote:V({baseUrl:t.cloudUrl,vault:n,getToken:()=>c}),fingerprint:`penzor:${t.cloudUrl.replace(/\/+$/,"")}|u:${s.id}|${n}`,maxFileBytes:Y}}),e.log('[forsion-extend] remote-sync backend "penzor" registered')}import{readFileSync as ke,writeFileSync as be,mkdirSync as Ce,chmodSync as ve,renameSync as Se}from"node:fs";import{join as _e}from"node:path";function C(e,o){try{let t=new URL(e);if(t.protocol!=="https:"&&t.protocol!=="http:")return null;let r=o.split(".")[1];if(!r)return null;let n=r.replace(/-/g,"+").replace(/_/g,"/"),s=Uint8Array.from(atob(n),i=>i.charCodeAt(0)),c=JSON.parse(new TextDecoder().decode(s)),a=c.userId??c.sub;return typeof a!="string"&&typeof a!="number"||!String(a).trim()?null:`${t.origin}${t.pathname.replace(/\/+$/,"")}::${String(a)}`}catch{return null}}function U(e){try{let o=e.split(".")[1];if(!o)return null;let t=JSON.parse(Buffer.from(o,"base64url").toString("utf8"));return t&&typeof t=="object"?t:null}catch{return null}}function Q(e,o=Date.now()){let t=U(e)?.iat;return typeof t=="number"?o-t*1e3:1/0}function Te(e,o=Date.now()){let t=U(e)?.exp;return typeof t=="number"?t*1e3-o:1/0}var Ee=36e5;function ee(e,o=Date.now()){return!!e&&Q(e,o)>=Ee}async function te(e,o,t=8e3,r){if(!e||!o)return null;let n=e.replace(/\/+$/,"");try{let s=await fetch(`${n}/api/auth/refresh`,{method:"POST",headers:{Authorization:`Bearer ${o}`,...r?{"X-Forsion-Client":r}:{}},signal:AbortSignal.timeout(t)});if(!s.ok)return null;let c=await s.json().catch(()=>null),a=typeof c?.token=="string"?c.token:"";return a&&a!==o?a:null}catch{return null}}var T=(e,o)=>`${e.replace(/\/+$/,"")}\0${o}`,Ae=(e,o)=>new Promise((t,r)=>{let n=()=>{clearTimeout(s),r(new Error("Sign-in cancelled."))},s=setTimeout(()=>{o.removeEventListener("abort",n),t()},e);o.aborted?n():o.addEventListener("abort",n,{once:!0})});function ne(e){let o=()=>_e(e.homeDir(),"auth-accounts.json"),t=(u,d)=>{Ce(e.homeDir(),{recursive:!0});let p=`${u}.tmp`;be(p,JSON.stringify(d,null,2),{encoding:"utf8",mode:384}),ve(p,384),Se(p,u)},r=()=>{try{let u=JSON.parse(ke(o(),"utf8"));return Array.isArray(u.accounts)?u.accounts.filter(d=>d&&typeof d.token=="string"&&d.id===C(d.cloudUrl,d.token)):[]}catch{return[]}},n=(u,d)=>{let p=C(u.cloudUrl||"",u.token||"");if(!p||!u.token||!u.cloudUrl)return;let f=r(),g=f.find(k=>k.id===p),h=U(u.token),y={...g,id:p,cloudUrl:u.cloudUrl.replace(/\/+$/,""),token:u.token,username:d?.username||g?.username||h?.username,nickname:d?.nickname||g?.nickname};JSON.stringify(g)!==JSON.stringify(y)&&t(o(),{version:1,accounts:[...f.filter(k=>k.id!==p),y]})},s=()=>{let u=e.readCreds();n(u);let d=C(u.cloudUrl,u.token);return r().map(({token:p,...f})=>({...f,active:f.id===d}))},c=u=>{let d=r().find(p=>p.id===u);if(!d)throw new Error("Account is no longer signed in. Sign in again.");return{cloudUrl:d.cloudUrl,token:d.token}},a=u=>{let d=C(u.cloudUrl||"",u.token||"");d&&t(o(),{version:1,accounts:r().filter(p=>p.id!==d)})},i=null;return{rememberForsionAccount:n,forsionAccounts:s,savedForsionAccount:c,forgetForsionAccount:a,cancelForsionLogin:()=>{i?.abort(),i=null},forsionDeviceLogin:async(u,d,p)=>{if(i)throw new Error("A sign-in is already in progress.");if(!u)throw new Error("\u8BF7\u5148\u586B\u5199 Forsion \u4E91\u7AEF\u5730\u5740(\u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF TANGU_CLOUD_URL)");let f=new AbortController;i=f;let g=()=>{if(f.signal.aborted||i!==f)throw new Error("Sign-in cancelled.")};try{let h=u.replace(/\/+$/,""),y;try{y=await fetch(`${h}/api/auth/cli/start`,{method:"POST",headers:{"Content-Type":"application/json"},body:"{}",signal:AbortSignal.any([f.signal,AbortSignal.timeout(15e3)])}).then(b=>b.json())}catch(b){throw new Error(`\u65E0\u6CD5\u8FDE\u63A5 ${h}:${b?.message||b}`)}if(g(),!y?.device_code)throw new Error("\u4E91\u7AEF\u4E0D\u652F\u6301 CLI \u767B\u5F55(/api/auth/cli/start \u8FD4\u56DE\u5F02\u5E38)");let k=y.verification_uri_complete||`${y.verification_uri}?code=${y.user_code}`,S=new URL(`${h}/auth`);S.searchParams.set("logout","1"),S.searchParams.set("app","forsion-desktop"),S.searchParams.set("redirect",k);let M=S.toString();d?.({url:M,userCode:String(y.user_code||"")}),e.openExternal(M);let oe=Date.now()+(y.expires_in||600)*1e3,se=(y.interval||2)*1e3;for(;Date.now()<oe;){await Ae(se,f.signal),g();let b=null;try{b=await fetch(`${h}/api/auth/cli/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:y.device_code}),signal:AbortSignal.any([f.signal,AbortSignal.timeout(15e3)])})}catch{g();continue}if(g(),b.status===410)throw new Error("\u767B\u5F55\u7801\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u53D1\u8D77\u767B\u5F55");let _=await b.json().catch(()=>({status:"pending"}));if(g(),_.status==="approved"&&_.token){let ae={cloudUrl:h,token:_.token};return await p(ae,g),g(),{token:_.token,cloudUrl:h}}}throw new Error("\u767B\u5F55\u8D85\u65F6,\u8BF7\u91CD\u8BD5")}finally{i===f&&(i=null)}},readAccounts:r}}var re=["homeDir","appVersion","broadcast","accountBackendState","accountTransition","accountCommit","accountClear","writeCreds","onExternalCredsChange","setTokenRefresher","readCreds"],I=e=>re.every(o=>typeof e[o]=="function");function F(e){let o=ne(e),t=0,r=()=>{let s=e.readCreds();return T(s.cloudUrl,s.token)},n=null;e.handle("auth:status",async()=>{let s=t,c=r(),{base:a}=await e.getCloud(),i=e.readCreds().token,l=i?await v(a,i):null,m=await e.accountBackendState(),{base:u}=await e.getCloud(),d=e.readCreds(),p=T(u,d.token)!==T(a,i),f=T(a,i);!p&&l?.status==="ok"&&l.user&&(n={key:f,user:l.user},o.rememberForsionAccount({...d,cloudUrl:a},l.user));let g=p?void 0:l?.status==="ok"?l.user:l?.status==="offline"&&n?.key===f?n.user:void 0;if(p)return{loggedIn:!!d.token,tokenValid:null,cloudUrl:u,accountId:C(u,d.token),username:null,nickname:null,avatar:null,membershipTier:null,tokenSource:d.token?"tangu-login":null,backendState:m};if(l?.status==="expired"){await e.accountTransition(async()=>{if(s!==t||r()!==c)return;let y=()=>{if(s!==t||r()!==c)throw Z};try{await e.accountClear(y,()=>{e.log("[auth] token \u5DF2\u5931\u6548(\u670D\u52A1\u7AEF 401/403),\u81EA\u52A8\u767B\u51FA"),++t,o.cancelForsionLogin(),o.forgetForsionAccount(e.readCreds()),n=null})}catch(k){if(k!==Z)throw k}});let h=e.readCreds();return{loggedIn:!!h.token,tokenValid:null,cloudUrl:h.cloudUrl||a,accountId:C(h.cloudUrl||a,h.token),username:null,nickname:null,avatar:null,membershipTier:null,tokenSource:h.token?"tangu-login":null,backendState:m}}return{loggedIn:!!i,tokenValid:l&&l.status==="ok"?!0:null,cloudUrl:a,accountId:C(a,i),username:g?.username||null,nickname:g?.nickname||null,avatar:g?.avatar||null,membershipTier:g?.membershipTier||null,tokenSource:i?"tangu-login":null,backendState:m}}),e.handle("auth:accounts",()=>o.forsionAccounts()),e.handle("auth:switchAccount",async(s,c)=>{if(typeof c!="string")throw new Error("Invalid account.");let a=++t;return o.cancelForsionLogin(),e.accountTransition(async()=>{let i=o.savedForsionAccount(c);return await e.accountCommit(i,()=>{if(a!==t)throw new Error("Account switch cancelled.")},()=>{o.rememberForsionAccount(i),n=null}),{ok:!0,cloudUrl:i.cloudUrl||""}})}),e.handle("auth:forsionLogin",async(s,c)=>{let a=++t;o.cancelForsionLogin();let{base:i}=await e.getCloud();if(a!==t)throw new Error("Sign-in cancelled.");let l=(c||i||"").trim();return{ok:!0,cloudUrl:(await o.forsionDeviceLogin(l,u=>e.broadcast("auth:device",u),(u,d)=>e.accountTransition(()=>e.accountCommit(u,()=>{if(d(),a!==t)throw new Error("Sign-in cancelled.")},()=>{o.rememberForsionAccount(u),n=null})))).cloudUrl}}),e.handle("auth:logout",async()=>(++t,o.cancelForsionLogin(),e.accountTransition(async()=>{let{base:s}=await e.getCloud(),c=e.readCreds();return await e.accountClear(void 0,()=>{o.forgetForsionAccount(c),n=null,s&&c.token&&fetch(`${s}/api/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${c.token}`},signal:AbortSignal.timeout(5e3)}).catch(()=>{})}),{ok:!0}}))),e.onExternalCredsChange(({previous:s,current:c})=>{++t,o.cancelForsionLogin(),s.token&&!c.token&&o.forgetForsionAccount(s),n=null,o.rememberForsionAccount(c)}),e.setTokenRefresher(async s=>{let c=t,a=r(),i=e.readCreds().token;if(!ee(i))return;let{base:l}=await e.getCloud(),m=await te(l,i,s,`desktop/${e.appVersion()}`);if(!m){e.log("[auth] \u6ED1\u52A8\u7EED\u671F\u672A\u6210\u529F(\u79BB\u7EBF/\u8001\u7248\u672C server/\u8FD9\u679A\u5DF2\u5931\u6548),\u7EE7\u7EED\u7528\u65E7 token");return}c!==t||r()!==a||(o.rememberForsionAccount({cloudUrl:l,token:m}),e.writeCreds({cloudUrl:l,token:m}),e.log("[auth] \u767B\u5F55\u6001\u5DF2\u6ED1\u52A8\u7EED\u671F(\u6709\u6548\u671F\u91CD\u65B0\u8BA1\u6EE1 2 \u5468)"))}),e.log("[forsion-extend] account core registered")}var Z=Symbol("stale-auth-intent");function Ge(e){e.handle("auth:openAccountCenter",async(t,r)=>{let{base:n,token:s}=await e.getCloud();if(!n)return{ok:!1};let c=r&&/^[a-z0-9-]+$/i.test(r)?`#${r}`:"",a=`${n}/account${s?`?token=${encodeURIComponent(s)}`:""}${c}`;return await e.openExternal(a),{ok:!0}}),e.handle("auth:openPayCenter",async()=>{let{base:t,token:r}=await e.getCloud();if(!t)return{ok:!1};let n=`${t}/pay?tab=membership${r?`&token=${encodeURIComponent(r)}`:""}&redirect=${encodeURIComponent(`${t}/account`)}`;return await e.openExternal(n),{ok:!0}});let o=()=>e.getCloud();e.handle("account:quota",async()=>{let t=await o();if(!t.token)return{status:401,json:null};try{return await w(t,"GET","/api/token-quota/my",void 0,15e3)}catch(r){return{status:0,json:{detail:String(r?.message||r)}}}}),e.handle("account:useResetCard",async(t,r)=>{let n=await o();if(!n.token)return{status:401,json:null};if(r!==void 0&&r!=="both"&&r!=="weekly")return{status:400,json:{error:"invalid_type",detail:`invalid reset card type: ${r}`}};let s=r??"both";try{return await w(n,"POST","/api/token-quota/reset-card/use",{type:s},15e3)}catch(c){return{status:0,json:{detail:String(c?.message||c)}}}}),e.handle("account:bgConvert",async(t,r)=>{let n=await o();if(!n.token)return{status:401,json:null};if(!Number.isInteger(r)||r<1||r>100)return{status:400,json:{error:"invalid_percent"}};try{return await w(n,"POST","/api/token-quota/background/convert",{percent:r},15e3)}catch(s){return{status:0,json:{detail:String(s?.message||s)}}}}),e.handle("account:bgAutoMain",async(t,r)=>{let n=await o();if(!n.token)return{status:401,json:null};if(typeof r!="boolean")return{status:400,json:{error:"invalid_request"}};try{return await w(n,"POST","/api/token-quota/background/auto-main",{enabled:r},15e3)}catch(s){return{status:0,json:{detail:String(s?.message||s)}}}}),e.handle("feedback:submit",async(t,r)=>{let{base:n,token:s}=await e.getCloud();if(!n||!s)return{ok:!1,error:"not-logged-in"};let c=(r?.description||"").trim();if(!c)return{ok:!1,error:"empty"};if(c.length>1e4)return{ok:!1,error:"description-too-long"};let a=[],i=!1;if(r?.sessionLogJson){let l=Buffer.from(r.sessionLogJson,"utf8");if(l.length>5*1024*1024)return{ok:!1,error:"attachment-too-large"};a.push({filename:r.sessionLogName||"tangu-session.json",mime_type:"application/json",size:l.length,data_base64:l.toString("base64")})}try{let l=await fetch(`${n}/api/feedback`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({description:c,attachments:a}),signal:AbortSignal.timeout(2e4)});if(!l.ok){let u=`HTTP ${l.status}`;try{u=(await l.json())?.detail||u}catch{}return{ok:!1,error:u}}return{ok:!0,id:(await l.json().catch(()=>({})))?.id??null,attachmentSkipped:i}}catch(l){return{ok:!1,error:l?.message||String(l)}}}),e.handle("cloud:fetch",async(t,r)=>{if(!e.isTrustedSender(t))return{status:0,error:"untrusted"};let n=r??{},s=typeof n.path=="string"?n.path:"",c=Math.min(12e4,Math.max(1e3,Number(n.timeoutMs)||15e3)),a=typeof n.method=="string"?n.method.toUpperCase():"GET";if(!/^(GET|POST|PUT|PATCH|DELETE)$/.test(a))return{status:0,error:"bad_method"};if(!s.startsWith("/"))return{status:0,error:"bad_path"};let{base:i,token:l}=await e.getCloud();if(!String(i||""))return{status:0,error:"no_cloud_url"};let m=N(i,s);if(!m)return{status:0,error:"bad_path"};if(!l)return{status:401,error:"not_signed_in"};let u=n.body!==void 0&&a!=="GET"&&a!=="DELETE",d=new AbortController,p=setTimeout(()=>d.abort(),c);try{let f=await fetch(m,{method:a,headers:{Authorization:`Bearer ${l}`,...u?{"Content-Type":"application/json"}:{}},body:u?JSON.stringify(n.body):void 0,signal:d.signal});return{status:f.status,json:await f.json().catch(()=>null)}}catch(f){return{status:0,error:String(f?.message||f)}}finally{clearTimeout(p)}}),e.log("[forsion-extend] cloud account handlers registered"),j(e)?P(e):e.log("[forsion-extend] host has no Connect seam (projectsRoot / transpileForServe / mimeOf / setPreviewHooks); Connect stays with the host"),R(e)?O(e):e.log("[forsion-extend] host has no remote-sync seam (registerRemoteSyncBackend / readCreds); penzor stays with the host"),I(e)?F(e):e.log("[forsion-extend] host has no account seam (accountCommit / accountClear / \u2026); account core stays with the host")}export{re as ACCOUNT_SEAM,A as CONNECT_MAX_FILES,H as CONNECT_MAX_FILE_BYTES,z as CONNECT_MAX_TOTAL_BYTES,G as FORSION_CONNECT_LOCAL_SDK,Y as PENZOR_MAX_FILE,w as cloudJson,D as collectProjectFiles,ne as createAccountCloud,V as createPenzorRemote,$ as expectedPartsOf,C as forsionAccountId,te as forsionRefreshToken,v as forsionWhoami,I as hasAccountHost,j as hasConnectHost,R as hasRemoteSyncHost,W as makePreviewProxy,J as readConnectMeta,F as registerAccount,Ge as registerCloud,P as registerConnect,O as registerPenzor,ee as shouldRefreshToken,Q as tokenAgeMs,Te as tokenRemainingMs,q as writeConnectMeta};
193
+ `,es=t=>({transpile:(e,n,s)=>t.transpileForServe(e,n,s),mimeOf:e=>t.mimeOf(e)});function jt(t){let e=t;return typeof e.projectsRoot=="function"&&typeof e.transpileForServe=="function"&&typeof e.mimeOf=="function"&&typeof e.setPreviewHooks=="function"}function Ut(t){t.setPreviewHooks({sdkJs:Fn,proxy:Nn(()=>t.getCloud())}),t.handle("connect:meta",(e,n)=>typeof n=="string"&&n?$n(n):{}),t.handle("connect:list",async()=>{let e=await t.getCloud();if(!e.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{status:n,json:s}=await me(e,"GET","/api/connect/apps");return n===401||n===403?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:n!==200?{ok:!1,code:"error",detail:s?.detail||`HTTP ${n}`}:{ok:!0,base:e.base,...s}}catch(n){return{ok:!1,code:"error",detail:n?.message||String(n)}}}),t.handle("connect:publish",async(e,n)=>{if(!n||typeof n.dir!="string"||!n.dir||!n.name||!n.slug||!n.entry)return{ok:!1,code:"error",detail:"\u53C2\u6570\u4E0D\u5B8C\u6574"};let s;try{let o=Rn(t.projectsRoot());if(s=Rn(n.dir),s!==o&&!s.startsWith(o+Kr))return{ok:!1,code:"error",detail:"\u53EA\u80FD\u53D1\u5E03 Coding Space \u9879\u76EE\u76EE\u5F55"}}catch{return{ok:!1,code:"error",detail:"\u9879\u76EE\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u8BBF\u95EE"}}let r=await t.getCloud();if(!r.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{files:o,totalBytes:a}=Pn(s,es(t));if(!o.some(m=>m.path===n.entry))return{ok:!1,code:"error",detail:`\u5165\u53E3\u6587\u4EF6\u4E0D\u5B58\u5728:${n.entry}`};let{status:c,json:l}=await me(r,"POST","/api/connect/apps",{slug:n.slug,name:n.name,entry:n.entry,files:o},3e5);return c===401?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:c!==200?{ok:!1,code:l?.code||"error",detail:l?.detail||`HTTP ${c}`,used:l?.used,limit:l?.limit}:(Mn(s,{slug:String(l.slug)}),{ok:!0,slug:l.slug,handle:l.handle,url:`${r.base}${l.url}`,totalBytes:a})}catch(o){return{ok:!1,code:"error",detail:o?.message||String(o)}}}),t.handle("connect:unpublish",async(e,n)=>{if(!n||typeof n!="string")return{ok:!1,code:"error",detail:"\u53C2\u6570\u4E0D\u5B8C\u6574"};let s=await t.getCloud();if(!s.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{status:r,json:o}=await me(s,"DELETE",`/api/connect/apps/${encodeURIComponent(n)}`);return r===401||r===403?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:r!==200&&r!==404?{ok:!1,code:"error",detail:o?.detail||`HTTP ${r}`}:{ok:!0}}catch(r){return{ok:!1,code:"error",detail:r?.message||String(r)}}}),t.handle("connect:listingApply",async(e,n)=>{if(!n||typeof n.slug!="string"||!n.slug||typeof n.summary!="string"||!n.summary.trim())return{ok:!1,code:"error",detail:"\u53C2\u6570\u4E0D\u5B8C\u6574"};let s=await t.getCloud();if(!s.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{status:r,json:o}=await me(s,"PUT",`/api/connect/apps/${encodeURIComponent(n.slug)}/listing`,{summary:n.summary});return r===401?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:r!==200?{ok:!1,code:o?.code||"error",detail:o?.detail||`HTTP ${r}`}:{ok:!0,status:o.status}}catch(r){return{ok:!1,code:"error",detail:r?.message||String(r)}}}),t.handle("connect:listingWithdraw",async(e,n)=>{if(!n||typeof n!="string")return{ok:!1,code:"error",detail:"\u53C2\u6570\u4E0D\u5B8C\u6574"};let s=await t.getCloud();if(!s.token)return{ok:!1,code:"not_logged_in",detail:"\u8BF7\u5148\u767B\u5F55 Forsion \u8D26\u53F7"};try{let{status:r,json:o}=await me(s,"DELETE",`/api/connect/apps/${encodeURIComponent(n)}/listing`);return r===401?{ok:!1,code:"not_logged_in",detail:"\u767B\u5F55\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u767B\u5F55"}:r!==200&&r!==404?{ok:!1,code:"error",detail:o?.detail||`HTTP ${r}`}:{ok:!0}}catch(r){return{ok:!1,code:"error",detail:r?.message||String(r)}}}),t.handle("connect:store",async()=>{let e=await t.getCloud();try{let{status:n,json:s}=await me(e,"GET","/api/connect/store");return n!==200?{ok:!1,detail:s?.detail||`HTTP ${n}`}:{ok:!0,base:e.base,items:Array.isArray(s.items)?s.items:[]}}catch(n){return{ok:!1,detail:n?.message||String(n)}}}),t.log("[forsion-extend] connect handlers registered")}import{createHash as ts}from"node:crypto";async function nt(t,e){if(!t||!e)return{status:"offline"};let n=t.replace(/\/+$/,"");try{let s=await fetch(`${n}/api/brain/users/me`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(5e3)});if(s.status===401||s.status===403)return{status:(s.headers.get("content-type")||"").includes("application/json")?"expired":"offline"};if(!s.ok)return{status:"offline"};let r=await s.json();if(!r)return{status:"offline"};let o=r.avatar||r.avatarUrl||r.avatar_url||void 0;return o&&/^\/(?!\/)/.test(o)&&(o=n+o),{status:"ok",user:{username:r.username||r.nickname||void 0,nickname:r.nickname||void 0,avatar:o,membershipTier:r.membershipTier||r.membership_tier||void 0}}}catch{return{status:"offline"}}}var On=t=>`${t.seq}:${t.hash}`,ns=t=>ts("sha256").update(t).digest("hex");function Ht(t){if(t===null)return{baseSeq:0,baseHash:null};if(typeof t!="string")return;let e=t.indexOf(":"),n=Number(e===-1?t:t.slice(0,e));if(!Number.isInteger(n)||n<=0)return;let s=e===-1?"":t.slice(e+1);return{baseSeq:n,baseHash:/^[0-9a-f]{64}$/.test(s)?s:null}}function jn(t){let e=t.baseUrl.replace(/\/+$/,""),n=r=>`${e}/api/remotesync/vaults/${encodeURIComponent(t.vault)}${r}`,s=async(r,o)=>{let a=t.getToken();if(!a)throw new Error("penzor-not-logged-in");let c=await fetch(r,{...o,headers:{...o.headers,Authorization:`Bearer ${a}`}});if(c.status===409){let l=await c.json().catch(()=>({}));throw new Error(`cas-conflict ${String(l.code??"")}: seq=${String(l.seq??"?")}`)}if(!c.ok){let l=await c.text().catch(()=>"");throw new Error(`penzor ${o.method??"GET"} ${c.status}: ${l.slice(0,200)}`)}return c};return{kind:"penzor",async walk(r){let o=await s(n("/manifest"),{method:"GET",signal:r}),{files:a}=await o.json();return a.map(c=>({key:c.path,size:c.size,mtimeMs:c.mtimeMs,id:On(c)}))},async readFile(r,o){let c=await(await s(n(`/file?path=${encodeURIComponent(r)}`),{method:"GET",signal:o})).json(),l=await fetch(c.url,{signal:o});if(!l.ok)throw new Error(`penzor blob GET ${l.status}: ${r}`);let m=Buffer.from(await l.arrayBuffer());if(ns(m)!==c.hash)throw new Error(`penzor hash mismatch: ${r}`);return m},async writeFile(r,o,a,c,l){let m=Ht(l),h=new URLSearchParams({path:r,mtimeMs:String(Math.floor(a)||0)});m&&(h.set("baseSeq",String(m.baseSeq)),m.baseHash&&h.set("baseHash",m.baseHash));let u=await(await s(n(`/file?${h.toString()}`),{method:"PUT",body:new Uint8Array(o),headers:{"Content-Type":"application/octet-stream"},signal:c})).json();return{key:r,size:u.size,mtimeMs:u.mtimeMs,id:On(u)}},async rm(r,o,a){let c=Ht(a),l=new URLSearchParams({path:r});c&&c.baseSeq>0&&(l.set("baseSeq",String(c.baseSeq)),c.baseHash&&l.set("baseHash",c.baseHash)),await s(n(`/file?${l.toString()}`),{method:"DELETE",signal:o})},async check(){try{return await s(n("/manifest"),{method:"GET"}),{ok:!0}}catch(r){return{ok:!1,error:String(r?.message||r)}}}}}var Un=50*1024*1024,Ln=new Map;async function rs(t,e){let n=Ln.get(e);if(n)return{id:n};let s=await nt(t,e);if(s.status==="offline")return{error:"penzor-offline"};if(s.status!=="ok")return{error:"penzor-not-logged-in"};let r=s.user?.username?.trim();return r?(Ln.set(e,r),{id:r}):{error:"penzor-auth-unverified"}}var zt=t=>typeof t.registerRemoteSyncBackend=="function"&&typeof t.readCreds=="function";function qt(t){t.registerRemoteSyncBackend("penzor",async e=>{let n=t.readCreds();if(!n.token||!n.cloudUrl)return{error:"penzor-not-logged-in"};let s=e?.vault,r=(typeof s=="string"?s:"default").trim()||"default";if(!/^[A-Za-z0-9_-]{1,64}$/.test(r))return{error:"penzor-bad-vault"};let o=await rs(n.cloudUrl,n.token);if("error"in o)return o;let a=n.token;return{remote:jn({baseUrl:n.cloudUrl,vault:r,getToken:()=>a}),fingerprint:`penzor:${n.cloudUrl.replace(/\/+$/,"")}|u:${o.id}|${r}`,maxFileBytes:Un}}),t.log('[forsion-extend] remote-sync backend "penzor" registered')}import{readFileSync as ss,writeFileSync as os,mkdirSync as is,chmodSync as as,renameSync as ls}from"node:fs";import{join as cs}from"node:path";function Se(t,e){try{let n=new URL(t);if(n.protocol!=="https:"&&n.protocol!=="http:")return null;let s=e.split(".")[1];if(!s)return null;let r=s.replace(/-/g,"+").replace(/_/g,"/"),o=Uint8Array.from(atob(r),l=>l.charCodeAt(0)),a=JSON.parse(new TextDecoder().decode(o)),c=a.userId??a.sub;return typeof c!="string"&&typeof c!="number"||!String(c).trim()?null:`${n.origin}${n.pathname.replace(/\/+$/,"")}::${String(c)}`}catch{return null}}function Wt(t){try{let e=t.split(".")[1];if(!e)return null;let n=JSON.parse(Buffer.from(e,"base64url").toString("utf8"));return n&&typeof n=="object"?n:null}catch{return null}}function zn(t,e=Date.now()){let n=Wt(t)?.iat;return typeof n=="number"?e-n*1e3:1/0}function us(t,e=Date.now()){let n=Wt(t)?.exp;return typeof n=="number"?n*1e3-e:1/0}var ds=36e5;function qn(t,e=Date.now()){return!!t&&zn(t,e)>=ds}async function Wn(t,e,n=8e3,s){if(!t||!e)return null;let r=t.replace(/\/+$/,"");try{let o=await fetch(`${r}/api/auth/refresh`,{method:"POST",headers:{Authorization:`Bearer ${e}`,...s?{"X-Forsion-Client":s}:{}},signal:AbortSignal.timeout(n)});if(!o.ok)return null;let a=await o.json().catch(()=>null),c=typeof a?.token=="string"?a.token:"";return c&&c!==e?c:null}catch{return null}}var bt=(t,e)=>`${t.replace(/\/+$/,"")}\0${e}`,fs=(t,e)=>new Promise((n,s)=>{let r=()=>{clearTimeout(o),s(new Error("Sign-in cancelled."))},o=setTimeout(()=>{e.removeEventListener("abort",r),n()},t);e.aborted?r():e.addEventListener("abort",r,{once:!0})});function Bn(t){let e=()=>cs(t.homeDir(),"auth-accounts.json"),n=(f,u)=>{is(t.homeDir(),{recursive:!0});let y=`${f}.tmp`;os(y,JSON.stringify(u,null,2),{encoding:"utf8",mode:384}),as(y,384),ls(y,f)},s=()=>{try{let f=JSON.parse(ss(e(),"utf8"));return Array.isArray(f.accounts)?f.accounts.filter(u=>u&&typeof u.token=="string"&&u.id===Se(u.cloudUrl,u.token)):[]}catch{return[]}},r=(f,u)=>{let y=Se(f.cloudUrl||"",f.token||"");if(!y||!f.token||!f.cloudUrl)return;let _=s(),T=_.find(j=>j.id===y),E=Wt(f.token),L={...T,id:y,cloudUrl:f.cloudUrl.replace(/\/+$/,""),token:f.token,username:u?.username||T?.username||E?.username,nickname:u?.nickname||T?.nickname};JSON.stringify(T)!==JSON.stringify(L)&&n(e(),{version:1,accounts:[..._.filter(j=>j.id!==y),L]})},o=()=>{let f=t.readCreds();r(f);let u=Se(f.cloudUrl,f.token);return s().map(({token:y,..._})=>({..._,active:_.id===u}))},a=f=>{let u=s().find(y=>y.id===f);if(!u)throw new Error("Account is no longer signed in. Sign in again.");return{cloudUrl:u.cloudUrl,token:u.token}},c=f=>{let u=Se(f.cloudUrl||"",f.token||"");u&&n(e(),{version:1,accounts:s().filter(y=>y.id!==u)})},l=null;return{rememberForsionAccount:r,forsionAccounts:o,savedForsionAccount:a,forgetForsionAccount:c,cancelForsionLogin:()=>{l?.abort(),l=null},forsionDeviceLogin:async(f,u,y)=>{if(l)throw new Error("A sign-in is already in progress.");if(!f)throw new Error("\u8BF7\u5148\u586B\u5199 Forsion \u4E91\u7AEF\u5730\u5740(\u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF TANGU_CLOUD_URL)");let _=new AbortController;l=_;let T=()=>{if(_.signal.aborted||l!==_)throw new Error("Sign-in cancelled.")};try{let E=f.replace(/\/+$/,""),L;try{L=await fetch(`${E}/api/auth/cli/start`,{method:"POST",headers:{"Content-Type":"application/json"},body:"{}",signal:AbortSignal.any([_.signal,AbortSignal.timeout(15e3)])}).then(Y=>Y.json())}catch(Y){throw new Error(`\u65E0\u6CD5\u8FDE\u63A5 ${E}:${Y?.message||Y}`)}if(T(),!L?.device_code)throw new Error("\u4E91\u7AEF\u4E0D\u652F\u6301 CLI \u767B\u5F55(/api/auth/cli/start \u8FD4\u56DE\u5F02\u5E38)");let j=L.verification_uri_complete||`${L.verification_uri}?code=${L.user_code}`,te=new URL(`${E}/auth`);te.searchParams.set("logout","1"),te.searchParams.set("app","forsion-desktop"),te.searchParams.set("redirect",j);let G=te.toString();u?.({url:G,userCode:String(L.user_code||"")}),t.openExternal(G);let B=Date.now()+(L.expires_in||600)*1e3,X=(L.interval||2)*1e3;for(;Date.now()<B;){await fs(X,_.signal),T();let Y=null;try{Y=await fetch(`${E}/api/auth/cli/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:L.device_code}),signal:AbortSignal.any([_.signal,AbortSignal.timeout(15e3)])})}catch{T();continue}if(T(),Y.status===410)throw new Error("\u767B\u5F55\u7801\u5DF2\u8FC7\u671F,\u8BF7\u91CD\u65B0\u53D1\u8D77\u767B\u5F55");let ne=await Y.json().catch(()=>({status:"pending"}));if(T(),ne.status==="approved"&&ne.token){let ue={cloudUrl:E,token:ne.token};return await y(ue,T),T(),{token:ne.token,cloudUrl:E}}}throw new Error("\u767B\u5F55\u8D85\u65F6,\u8BF7\u91CD\u8BD5")}finally{l===_&&(l=null)}},readAccounts:s}}var Vn=["homeDir","appVersion","broadcast","accountBackendState","accountTransition","accountCommit","accountClear","writeCreds","onExternalCredsChange","setTokenRefresher","readCreds"],Bt=t=>Vn.every(e=>typeof t[e]=="function");function Vt(t){let e=Bn(t),n=0,s=()=>{let o=t.readCreds();return bt(o.cloudUrl,o.token)},r=null;t.handle("auth:status",async()=>{let o=n,a=s(),{base:c}=await t.getCloud(),l=t.readCreds().token,m=l?await nt(c,l):null,h=await t.accountBackendState(),{base:f}=await t.getCloud(),u=t.readCreds(),y=bt(f,u.token)!==bt(c,l),_=bt(c,l);!y&&m?.status==="ok"&&m.user&&(r={key:_,user:m.user},e.rememberForsionAccount({...u,cloudUrl:c},m.user));let T=y?void 0:m?.status==="ok"?m.user:m?.status==="offline"&&r?.key===_?r.user:void 0;if(y)return{loggedIn:!!u.token,tokenValid:null,cloudUrl:f,accountId:Se(f,u.token),username:null,nickname:null,avatar:null,membershipTier:null,tokenSource:u.token?"tangu-login":null,backendState:h};if(m?.status==="expired"){await t.accountTransition(async()=>{if(o!==n||s()!==a)return;let L=()=>{if(o!==n||s()!==a)throw Hn};try{await t.accountClear(L,()=>{t.log("[auth] token \u5DF2\u5931\u6548(\u670D\u52A1\u7AEF 401/403),\u81EA\u52A8\u767B\u51FA"),++n,e.cancelForsionLogin(),e.forgetForsionAccount(t.readCreds()),r=null})}catch(j){if(j!==Hn)throw j}});let E=t.readCreds();return{loggedIn:!!E.token,tokenValid:null,cloudUrl:E.cloudUrl||c,accountId:Se(E.cloudUrl||c,E.token),username:null,nickname:null,avatar:null,membershipTier:null,tokenSource:E.token?"tangu-login":null,backendState:h}}return{loggedIn:!!l,tokenValid:m&&m.status==="ok"?!0:null,cloudUrl:c,accountId:Se(c,l),username:T?.username||null,nickname:T?.nickname||null,avatar:T?.avatar||null,membershipTier:T?.membershipTier||null,tokenSource:l?"tangu-login":null,backendState:h}}),t.handle("auth:accounts",()=>e.forsionAccounts()),t.handle("auth:switchAccount",async(o,a)=>{if(typeof a!="string")throw new Error("Invalid account.");let c=++n;return e.cancelForsionLogin(),t.accountTransition(async()=>{let l=e.savedForsionAccount(a);return await t.accountCommit(l,()=>{if(c!==n)throw new Error("Account switch cancelled.")},()=>{e.rememberForsionAccount(l),r=null}),{ok:!0,cloudUrl:l.cloudUrl||""}})}),t.handle("auth:forsionLogin",async(o,a)=>{let c=++n;e.cancelForsionLogin();let{base:l}=await t.getCloud();if(c!==n)throw new Error("Sign-in cancelled.");let m=(a||l||"").trim();return{ok:!0,cloudUrl:(await e.forsionDeviceLogin(m,f=>t.broadcast("auth:device",f),(f,u)=>t.accountTransition(()=>t.accountCommit(f,()=>{if(u(),c!==n)throw new Error("Sign-in cancelled.")},()=>{e.rememberForsionAccount(f),r=null})))).cloudUrl}}),t.handle("auth:logout",async()=>(++n,e.cancelForsionLogin(),t.accountTransition(async()=>{let{base:o}=await t.getCloud(),a=t.readCreds();return await t.accountClear(void 0,()=>{e.forgetForsionAccount(a),r=null,o&&a.token&&fetch(`${o}/api/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${a.token}`},signal:AbortSignal.timeout(5e3)}).catch(()=>{})}),{ok:!0}}))),t.onExternalCredsChange(({previous:o,current:a})=>{++n,e.cancelForsionLogin(),o.token&&!a.token&&e.forgetForsionAccount(o),r=null,e.rememberForsionAccount(a)}),t.setTokenRefresher(async o=>{let a=n,c=s(),l=t.readCreds().token;if(!qn(l))return;let{base:m}=await t.getCloud(),h=await Wn(m,l,o,`desktop/${t.appVersion()}`);if(!h){t.log("[auth] \u6ED1\u52A8\u7EED\u671F\u672A\u6210\u529F(\u79BB\u7EBF/\u8001\u7248\u672C server/\u8FD9\u679A\u5DF2\u5931\u6548),\u7EE7\u7EED\u7528\u65E7 token");return}a!==n||s()!==c||(e.rememberForsionAccount({cloudUrl:m,token:h}),t.writeCreds({cloudUrl:m,token:h}),t.log("[auth] \u767B\u5F55\u6001\u5DF2\u6ED1\u52A8\u7EED\u671F(\u6709\u6548\u671F\u91CD\u65B0\u8BA1\u6EE1 2 \u5468)"))}),t.log("[forsion-extend] account core registered")}var Hn=Symbol("stale-auth-intent");import{promises as Xe}from"node:fs";import je from"node:path";import{createHash as hs}from"node:crypto";var Gt=null;function Gn(t){Gt=t}function de(){if(!Gt)throw new Error("amadeus sync env not set (registerAmadeus factory has not run)");return Gt}var fe=()=>de().accountId();function rt(t=fe()){return t?hs("sha256").update(t).digest("hex"):"signed-out"}var Ee=(t=fe())=>de().readConfig(t),Ae=(t,e=fe())=>de().writeConfig(t,e),qe=(t,e=fe())=>de().updateConfig(t,e),De=(t=fe())=>de().cloudVaultDir(t),St=t=>de().isManagedCloudVault(t);import{createHash as wo}from"node:crypto";import{promises as ee,existsSync as Cr}from"node:fs";import se from"node:path";import{EventEmitter as zs}from"node:events";import{stat as qs}from"node:fs";import{readdir as Ws,stat as Bs}from"node:fs/promises";import*as z from"node:path";import{lstat as Yn,readdir as ms,realpath as ps,stat as gs}from"node:fs/promises";import{join as ys,resolve as ws,sep as Jn}from"node:path";import{Readable as bs}from"node:stream";var pe={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},We={root:".",fileFilter:t=>!0,directoryFilter:t=>!0,type:pe.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:256};Object.freeze(We);var Zn="READDIRP_RECURSIVE_ERROR",Ss=new Set(["ENOENT","EPERM","EACCES","ELOOP",Zn]),Kn=[pe.DIR_TYPE,pe.EVERYTHING_TYPE,pe.FILE_DIR_TYPE,pe.FILE_TYPE],Es=new Set([pe.DIR_TYPE,pe.EVERYTHING_TYPE,pe.FILE_DIR_TYPE]),vs=new Set([pe.EVERYTHING_TYPE,pe.FILE_DIR_TYPE,pe.FILE_TYPE]),_s=t=>Ss.has(t.code),ks=process.platform==="win32",Xn=t=>!0,Qn=t=>{if(t===void 0)return Xn;if(typeof t=="function")return t;if(typeof t=="string"){let e=t.trim();return n=>n.basename===e}if(Array.isArray(t)){let e=t.map(n=>n.trim());return n=>e.some(s=>n.basename===s)}return Xn},Yt=class extends bs{parents;reading;parent;_stat;_maxDepth;_wantsDir;_wantsFile;_wantsEverything;_root;_isDirent;_statsProp;_rdOptions;_fileFilter;_directoryFilter;_relStart;constructor(e={}){super({objectMode:!0,autoDestroy:!0,highWaterMark:e.highWaterMark??We.highWaterMark});let n={...We,...e},s=n.root??We.root,r=n.type??We.type;this._fileFilter=Qn(n.fileFilter),this._directoryFilter=Qn(n.directoryFilter);let o=n.lstat?Yn:gs;ks?this._stat=c=>o(c,{bigint:!0}):this._stat=o,this._maxDepth=n.depth!=null&&Number.isSafeInteger(n.depth)?n.depth:We.depth,this._wantsDir=Es.has(r),this._wantsFile=vs.has(r),this._wantsEverything=r===pe.EVERYTHING_TYPE,this._root=ws(s),this._relStart=this._root.endsWith(Jn)?this._root.length:this._root.length+1,this._isDirent=!n.alwaysStat,this._statsProp=this._isDirent?"dirent":"stats",this._rdOptions={encoding:"utf8",withFileTypes:this._isDirent};let a={path:this._root,depth:1};a.pending=this._exploreDir(this._root,1),this.parents=[a],this.reading=!1,this.parent=void 0}async _read(e){if(!this.reading){this.reading=!0;try{for(;!this.destroyed&&e>0;){let n=this.parent,s=n&&n.files;if(s&&s.length>0){let{path:r,depth:o}=n,a=s.splice(0,e).map(l=>this._formatEntry(l,r)),c=this._isDirent?a:await Promise.all(a);for(let l of c){if(!l)continue;if(this.destroyed)return;let m=this._getEntryType(l);typeof m!="string"&&(m=await m),m==="directory"&&this._directoryFilter(l)?(o<=this._maxDepth&&this.parents.push({path:l.fullPath,depth:o+1}),this._wantsDir&&(this.push(l),e--)):(m==="file"||this._includeAsFile(l))&&this._fileFilter(l)&&this._wantsFile&&(this.push(l),e--)}}else{let r=this.parents.pop();if(!r){this.push(null);break}let o=r.pending??this._exploreDir(r.path,r.depth),a=this.parents[this.parents.length-1];if(a&&!a.pending&&(a.pending=this._exploreDir(a.path,a.depth)),this.parent=await o,this.destroyed)return}}}catch(n){this.destroy(n)}finally{this.reading=!1}}}async _exploreDir(e,n){let s;try{s=await ms(e,this._rdOptions)}catch(r){this._onError(r)}return{files:s,depth:n,path:e}}_formatEntry(e,n){let s=this._isDirent?e.name:e,r=ys(n,s),o={path:r.slice(this._relStart),fullPath:r,basename:s};return this._isDirent?(o.dirent=e,o):this._stat(r).then(a=>(o.stats=a,o),a=>{this._onError(a)})}_onError(e){_s(e)&&!this.destroyed?this.emit("warn",e):this.destroy(e)}_getEntryType(e){if(!e||!(this._statsProp in e))return"";let n=e[this._statsProp];return n.isFile()?"file":n.isDirectory()?"directory":n.isSymbolicLink()?this._getSymlinkEntryType(e):""}async _getSymlinkEntryType(e){let n=e.fullPath;try{let s=await ps(n),r=await Yn(s);if(r.isFile())return"file";if(r.isDirectory()){let o=s.length;if(n.startsWith(s)&&n[o]===Jn){let a=new Error(`Circular symlink detected: "${n}" points to "${s}"`);return a.code=Zn,this._onError(a),""}return"directory"}}catch(s){this._onError(s)}return""}_includeAsFile(e){let n=e&&e[this._statsProp];return n&&this._wantsEverything&&!n.isDirectory()}};function er(t,e={}){let n=e.entryType||e.type;if(n==="both"&&(n=pe.FILE_DIR_TYPE),t){if(typeof t!="string")throw new TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");if(n&&!Kn.includes(n))throw new Error(`readdirp: Invalid type passed. Use one of ${Kn.join(", ")}`)}else throw new Error("readdirp: root argument is required. Usage: readdirp(root, options)");let s={...e,root:t};return n&&(s.type=n),new Yt(s)}import{watch as Cs,unwatchFile as tr,watchFile as xs}from"node:fs";import{realpath as Jt,lstat as Ts,open as Rs,stat as rr}from"node:fs/promises";import{type as Is}from"node:os";import*as K from"node:path";var As="data",Qt="end",sr="close",Ct=()=>{};var xt=process.platform,Zt=xt==="win32",Ps=xt==="darwin",Ds=xt==="linux",$s=xt==="freebsd",or=Is()==="OS400",Z={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},ve=Z,Ms="watch",Ns={lstat:Ts,stat:rr},Le="listeners",Et="errHandlers",Be="rawEmitters",Fs=[Le,Et,Be],Os=new Set(["3dm","3ds","3g2","3gp","7z","a","aac","adp","afdesign","afphoto","afpub","ai","aif","aiff","alz","ape","apk","appimage","ar","arj","asf","au","avi","bak","baml","bh","bin","bk","bmp","btif","bz2","bzip2","cab","caf","cgm","class","cmx","cpio","cr2","cur","dat","dcm","deb","dex","djvu","dll","dmg","dng","doc","docm","docx","dot","dotm","dra","DS_Store","dsk","dts","dtshd","dvb","dwg","dxf","ecelp4800","ecelp7470","ecelp9600","egg","eol","eot","epub","exe","f4v","fbs","fh","fla","flac","flatpak","fli","flv","fpx","fst","fvt","g3","gh","gif","graffle","gz","gzip","h261","h263","h264","icns","ico","ief","img","ipa","iso","jar","jpeg","jpg","jpgv","jpm","jxr","key","ktx","lha","lib","lvp","lz","lzh","lzma","lzo","m3u","m4a","m4v","mar","mdi","mht","mid","midi","mj2","mka","mkv","mmr","mng","mobi","mov","movie","mp3","mp4","mp4a","mpeg","mpg","mpga","mxu","nef","npx","numbers","nupkg","o","odp","ods","odt","oga","ogg","ogv","otf","ott","pages","pbm","pcx","pdb","pdf","pea","pgm","pic","png","pnm","pot","potm","potx","ppa","ppam","ppm","pps","ppsm","ppsx","ppt","pptm","pptx","psd","pya","pyc","pyo","pyv","qt","rar","ras","raw","resources","rgb","rip","rlc","rmf","rmvb","rpm","rtf","rz","s3m","s7z","scpt","sgi","shar","snap","sil","sketch","slk","smv","snk","so","stl","suo","sub","swf","tar","tbz","tbz2","tga","tgz","thmx","tif","tiff","tlz","ttc","ttf","txz","udf","uvh","uvi","uvm","uvp","uvs","uvu","viv","vob","war","wav","wax","wbmp","wdp","weba","webm","webp","whl","wim","wm","wma","wmv","wmx","woff","woff2","wrm","wvx","xbm","xif","xla","xlam","xls","xlsb","xlsm","xlsx","xlt","xltm","xltx","xm","xmind","xpi","xpm","xwd","xz","z","zip","zipx"]),Ls=t=>Os.has(K.extname(t).slice(1).toLowerCase()),Xt=(t,e)=>{t instanceof Set?t.forEach(e):e(t)},st=(t,e,n)=>{let s=t[e];s instanceof Set||(t[e]=s=new Set([s])),s.add(n)},js=t=>e=>{let n=t[e];n instanceof Set?n.clear():delete t[e]},ot=(t,e,n)=>{let s=t[e];s instanceof Set?s.delete(n):s===n&&delete t[e]},ir=t=>t instanceof Set?t.size===0:!t,vt=new Map;function nr(t,e,n,s,r){let o=(a,c)=>{n(t),r(a,c,{watchedPath:t}),c&&t!==c&&_t(K.resolve(t,c),Le,K.join(t,c))};try{return Cs(t,{persistent:e.persistent},o)}catch(a){s(a);return}}var _t=(t,e,n,s,r)=>{let o=vt.get(t);o&&Xt(o[e],a=>{a(n,s,r)})},Us=(t,e,n,s)=>{let{listener:r,errHandler:o,rawEmitter:a}=s,c=vt.get(e),l;if(!n.persistent)return l=nr(t,n,r,o,a),l?l.close.bind(l):void 0;if(c)st(c,Le,r),st(c,Et,o),st(c,Be,a);else{if(l=nr(t,n,_t.bind(null,e,Le),o,_t.bind(null,e,Be)),!l)return;l.on(ve.ERROR,async m=>{let h=_t.bind(null,e,Et);if(c&&(c.watcherUnusable=!0),Zt&&m.code==="EPERM")try{await(await Rs(t,"r")).close(),h(m)}catch{}else h(m)}),c={listeners:r,errHandlers:o,rawEmitters:a,watcher:l},vt.set(e,c)}return()=>{ot(c,Le,r),ot(c,Et,o),ot(c,Be,a),ir(c.listeners)&&(c.watcher.close(),vt.delete(e),Fs.forEach(js(c)),c.watcher=void 0,Object.freeze(c))}},Kt=new Map,Hs=(t,e,n,s)=>{let{listener:r,rawEmitter:o}=s,a=Kt.get(e),c=a&&a.options;return c&&(c.persistent<n.persistent||c.interval>n.interval)&&(tr(e),a=void 0),a?(st(a,Le,r),st(a,Be,o)):(a={listeners:r,rawEmitters:o,options:n,watcher:xs(e,n,(l,m)=>{Xt(a.rawEmitters,f=>{f(ve.CHANGE,e,{curr:l,prev:m})});let h=l.mtimeMs;(l.size!==m.size||h>m.mtimeMs||h===0)&&Xt(a.listeners,f=>f(t,l))})},Kt.set(e,a)),()=>{ot(a,Le,r),ot(a,Be,o),ir(a.listeners)&&(Kt.delete(e),tr(e),a.options=a.watcher=void 0,Object.freeze(a))}},kt=class{fsw;_boundHandleError;constructor(e){this.fsw=e,this._boundHandleError=n=>e._handleError(n)}_watchWithNodeFs(e,n){let s=this.fsw.options,r=K.dirname(e),o=K.basename(e);this.fsw._getWatchedDir(r).add(o);let c=K.resolve(e),l={persistent:s.persistent};n||(n=Ct);let m;if(s.usePolling){let h=s.interval!==s.binaryInterval;l.interval=h&&Ls(o)?s.binaryInterval:s.interval,m=Hs(e,c,l,{listener:n,rawEmitter:this.fsw._emitRaw})}else m=Us(e,c,l,{listener:n,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return m}_handleFile(e,n,s){if(this.fsw.closed)return;let r=K.dirname(e),o=K.basename(e),a=this.fsw._getWatchedDir(r),c=n;if(a.has(o))return;let l=async(h,f)=>{if(this.fsw._throttle(Ms,e,5)){if(!f||f.mtimeMs===0)try{let u=await rr(e);if(this.fsw.closed)return;let y=u.atimeMs,_=u.mtimeMs;if((!y||y<=_||_!==c.mtimeMs)&&this.fsw._emit(ve.CHANGE,e,u),(Ps||Ds||$s)&&c.ino!==u.ino){this.fsw._closeFile(h),c=u;let T=this._watchWithNodeFs(e,l);T&&this.fsw._addPathCloser(h,T)}else c=u}catch{this.fsw._remove(r,o)}else if(a.has(o)){let u=f.atimeMs,y=f.mtimeMs;(!u||u<=y||y!==c.mtimeMs)&&this.fsw._emit(ve.CHANGE,e,f),c=f}}},m=this._watchWithNodeFs(e,l);if(!(s&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(e)){if(!this.fsw._throttle(ve.ADD,e,0))return;this.fsw._emit(ve.ADD,e,n)}return m}async _handleSymlink(e,n,s,r){if(this.fsw.closed)return;let o=e.fullPath,a=this.fsw._getWatchedDir(n);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let c;try{c=await Jt(s)}catch{return this.fsw._emitReady(),!0}return this.fsw.closed?void 0:(a.has(r)?this.fsw._symlinkPaths.get(o)!==c&&(this.fsw._symlinkPaths.set(o,c),this.fsw._emit(ve.CHANGE,s,e.stats)):(a.add(r),this.fsw._symlinkPaths.set(o,c),this.fsw._emit(ve.ADD,s,e.stats)),this.fsw._emitReady(),!0)}if(this.fsw._symlinkPaths.has(o))return!0;this.fsw._symlinkPaths.set(o,!0)}_handleRead(e,n,s,r,o,a,c){e=K.join(e,"");let l=r?`${e}:${r}`:e;if(c=this.fsw._throttle("readdir",l,1e3),!c)return;let m=this.fsw._getWatchedDir(s.path),h=new Set,f=this.fsw._readdirp(e,{fileFilter:u=>s.filterPath(u),directoryFilter:u=>s.filterDir(u)});if(f)return f.on(As,async u=>{if(this.fsw.closed){f=void 0;return}let y=u.path,_=K.join(e,y);if(h.add(y),!(u.stats.isSymbolicLink()&&await this._handleSymlink(u,e,_,y))){if(this.fsw.closed){f=void 0;return}(y===r||!r&&!m.has(y))&&(this.fsw._incrReadyCount(),_=K.join(o,K.relative(o,_)),this._addToNodeFs(_,n,s,a+1))}}).on(ve.ERROR,this._boundHandleError),new Promise((u,y)=>{if(!f)return y();f.once(Qt,()=>{if(this.fsw.closed){f=void 0;return}let _=c?c.clear():!1;u(void 0),m.getChildren().filter(T=>T!==e&&!h.has(T)).forEach(T=>{this.fsw._remove(e,T)}),f=void 0,_&&this._handleRead(e,!1,s,r,o,a,c)})})}async _handleDir(e,n,s,r,o,a,c){let l=this.fsw._getWatchedDir(K.dirname(e)),m=l.has(K.basename(e));!(s&&this.fsw.options.ignoreInitial)&&!o&&!m&&this.fsw._emit(ve.ADD_DIR,e,n),l.add(K.basename(e)),this.fsw._getWatchedDir(e);let h,f,u=this.fsw.options.depth;if((u==null||r<=u)&&!this.fsw._symlinkPaths.has(c)){if(!o&&(await this._handleRead(e,s,a,o,e,r,h),this.fsw.closed))return;f=this._watchWithNodeFs(e,(y,_)=>{_&&_.mtimeMs===0||this._handleRead(y,!1,a,o,e,r,h)})}return f}async _addToNodeFs(e,n,s,r,o){let a=this.fsw._emitReady;if(this.fsw._isIgnored(e)||this.fsw.closed)return a(),!1;let c=this.fsw._getWatchHelpers(e);s&&(c.filterPath=l=>s.filterPath(l),c.filterDir=l=>s.filterDir(l));try{let l=await Ns[c.statMethod](c.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(c.watchPath,l))return a(),!1;let m=this.fsw.options.followSymlinks,h;if(l.isDirectory()){let f=K.resolve(e),u=m?await Jt(e):e;if(this.fsw.closed||(h=await this._handleDir(c.watchPath,l,n,r,o,c,u),this.fsw.closed))return;f!==u&&u!==void 0&&this.fsw._symlinkPaths.set(f,u)}else if(l.isSymbolicLink()){let f=m?await Jt(e):e;if(this.fsw.closed)return;let u=K.dirname(c.watchPath);if(this.fsw._getWatchedDir(u).add(c.watchPath),this.fsw._emit(ve.ADD,c.watchPath,l),h=await this._handleDir(u,l,n,r,e,c,f),this.fsw.closed)return;f!==void 0&&this.fsw._symlinkPaths.set(K.resolve(e),f)}else h=this._handleFile(c.watchPath,l,n);return a(),h&&this.fsw._addPathCloser(e,h),!1}catch(l){if(this.fsw._handleError(l))return a(),e}}};var en="/",Vs="//",dr=".",Gs="..",Ys="string",Js=/\\/g,fr=/\/\//g,Ks=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,Xs=/^\.[/\\]/;function Tt(t){return Array.isArray(t)?t:[t]}var tn=t=>typeof t=="object"&&t!==null&&!(t instanceof RegExp);function Qs(t){return typeof t=="function"?t:typeof t=="string"?e=>t===e:t instanceof RegExp?e=>t.test(e):typeof t=="object"&&t!==null?e=>{if(t.path===e)return!0;if(t.recursive){let n=z.relative(t.path,e);return n?!n.startsWith("..")&&!z.isAbsolute(n):!1}return!1}:()=>!1}function Zs(t){if(typeof t!="string")throw new Error("string expected");t=z.normalize(t),t=t.replace(/\\/g,"/");let e=!1;return t.startsWith("//")&&(e=!0),t=t.replace(fr,"/"),e&&(t="/"+t),t}function ar(t,e,n){let s=Zs(e);for(let r=0;r<t.length;r++){let o=t[r];if(o(s,n))return!0}return!1}function eo(t,e){if(t==null)throw new TypeError("anymatch: specify first argument");let s=Tt(t).map(r=>Qs(r));return e==null?(r,o)=>ar(s,r,o):ar(s,e)}var lr=t=>{let e=Tt(t).flat();if(!e.every(n=>typeof n===Ys))throw new TypeError(`Non-string provided as watch path: ${e}`);return e.map(hr)},cr=t=>{let e=t.replace(Js,en),n=!1;return e.startsWith(Vs)&&(n=!0),e=e.replace(fr,en),n&&(e=en+e),e},hr=t=>cr(z.normalize(cr(t))),ur=(t="")=>e=>typeof e=="string"?hr(z.isAbsolute(e)?e:z.join(t,e)):e,to=(t,e)=>z.isAbsolute(t)?t:z.join(e,t),no=Object.freeze(new Set),nn=class{path;_removeWatcher;items;constructor(e,n){this.path=e,this._removeWatcher=n,this.items=new Set}add(e){let{items:n}=this;n&&e!==dr&&e!==Gs&&n.add(e)}async remove(e){let{items:n}=this;if(!n||(n.delete(e),n.size>0))return;let s=this.path;try{await Ws(s)}catch{this._removeWatcher&&this._removeWatcher(z.dirname(s),z.basename(s))}}has(e){let{items:n}=this;if(n)return n.has(e)}getChildren(){let{items:e}=this;return e?[...e.values()]:[]}dispose(){this.items.clear(),this.path="",this._removeWatcher=Ct,this.items=no,Object.freeze(this)}},ro="stat",so="lstat",rn=class{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(e,n,s){this.fsw=s;let r=e;this.path=e=e.replace(Xs,""),this.watchPath=r,this.fullWatchPath=z.resolve(r),this.dirParts=[],this.dirParts.forEach(o=>{o.length>1&&o.pop()}),this.followSymlinks=n,this.statMethod=n?ro:so}entryPath(e){return z.join(this.watchPath,z.relative(this.watchPath,e.fullPath))}filterPath(e){let{stats:n}=e;if(n&&n.isSymbolicLink())return this.filterDir(e);let s=this.entryPath(e);return this.fsw._isntIgnored(s,n)&&this.fsw._hasReadPermissions(n)}filterDir(e){return this.fsw._isntIgnored(this.entryPath(e),e.stats)}},Rt=class extends zs{closed;options;_closers;_ignoredPaths;_throttled;_streams;_symlinkPaths;_watched;_pendingWrites;_pendingUnlinks;_readyCount;_emitReady;_closePromise;_userIgnored;_readyEmitted;_emitRaw;_boundRemove;_nodeFsHandler;constructor(e={}){super(),this.closed=!1,this._closers=new Map,this._ignoredPaths=new Set,this._throttled=new Map,this._streams=new Set,this._symlinkPaths=new Map,this._watched=new Map,this._pendingWrites=new Map,this._pendingUnlinks=new Map,this._readyCount=0,this._readyEmitted=!1;let n=e.awaitWriteFinish,s={stabilityThreshold:2e3,pollInterval:100},r={persistent:!0,ignoreInitial:!1,ignorePermissionErrors:!1,interval:100,binaryInterval:300,followSymlinks:!0,usePolling:!1,atomic:!0,...e,ignored:e.ignored?Tt(e.ignored):Tt([]),awaitWriteFinish:n===!0?s:typeof n=="object"?{...s,...n}:!1};or&&(r.usePolling=!0),r.atomic===void 0&&(r.atomic=!r.usePolling);let o=process.env.CHOKIDAR_USEPOLLING;if(o!==void 0){let l=o.toLowerCase();l==="false"||l==="0"?r.usePolling=!1:l==="true"||l==="1"?r.usePolling=!0:r.usePolling=!!l}let a=process.env.CHOKIDAR_INTERVAL;a&&(r.interval=Number.parseInt(a,10));let c=0;this._emitReady=()=>{c++,c>=this._readyCount&&(this._emitReady=Ct,this._readyEmitted=!0,process.nextTick(()=>this.emit(Z.READY)))},this._emitRaw=(...l)=>this.emit(Z.RAW,...l),this._boundRemove=this._remove.bind(this),this.options=r,this._nodeFsHandler=new kt(this),Object.freeze(r)}_addIgnoredPath(e){if(tn(e)){for(let n of this._ignoredPaths)if(tn(n)&&n.path===e.path&&n.recursive===e.recursive)return}this._ignoredPaths.add(e)}_removeIgnoredPath(e){if(this._ignoredPaths.delete(e),typeof e=="string")for(let n of this._ignoredPaths)tn(n)&&n.path===e&&this._ignoredPaths.delete(n)}add(e,n,s){let{cwd:r}=this.options;this.closed=!1,this._closePromise=void 0;let o=lr(e);return r&&(o=o.map(a=>to(a,r))),o.forEach(a=>{this._removeIgnoredPath(a)}),this._userIgnored=void 0,this._readyCount||(this._readyCount=0),this._readyCount+=o.length,Promise.all(o.map(async a=>{let c=await this._nodeFsHandler._addToNodeFs(a,!s,void 0,0,n);return c&&this._emitReady(),c})).then(a=>{this.closed||a.forEach(c=>{c&&this.add(z.dirname(c),z.basename(n||c))})}),this}unwatch(e){if(this.closed)return this;let n=lr(e),{cwd:s}=this.options;return n.forEach(r=>{!z.isAbsolute(r)&&!this._closers.has(r)&&(s&&(r=z.join(s,r)),r=z.resolve(r)),this._closePath(r),this._addIgnoredPath(r),this._watched.has(r)&&this._addIgnoredPath({path:r,recursive:!0}),this._userIgnored=void 0}),this}close(){if(this._closePromise)return this._closePromise;this.closed=!0,this.removeAllListeners();let e=[];return this._closers.forEach(n=>n.forEach(s=>{let r=s();r instanceof Promise&&e.push(r)})),this._streams.forEach(n=>n.destroy()),this._userIgnored=void 0,this._readyCount=0,this._readyEmitted=!1,this._watched.forEach(n=>n.dispose()),this._closers.clear(),this._watched.clear(),this._streams.clear(),this._symlinkPaths.clear(),this._throttled.clear(),this._closePromise=e.length?Promise.all(e).then(()=>{}):Promise.resolve(),this._closePromise}getWatched(){let e={};return this._watched.forEach((n,s)=>{let o=(this.options.cwd?z.relative(this.options.cwd,s):s)||dr;e[o]=n.getChildren().sort()}),e}emitWithAll(e,n){this.emit(e,...n),e!==Z.ERROR&&this.emit(Z.ALL,e,...n)}async _emit(e,n,s){if(this.closed)return;let r=this.options;Zt&&(n=z.normalize(n)),r.cwd&&(n=z.relative(r.cwd,n));let o=[n];s!=null&&o.push(s);let a=r.awaitWriteFinish,c;if(a&&(c=this._pendingWrites.get(n)))return c.lastChange=new Date,this;if(r.atomic){if(e===Z.UNLINK)return this._pendingUnlinks.set(n,[e,...o]),setTimeout(()=>{this._pendingUnlinks.forEach((l,m)=>{this.emit(...l),this.emit(Z.ALL,...l),this._pendingUnlinks.delete(m)})},typeof r.atomic=="number"?r.atomic:100),this;e===Z.ADD&&this._pendingUnlinks.has(n)&&(e=Z.CHANGE,this._pendingUnlinks.delete(n))}if(a&&(e===Z.ADD||e===Z.CHANGE)&&this._readyEmitted){let l=(m,h)=>{m?(e=Z.ERROR,o[0]=m,this.emitWithAll(e,o)):h&&(o.length>1?o[1]=h:o.push(h),this.emitWithAll(e,o))};return this._awaitWriteFinish(n,a.stabilityThreshold,e,l),this}if(e===Z.CHANGE&&!this._throttle(Z.CHANGE,n,50))return this;if(r.alwaysStat&&s===void 0&&(e===Z.ADD||e===Z.ADD_DIR||e===Z.CHANGE)){let l=r.cwd?z.join(r.cwd,n):n,m;try{m=await Bs(l)}catch{}if(!m||this.closed)return;o.push(m)}return this.emitWithAll(e,o),this}_handleError(e){let n=e&&e.code;return e&&n!=="ENOENT"&&n!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||n!=="EPERM"&&n!=="EACCES")&&this.emit(Z.ERROR,e),e||this.closed}_throttle(e,n,s){this._throttled.has(e)||this._throttled.set(e,new Map);let r=this._throttled.get(e);if(!r)throw new Error("invalid throttle");let o=r.get(n);if(o)return o.count++,!1;let a,c=()=>{let m=r.get(n),h=m?m.count:0;return r.delete(n),clearTimeout(a),m&&clearTimeout(m.timeoutObject),h};a=setTimeout(c,s);let l={timeoutObject:a,clear:c,count:0};return r.set(n,l),l}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(e,n,s,r){let o=this.options.awaitWriteFinish;if(typeof o!="object")return;let a=o.pollInterval,c,l=e;this.options.cwd&&!z.isAbsolute(e)&&(l=z.join(this.options.cwd,e));let m=new Date,h=this._pendingWrites;function f(u){qs(l,(y,_)=>{if(y||!h.has(e)){y&&y.code!=="ENOENT"&&r(y);return}let T=Number(new Date);u&&_.size!==u.size&&(h.get(e).lastChange=T);let E=h.get(e);T-E.lastChange>=n?(h.delete(e),r(void 0,_)):c=setTimeout(f,a,_)})}h.has(e)||(h.set(e,{lastChange:m,cancelWait:()=>(h.delete(e),clearTimeout(c),s)}),c=setTimeout(f,a))}_isIgnored(e,n){if(this.options.atomic&&Ks.test(e))return!0;if(!this._userIgnored){let{cwd:s}=this.options,o=(this.options.ignored||[]).map(ur(s)),c=[...[...this._ignoredPaths].map(ur(s)),...o];this._userIgnored=eo(c,void 0)}return this._userIgnored(e,n)}_isntIgnored(e,n){return!this._isIgnored(e,n)}_getWatchHelpers(e){return new rn(e,this.options.followSymlinks,this)}_getWatchedDir(e){let n=z.resolve(e);return this._watched.has(n)||this._watched.set(n,new nn(n,this._boundRemove)),this._watched.get(n)}_hasReadPermissions(e){return this.options.ignorePermissionErrors?!0:!!(Number(e.mode)&256)}_remove(e,n,s){let r=z.join(e,n),o=z.resolve(r);if(s=s??(this._watched.has(r)||this._watched.has(o)),!this._throttle("remove",r,100))return;!s&&this._watched.size===1&&this.add(e,n,!0),this._getWatchedDir(r).getChildren().forEach(u=>this._remove(r,u));let l=this._getWatchedDir(e),m=l.has(n);l.remove(n),this._symlinkPaths.has(o)&&this._symlinkPaths.delete(o);let h=r;if(this.options.cwd&&(h=z.relative(this.options.cwd,r)),this.options.awaitWriteFinish&&this._pendingWrites.has(h)&&this._pendingWrites.get(h).cancelWait()===Z.ADD)return;this._watched.delete(r),this._watched.delete(o);let f=s?Z.UNLINK_DIR:Z.UNLINK;m&&!this._isIgnored(r)&&this._emit(f,r),this._closePath(r)}_closePath(e){this._closeFile(e);let n=z.dirname(e);this._getWatchedDir(n).remove(z.basename(e))}_closeFile(e){let n=this._closers.get(e);n&&(n.forEach(s=>s()),this._closers.delete(e))}_addPathCloser(e,n){if(!n)return;let s=this._closers.get(e);s||(s=[],this._closers.set(e,s)),s.push(n)}_readdirp(e,n){if(this.closed)return;let s={type:Z.ALL,alwaysStat:!0,lstat:!0,...n,depth:0},r=er(e,s);return this._streams.add(r),r.once(sr,()=>{r=void 0}),r.once(Qt,()=>{r&&(this._streams.delete(r),r=void 0)}),r}};function oo(t,e={}){let n=new Rt(e);return n.add(t),n}var mr={watch:oo,FSWatcher:Rt};function io(t,e){let n=Object.create(null);for(let o=0;o<e.length;o++){let a=e[o];n[a]?n[a].push(o):n[a]=[o]}let r=[{buffer1index:-1,buffer2index:-1,chain:null}];for(let o=0;o<t.length;o++){let a=t[o],c=n[a]||[],l=0,m=r[0];for(let h of c){let f;for(f=l;f<r.length&&!(r[f].buffer2index<h&&(f===r.length-1||r[f+1].buffer2index>h));f++);if(f<r.length){let u={buffer1index:o,buffer2index:h,chain:r[f]};if(l===r.length?r.push(m):r[l]=m,l=f+1,m=u,l===r.length)break}}r[l]=m}return r[r.length-1]}function pr(t,e){let n=io(t,e),s=[],r=t.length,o=e.length;for(let a=n;a!==null;a=a.chain){let c=r-a.buffer1index-1,l=o-a.buffer2index-1;r=a.buffer1index,o=a.buffer2index,(c||l)&&s.push({buffer1:[r+1,c],buffer1Content:t.slice(r+1,r+1+c),buffer2:[o+1,l],buffer2Content:e.slice(o+1,o+1+l)})}return s.reverse(),s}function ao(t,e,n){let s=[];function r(l,m){s.push({ab:m,oStart:l.buffer1[0],oLength:l.buffer1[1],abStart:l.buffer2[0],abLength:l.buffer2[1]})}pr(e,t).forEach(l=>r(l,"a")),pr(e,n).forEach(l=>r(l,"b")),s.sort((l,m)=>l.oStart-m.oStart);let o=[],a=0;function c(l){l>a&&(o.push({stable:!0,buffer:"o",bufferStart:a,bufferLength:l-a,bufferContent:e.slice(a,l)}),a=l)}for(;s.length;){let l=s.shift(),m=l.oStart,h=l.oStart+l.oLength,f=[l];for(c(m);s.length;){let u=s[0],y=u.oStart;if(y>h)break;h=Math.max(h,y+u.oLength),f.push(s.shift())}if(f.length===1){if(l.abLength>0){let u=l.ab==="a"?t:n;o.push({stable:!0,buffer:l.ab,bufferStart:l.abStart,bufferLength:l.abLength,bufferContent:u.slice(l.abStart,l.abStart+l.abLength)})}}else{let u={a:[t.length,-1,e.length,-1],b:[n.length,-1,e.length,-1]};for(;f.length;){l=f.shift();let j=l.oStart,te=j+l.oLength,G=l.abStart,B=G+l.abLength,X=u[l.ab];X[0]=Math.min(G,X[0]),X[1]=Math.max(B,X[1]),X[2]=Math.min(j,X[2]),X[3]=Math.max(te,X[3])}let y=u.a[0]+(m-u.a[2]),_=u.a[1]+(h-u.a[3]),T=u.b[0]+(m-u.b[2]),E=u.b[1]+(h-u.b[3]),L={stable:!1,aStart:y,aLength:_-y,aContent:t.slice(y,_),oStart:m,oLength:h-m,oContent:e.slice(m,h),bStart:T,bLength:E-T,bContent:n.slice(T,E)};o.push(L)}a=h}return c(e.length),o}function gr(t,e,n,s){s=Object.assign({excludeFalseConflicts:!0,stringSeparator:/\s+/},s),typeof t=="string"&&(t=t.split(s.stringSeparator)),typeof e=="string"&&(e=e.split(s.stringSeparator)),typeof n=="string"&&(n=n.split(s.stringSeparator));let o=[],a=ao(t,e,n),c=[];function l(){c.length&&o.push({ok:c}),c=[]}function m(h,f){if(h.length!==f.length)return!1;for(let u=0;u<h.length;u++)if(h[u]!==f[u])return!1;return!0}return a.forEach(h=>{h.stable?c.push(...h.bufferContent):s.excludeFalseConflicts&&m(h.aContent,h.bContent)?c.push(...h.aContent):(l(),o.push({conflict:{a:h.aContent,aIndex:h.aStart,o:h.oContent,oIndex:h.oStart,b:h.bContent,bIndex:h.bStart}}))}),l(),o}function It(t,e){let n=t.lastIndexOf("/"),s=n<0?"":t.slice(0,n+1),r=n<0?t:t.slice(n+1),o=r.lastIndexOf("."),a=o>0?r.slice(0,o):r,c=o>0?r.slice(o):"",l=h=>String(h).padStart(2,"0"),m=`${e.getFullYear()}-${l(e.getMonth()+1)}-${l(e.getDate())} ${l(e.getHours())}${l(e.getMinutes())}`;return`${s}${a} (conflict ${m})${c}`}function lo(t,e){if(e<2)return t;let n=t.lastIndexOf("."),s=n>t.lastIndexOf("/")&&n>t.lastIndexOf(")"),r=s?t.slice(0,n):t,o=s?t.slice(n):"";return`${r}-${e}${o}`}function co(t){let e=3735928559,n=1103547991;for(let r=0;r<t.length;r++){let o=t.charCodeAt(r);e=Math.imul(e^o,2654435761),n=Math.imul(n^o,1597334677)}e=Math.imul(e^e>>>16,2246822507)^Math.imul(n^n>>>13,3266489909),n=Math.imul(n^n>>>16,2246822507)^Math.imul(e^e>>>13,3266489909);let s=4294967296*(2097151&n)+(e>>>0);return`${t.length.toString(36)}-${s.toString(36)}`}function At(t,e,n){if(t===null&&e===null&&n===null)return{kind:"none"};if(n===null)return t===null?e?{kind:"dropShadow"}:{kind:"none"}:e?t===e.hash?{kind:"deleteLocal"}:{kind:"pushCreate"}:{kind:"pushCreate"};if(t===null)return e?n.seq===e.seq?{kind:"pushDelete"}:{kind:"pull"}:{kind:"pull"};if(!e)return t===n.hash?{kind:"adopt"}:{kind:"conflict"};let s=t!==e.hash,r=n.seq!==e.seq;return!s&&!r?{kind:"none"}:s?r?t===n.hash?{kind:"adopt"}:n.hash===e.hash?{kind:"push",baseSeq:n.seq}:{kind:"conflict"}:{kind:"push",baseSeq:e.seq}:{kind:"pull"}}function yr(t,e,n){let s=gr(t.split(`
194
+ `),e.split(`
195
+ `),n.split(`
196
+ `),{excludeFalseConflicts:!0}),r=[];for(let o of s){if(o.conflict)return null;o.ok&&r.push(...o.ok)}return r.join(`
197
+ `)}function sn(t,e,n=200){return t>=n||e>=5&&t>=Math.max(5,Math.ceil(e/2))}var uo=/[\u0000-\u001f\u007f]/;function Ve(t){let e=t.replace(/\\/g,"/").normalize("NFC").trim();if(e=e.replace(/\/+$/,""),!e||e.length>512||e.startsWith("/")||uo.test(e))return null;let n=e.split("/");for(let s of n)if(!s||s==="."||s==="..")return null;return n.join("/")}function on(t,e){let n=t.replace(/\\/g,"/").normalize("NFC");return e===""?Ve(n):n.startsWith(`${e}/`)?Ve(n.slice(e.length+1)):null}function wr(t,e){return e===""?t:`${e}/${t}`}function it(t){return!!(t===".DS_Store"||t==="Icon\r"||t===".sync-trash"||/\.tmp-\d+-\d+-\d+$/.test(t)||/^\..+\.lock$/.test(t))}function Ce(t){return/\.md$/i.test(t)?"page":/\.db$/i.test(t)?"db":"binary"}var $e=t=>t==="page"||t==="db";import{gzip as fo}from"node:zlib";import{promisify as ho}from"node:util";var mo=ho(fo),po=1024,le=class extends Error{status;body;constructor(e,n,s){super(`cloud http ${e} on ${s}`),this.status=e,this.body=n}},br=t=>12e4+Math.ceil(t/256);function Sr(t){let e=`${t.baseUrl.replace(/\/+$/,"")}/api/amadeus`,n=async(r,o,a)=>{let c={Authorization:`Bearer ${t.token}`,...a?.headers};r!=="GET"&&(c["X-Amadeus-Client"]=t.clientId);let l;a?.json!==void 0?(c["Content-Type"]="application/json",l=JSON.stringify(a.json),l.length>=po&&(c["Content-Encoding"]="gzip",l=await mo(l))):a?.form&&(l=a.form);let m=await fetch(o,{method:r,headers:c,body:l,signal:AbortSignal.timeout(a?.timeoutMs??3e4)});if(!m.ok){let h=null;try{h=await m.json()}catch{}throw new le(m.status,h,o)}return m.json()},s=r=>new URLSearchParams(r).toString();return{clientId:t.clientId,async listVaults(){return((await n("GET",`${e}/vaults`)).vaults??[]).map(o=>({id:String(o.id),name:String(o.name),lastChangeSeq:Number(o.lastChangeSeq??0)}))},async tree(r){let o=await n("GET",`${e}/vaults/${r}/tree`);if(!Array.isArray(o.entries))throw new Error("server too old: tree has no entries[] (deploy the amadeus microserver update)");return{folders:o.folders??[],seq:Number(o.seq??0),maxFileBytes:Number.isInteger(o.maxFileBytes)&&o.maxFileBytes>0?o.maxFileBytes:void 0,entries:o.entries.map(a=>({path:String(a.path),kind:a.kind,seq:Number(a.seq??0),hash:a.hash??null,size:Number(a.size??0)}))}},async getFile(r,o){let a=await n("GET",`${e}/vaults/${r}/file?${s({path:o})}`);return{content:String(a.content??""),seq:Number(a.seq??0),hash:a.hash??null}},putFile(r,o,a,c,l=!1){return n("PUT",`${e}/vaults/${r}/file`,{json:{path:o,content:a,baseSeq:c,...l?{force:!0}:{}}})},async deleteFile(r,o,a,c){let l={path:o};a!==void 0&&(l.baseSeq=String(a)),await n("DELETE",`${e}/vaults/${r}/file?${s(l)}`,c?.confirmed?{headers:{"X-Amadeus-Delete-Confirmed":"1"}}:void 0)},move(r,o,a){return n("POST",`${e}/vaults/${r}/move`,{json:{from:o,to:a}})},renameFolder(r,o,a){return n("POST",`${e}/vaults/${r}/folders/rename`,{json:{path:o,newName:a}})},moveFolder(r,o,a){return n("POST",`${e}/vaults/${r}/folders/move`,{json:{path:o,dest:a}})},async deleteFolder(r,o){await n("DELETE",`${e}/vaults/${r}/folders?${s({path:o})}`)},putBinary(r,o,a,c){let l=new FormData;return l.set("path",o),c?.ifAbsent&&l.set("ifAbsent","true"),c?.baseSeq!==void 0&&l.set("baseSeq",String(c.baseSeq)),l.set("file",new Blob([new Uint8Array(a)]),o.split("/").pop()||"file"),n("POST",`${e}/vaults/${r}/binary`,{form:l,timeoutMs:br(a.length)})},async listVersions(r,o){return((await n("GET",`${e}/vaults/${r}/file/versions?${s({path:o})}`)).versions??[]).map(c=>({id:String(c.id),seq:Number(c.seq??0)}))},async getVersion(r,o){let a=await n("GET",`${e}/vaults/${r}/file/versions/${o}`);return String(a.content??"")},async getAsset(r,o){let a=new AbortController,c=setTimeout(()=>a.abort(),12e4);try{let l=await fetch(`${e}/vaults/${r}/asset?${s({ref:o})}`,{headers:{Authorization:`Bearer ${t.token}`},signal:a.signal});if(!l.ok)throw new le(l.status,null,"asset:"+o);return clearTimeout(c),c=setTimeout(()=>a.abort(),br(Number(l.headers.get("content-length"))||0)),Buffer.from(await l.arrayBuffer())}finally{clearTimeout(c)}},async changes(r,o){let a=await n("GET",`${e}/vaults/${r}/changes?${s({since:String(o)})}`);return{changes:a.changes??[],seq:Number(a.seq??0)}}}}function Er(t,e){let n=!1,s=0,r=null,o=null,a=()=>`${t.baseUrl.replace(/\/+$/,"")}/api/amadeus/vaults/${t.vaultId}/events?since=${e.getSince()}`,c=m=>{if(n)return;e.onDown(m);let h=Math.min(3e4,1e3*2**s)*(.7+Math.random()*.6);s++,o=setTimeout(()=>void l(),h)},l=async()=>{if(n)return;r=new AbortController;let m;try{m=await fetch(a(),{headers:{Authorization:`Bearer ${t.token}`,Accept:"text/event-stream"},signal:r.signal})}catch(E){c(E);return}if(!m.ok||!m.body){c(new Error(`sse http ${m.status}`));return}s=0,e.onOpen();let h=m.body.getReader(),f=new TextDecoder,u="",y="",_=[],T=()=>{if(!_.length&&!y)return;let E=_.join(`
198
+ `),L=y||"message";y="",_=[];let j=null;try{j=E?JSON.parse(E):null}catch{return}L==="hello"?e.onHello(Number(j?.seq??0)):L==="change"?e.onChange(j):L==="reset"?e.onReset():L==="presence"?e.onPresence?.(j):L==="presence-roster"&&e.onPresenceRoster?.(j)};try{for(;;){let{done:E,value:L}=await h.read();if(E)break;for(u+=f.decode(L,{stream:!0});;){let j=u.indexOf(`
199
+ `);if(j<0)break;let te=u.slice(0,j).replace(/\r$/,"");if(u=u.slice(j+1),te==="")T();else{if(te.startsWith(":"))continue;te.startsWith("event:")?y=te.slice(6).trim():te.startsWith("data:")&&_.push(te.slice(5).replace(/^ /,""))}}}}catch(E){n||c(E);return}c(new Error("sse stream ended"))};return l(),{stop:()=>{n=!0,o&&clearTimeout(o),r?.abort()}}}import{constants as go,promises as Ye}from"node:fs";import yo from"node:path";var Ge=t=>yo.join(de().userDataDir(),de().isDevMode()?`${t}.dev.json`:`${t}.json`);async function an(t){try{let e=JSON.parse(await Ye.readFile(Ge(t),"utf8"));return!e||typeof e.vaultRoot!="string"||typeof e.vaultId!="string"?null:(e.files=e.files??{},e.cursor=Number(e.cursor??0),e.lastSyncAt=e.lastSyncAt??null,e)}catch{return null}}function vr(t){let e=null,n=null,s=Promise.resolve(),r=null,o=()=>{if(!e)return s;let a=e,c=JSON.stringify(e);return e=null,s=s.then(async()=>{try{let l=Ge(t),m=`${l}.tmp-${process.pid}-${Date.now()}-0`;await Ye.writeFile(m,c,"utf8"),await Ye.rename(m,l),r=null}catch(l){e??=a,r=l}}),s};return{save(a){e=a,!n&&(n=setTimeout(()=>{n=null,o()},500))},async flush(a=!1){if(n&&(clearTimeout(n),n=null),await o(),a&&r)throw r}}}async function _r(t){try{await Ye.unlink(Ge(t))}catch{}}async function kr(t,e){try{await Ye.copyFile(Ge(t),Ge(e),go.COPYFILE_EXCL)}catch(n){let s=n?.code;if(s==="EEXIST"||s==="ENOENT")return!1;throw n}return await Ye.unlink(Ge(t)).catch(()=>{}),!0}var bo=5*1024*1024,So=5*1024*1024,Eo=3e4,vo=2500,_o=3e3,ko=5,Co=256*1024,xo=5,xr=1024*1024,Tr=200,To=6e4,Ro=50,Io=".sync-trash",Je=t=>wo("sha256").update(t).digest("hex");function at(t,e={localRoot:De(),shadowName:`amadeus-sync-${rt()}`,vaultId:"first",serverDir:"",excludePrefixes:["\u4E0E\u6211\u5171\u4EAB/"]}){let n=i=>{let d=on(i,"");if(!d)return null;for(let p of e.excludePrefixes??[])if(d===p.replace(/\/$/,"")||d.startsWith(p))return null;if(e.ignoreNames?.length&&d.split("/").some(p=>e.ignoreNames.includes(p)))return null;let g=e.serverDir?`${e.serverDir}/${d}`:d;return e.inScope&&!e.inScope(g,Ce(g))?null:g},s=i=>{let d;if(e.serverDir){if(!i.startsWith(`${e.serverDir}/`))return null;d=i.slice(e.serverDir.length+1)}else{for(let g of e.excludePrefixes??[])if(i.startsWith(g))return null;d=i}return d.split("/").some(g=>it(g)||!!e.ignoreNames?.includes(g))?null:d},r=(i,d)=>!e.inScope||e.inScope(i,d),o=e.accountId??fe(),a=!1,c=0,l=Promise.resolve(),m=new Set,h="disabled",f=null,u=null,y=null,_=null,T=null,E=null,L=0,j=new Map,te=null,G=vr(e.shadowName),B=new Map,X=!1,Y=!1,ne=[],ue=()=>{u&&(u.pending=B.size?Object.fromEntries(B):void 0,G.save(u))},ut=()=>{Y=!1,ne.length=0},Qe=()=>{if(Y)return!0;let i=Date.now();for(;ne.length&&i-ne[0]>To;)ne.shift();return ne.length>=Ro?(Y=!0,!0):!1},xe=[],Ne=new Set,Ze=!1,v=null,C=null,w=null,b=()=>{!a||w||(w=setTimeout(()=>{w=null,t.onStatus(Oe())},200))},A=(i,d)=>{h=i,d!==void 0&&(f=d),b()},S=(i,d=!1)=>{if(a){if(i.key){if(Ne.has(i.key))return;Ne.add(i.key)}d?xe.unshift(i):xe.push(i),V()}},x=new Map,D=i=>{if(!a)return;let d=(u?.files[i]?.size??0)>Co,g=(e.pushQuietMs??_o)*(d?xo:1),p=Date.now(),k=x.get(i);k&&clearTimeout(k.timer);let I=k?.since??p,$=Math.max(0,Math.min(g,I+g*ko-p)),R=setTimeout(()=>{x.delete(i),S({key:i,run:()=>ae(i,!0)})},$);x.set(i,{timer:R,since:I}),b()},U=()=>{for(let{timer:i}of x.values())clearTimeout(i);x.clear()},N=i=>!(i instanceof le)||i.status>=500||i.status===0,F=i=>i instanceof le&&(i.status===401||i.status===403),V=async()=>{if(!Ze){Ze=!0;try{for(;xe.length;){(h==="idle"||h==="starting")&&A("syncing");let i=xe.shift();i.key&&Ne.delete(i.key);try{await i.run()}catch(d){if(!a)return;if(F(d)){xe.length=0,Ne.clear(),gt(),A("auth-required","login-expired");return}if(N(d)){S(i,!0),gt(),A("offline",d?.message||"network error"),W();return}let g=i.key??"(op)";j.set(g,d?.body?.code||`http ${d?.status}`),b()}}a&&h==="syncing"&&(u&&(u.lastSyncAt=Date.now(),G.save(u)),A("idle",null))}finally{Ze=!1;for(let i of m)i();m.clear()}}},W=()=>{!a||v||(v=setTimeout(()=>{v=null,tt()},Eo))},q=i=>{if(!E||!u)throw new Error("engine not bound");let d=s(i);if(d===null)throw new Error("path outside binding: "+i);let g=se.resolve(E,wr(d,u.folder)),p=se.relative(E,g);if(p.startsWith("..")||se.isAbsolute(p))throw new Error("path escapes vault: "+i);return g},Q=i=>({size:i,mtimeMs:-1}),J=async i=>{try{let d=await ee.stat(i);return d.isFile()?{size:d.size,mtimeMs:Math.floor(d.mtimeMs)}:null}catch{return null}},we=0,Fe=async(i,d,g=()=>!0)=>{await ee.mkdir(se.dirname(i),{recursive:!0});let p=`${i}.tmp-${process.pid}-${Date.now()}-${we++}`;await ee.writeFile(p,d);let k=await J(p)??Q(Buffer.byteLength(d));return g()?(await ee.rename(p,i),k):(await ee.rm(p,{force:!0}),null)},Ue=async i=>{let d;try{d=await ee.readdir(i,{withFileTypes:!0})}catch{return}for(let g of d)g.isDirectory()&&await Ue(se.join(i,g.name));try{await ee.rmdir(i)}catch{}},oe=async i=>{let d=q(i),g=await J(d),p;try{p=await ee.readFile(d)}catch{return null}return{hash:$e(Ce(i))?Je(p.toString("utf8")):Je(p),size:g?.size??p.length,mtimeMs:g?.mtimeMs??-1,buf:p}},_e=async(i,d,g,p)=>{u&&(u.files[i]={seq:d,hash:g,size:p.size,mtimeMs:p.mtimeMs},G.save(u))},ye=i=>{u&&i in u.files&&(delete u.files[i],G.save(u))},Te=async(i,d)=>{if(!y||!u||be(i))return;let g=re,p=Ce(i),k,I,$;if($e(p)){let O;try{O=await y.getFile(u.vaultId,i)}catch(H){if(H instanceof le&&H.status===404){await $t(i);return}throw H}k=O.content,I=O.seq,$=O.hash??Je(O.content)}else{let O;try{O=await y.getAsset(u.vaultId,i)}catch(H){if(H instanceof le&&H.status===404){j.set(i,"ASSET_404"),b();return}throw H}k=O,I=d??0,$=Je(O)}let R=await oe(i);if(g!==re||be(i))return;if(R&&R.hash===$){await _e(i,I,$,R);return}let M=u.files[i];if(R&&M&&$===M.hash&&R.hash!==M.hash){await _e(i,I,$,Q(M.size)),S({key:i,run:()=>ae(i)});return}if(R&&(!M||R.hash!==M.hash)){if(M&&p==="page"&&typeof k=="string"&&await Or(i,M,R,k,I,$,()=>g===re&&!be(i))||g!==re||be(i))return;await Lr(i)}let P=await Fe(q(i),k,()=>g===re&&!be(i));P&&await _e(i,I,$,P)},Or=async(i,d,g,p,k,I,$)=>{try{if(!y||!u||g.buf.length>xr||p.length>xr)return!1;let M=(await y.listVersions(u.vaultId,i)).find(H=>H.seq===d.seq);if(!M)return!1;let P=await y.getVersion(u.vaultId,M.id);if(Je(P)!==d.hash)return!1;let O=yr(g.buf.toString("utf8"),P,p);return O===null?!1:(await Fe(q(i),O,$)&&(await _e(i,k,I,Q(Buffer.byteLength(O))),S({key:i,run:()=>ae(i)})),!0)}catch{return!1}},Lr=async i=>{let d=Ve(It(i,new Date));if(!d)return;let g=d.lastIndexOf("."),p=g>d.lastIndexOf("/"),k=p?d.slice(0,g):d,I=p?d.slice(g):"",$=d;for(let R=2;Cr(q($));R++)$=`${k}-${R}${I}`;try{await ee.rename(q(i),q($))}catch(R){if(R?.code==="ENOENT")return;throw R}L++,S({key:$,run:()=>ae($)}),b()},yn=async i=>{if(!E)return;let d=q(i),g=s(i)??i,p=se.join(E,Io,new Date().toISOString().slice(0,10),...g.split("/")),k=Cr(p)?`${p}.${Date.now()}`:p;try{await ee.mkdir(se.dirname(k),{recursive:!0}),await ee.rename(d,k)}catch(I){if(I?.code==="ENOENT")return;throw new Error(`\u8F6F\u5220\u5931\u8D25,\u4FDD\u7559\u672C\u5730\u6587\u4EF6 ${d}: ${I?.message??String(I)}`)}},$t=async i=>{if(!u)return;let d=await oe(i);if(be(i))return;let g=u.files[i]??null,p=At(d?.hash??null,g,null);if(p.kind==="deleteLocal"){if(!X&&Qe()){B.set(i,"local"),ue(),b();return}ne.push(Date.now()),await yn(i),ye(i)}else p.kind==="pushCreate"?(ye(i),S({key:i,run:()=>ae(i)})):ye(i)},wn=(i,d)=>{if(u){for(let g of Object.keys(u.files))if(g===i||g.startsWith(`${i}/`)){let p=d+g.slice(i.length);u.files[p]=u.files[g],delete u.files[g]}G.save(u)}},bn=async i=>{if(!y||!u||i.seq<=u.cursor||!await ht())return;if(i.origin.client&&y.clientId===i.origin.client){u.cursor=i.seq,G.save(u);return}let d=i.type==="structure"?"folder":i.type,g=k=>s(k)!==null&&r(k,d);if(!g(i.path)&&!(i.newPath&&g(i.newPath))){u.cursor=i.seq,G.save(u);return}let p=i.path;switch(i.op){case"write":await Te(p,i.fileSeq);break;case"delete":await $t(p);break;case"move":{let k=i.newPath;if(!k)break;let I=u.files[p];if(await oe(p)&&I)try{await ee.mkdir(se.dirname(q(k)),{recursive:!0}),await ee.rename(q(p),q(k)),u.files[k]={...I,seq:i.fileSeq??I.seq},delete u.files[p],G.save(u)}catch{await Te(k,i.fileSeq)}else ye(p),await Te(k,i.fileSeq);break}case"mkdir":await ee.mkdir(q(p),{recursive:!0});break;case"rename-folder":case"move-folder":{let k=i.newPath;if(!k)break;try{await ee.mkdir(se.dirname(q(k)),{recursive:!0}),await ee.rename(q(p),q(k))}catch{}wn(p,k);break}case"delete-folder":{let k=`${p}/`;for(let I of Object.keys(u.files))(I===p||I.startsWith(k))&&await $t(I);await Ue(q(p));break}}if(u.cursor=i.seq,G.save(u),i.op==="move"||i.op==="rename-folder"||i.op==="move-folder"||i.op==="delete"||i.op==="delete-folder")try{await t.onRemoteApplied?.(i)}catch{}},jr=async(i,d,g)=>{let p=Number(d?.seq??0),k=d?.content??null;if(k!==null&&Je(k)===g.hash){await _e(i,p,g.hash,g);return}if(k===null&&p===0){if(!u?.files[i]){j.set(i,d?.code||"EXISTS"),b();return}ye(i),S({key:i,run:()=>ae(i)});return}await Te(i,p)},dt=async(i,d)=>{if(!y||!u)return;let g=await oe(i);if(!g){S({key:i,run:()=>ae(i)});return}if(g.size>bo){j.set(i,"TOO_LARGE"),b();return}let p=g.buf.toString("utf8");try{let k=await y.putFile(u.vaultId,i,p,d);j.delete(i),await _e(i,k.seq,k.hash??g.hash,g)}catch(k){if(k instanceof le&&k.status===409){await jr(i,k.body,g);return}throw k}},ft=async(i,d)=>{if(!y||!u)return;let g=await oe(i);if(!g){S({key:i,run:()=>ae(i)});return}if(g.size>(te??So)){j.set(i,"TOO_LARGE"),b();return}try{let p=await y.putBinary(u.vaultId,i,g.buf,{baseSeq:d});j.delete(i),await _e(i,p.seq,g.hash,g)}catch(p){if(p instanceof le&&p.status===409){let k=Number(p.body?.seq??0),I=p.body?.hash??null;if(I!==null&&I===g.hash){await _e(i,k,g.hash,g);return}if(k===0){if(!u.files[i]){j.set(i,p.body?.code||"EXISTS"),b();return}ye(i),S({key:i,run:()=>ae(i)});return}await Te(i,k);return}throw p}},Sn=async i=>{if(!y||!u||be(i))return;let d=re,g=u.files[i];if(g){if($e(Ce(i)))try{let p=await y.getFile(u.vaultId,i);if(p.seq!==g.seq){await Te(i,p.seq);return}}catch(p){if(p instanceof le&&p.status===404){ye(i);return}throw p}if(!(d!==re||be(i))){try{await y.deleteFile(u.vaultId,i,g.seq,{confirmed:X})}catch(p){if(p instanceof le&&p.status===409){await Te(i,Number(p.body?.seq??0)||null);return}if(p instanceof le&&p.status===429&&p.body?.code==="MASS_DELETE_BLOCKED"){B.set(i,"remote"),Y=!0,ue(),b();return}throw p}ye(i)}}},ht=async()=>E?await ee.stat(E).then(d=>d.isDirectory()).catch(()=>!1)||!e.requireRootExists&&!Object.keys(u?.files??{}).length?!0:(A("error",`vault-missing: ${E}`),W(),!1):!1,re=0,mt=new Set,pt=new Map,he=i=>JSON.stringify([i.from,i.to]),Pe=(i,d)=>i===d||i.startsWith(`${d}/`),be=i=>[...u?.moves??[],...mt].some(d=>Pe(i,d.from)||Pe(i,d.to)),Re=()=>!!(u?.moves?.length||mt.size),Mt=async i=>{if(!y||!u)return;let{from:d,to:g,kind:p}=i;if(s(d)===null||s(g)===null)throw new Error("Invalid queued cloud move");i.hashes??=Object.fromEntries(Object.entries(u.files).filter(([R])=>Pe(R,d)).map(([R,M])=>[R.slice(d.length),M.hash])),G.save(u),await G.flush(!0);let k,I=!1;try{if(p==="folder"){let R=se.posix.dirname(d)==="."?"":se.posix.dirname(d),M=se.posix.dirname(g)==="."?"":se.posix.dirname(g);R===M?await y.renameFolder(u.vaultId,d,se.posix.basename(g)):await y.moveFolder(u.vaultId,d,M)}else{let R=await y.move(u.vaultId,d,g);k=Number(R.seq)}}catch(R){if(!(R instanceof le)||R.status!==404)throw R;let M=await y.tree(u.vaultId);if(M.entries.some(H=>Pe(H.path,d))||M.folders.some(H=>Pe(H,d)))throw R;let O=M.entries.find(H=>H.path===g);if(k=O?.seq,I=!O&&!M.entries.some(H=>Pe(H.path,g))&&!M.folders.some(H=>Pe(H,g)),!I){let H=Object.entries(i.hashes);if(!(H.length>0&&H.every(([ke,He])=>M.entries.some(ze=>ze.path===g+ke&&ze.hash===He))))throw new le(409,{code:"MOVE_DESTINATION_CHANGED"},"local-move")}}if(I)for(let R of Object.keys(u.files))Pe(R,d)&&delete u.files[R];else wn(d,g),k!==void 0&&u.files[g]&&(u.files[g].seq=k);u.moves=(u.moves??[]).filter(R=>he(R)!==he(i)),G.save(u);try{await G.flush(!0)}catch(R){throw u.moves.unshift(i),G.save(u),R}let $=pt.get(he(i));pt.delete(he(i)),$?.(),be(g)||(p==="folder"?await Nt():await ae(g))},ae=async(i,d=!1)=>{if(!u||be(i))return;if(!r(i,Ce(i))){ye(i);return}if(!await ht())return;let g=await oe(i);if(be(i))return;let p=u.files[i]??null,k=At(g?.hash??null,p,p?{seq:p.seq,hash:p.hash}:null);switch(k.kind){case"push":$e(Ce(i))?await dt(i,k.baseSeq):await ft(i,k.baseSeq);break;case"pushCreate":$e(Ce(i))?await dt(i,0):await ft(i,0);break;case"pushDelete":if(d){wt();break}if(!X&&(B.has(i)||Qe())){B.set(i,"remote"),ue(),b();break}ne.push(Date.now()),await Sn(i);break;case"dropShadow":ye(i);break;default:g&&p&&g.hash===p.hash&&g.mtimeMs>=0&&(p.size!==g.size||p.mtimeMs!==g.mtimeMs)&&await _e(i,p.seq,p.hash,g);break}},En=async()=>{let i=new Map;if(!E||!u)return i;let d=E,g=null,p=async k=>{if(g)return;let I;try{I=await ee.readdir(k,{withFileTypes:!0})}catch($){g=`${k}: ${$?.message??String($)}`;return}for(let $ of I){if(it($.name)||$.isDirectory()&&e.ignoreNames?.includes($.name))continue;let R=se.join(k,$.name);if($.isDirectory())await p(R);else if($.isFile()){let M=se.relative(d,R).split(se.sep).join("/"),P=n(M);if(!P)continue;try{let O=await ee.stat(R);if(!O.isFile())continue;i.set(P,{size:O.size,mtimeMs:Math.floor(O.mtimeMs)})}catch(O){if(O?.code==="ENOENT")continue;g=`${R}: ${O?.message??String(O)}`;return}}}};return await p(d),g?(A("error",`scan-failed: ${g}`),W(),null):i},Nt=async()=>{let i=re;if(Re()||i!==re||!u||!await ht())return;let d=await En();if(!d||Re()||i!==re)return;let g=!1;for(let[I,$]of[...B])($==="remote"&&d.has(I)||$==="local"&&!d.has(I))&&(B.delete(I),g=!0);B.size||ut();for(let[I,$]of d){let R=u.files[I];R&&R.size===$.size&&R.mtimeMs===$.mtimeMs||S({key:I,run:()=>ae(I)})}let p=Object.keys(u.files),k=p.filter(I=>!d.has(I));if(k.length&&!X&&(Y||sn(k.length,p.length,Tr))){Y=!0;for(let I of k)B.set(I,"remote");ue(),b();return}g&&(ue(),b());for(let I of k)B.has(I)||S({key:I,run:()=>ae(I)})},et=async()=>{let i=re;if(Re()||i!==re||!y||!u||!E||!await ht())return;let d=await y.tree(u.vaultId);if(d.maxFileBytes!==void 0&&d.maxFileBytes!==te&&(te=d.maxFileBytes,b()),Re()||i!==re)return;let g=new Map;for(let P of d.entries)s(P.path)===null||!r(P.path,P.kind)||g.set(P.path,P);let p=await En();if(!p||Re()||i!==re)return;let k=new Set([...g.keys(),...p.keys(),...Object.keys(u.files)]),I=Object.keys(u.files).length,$=[];for(let P of k){if(Re()||i!==re)return;let O=u.files[P]??null,H=g.get(P)??null,ce=p.get(P)??null,ke=null,He=Q(ce?.size??0);if(ce)if(O&&O.size===ce.size&&O.mtimeMs===ce.mtimeMs)ke=O.hash,He=ce;else{let ze=await oe(P);ze&&(ke=ze.hash,He=ze)}$.push({sp:P,d:At(ke,O,H?{seq:H.seq,hash:H.hash}:null),rSeq:H?.seq??null,localHash:ke,localStat:He})}if(Re()||i!==re)return;let R=$.filter(P=>P.d.kind==="deleteLocal"||P.d.kind==="pushDelete").length,M=!X&&(Y||sn(R,I,Tr));M&&R&&(Y=!0),B.clear();for(let{sp:P,d:O,rSeq:H,localHash:ce,localStat:ke}of $){if(Re()||i!==re)return;if(M&&(O.kind==="deleteLocal"||O.kind==="pushDelete")){B.set(P,O.kind==="deleteLocal"?"local":"remote");continue}if((O.kind==="deleteLocal"||O.kind==="pushDelete")&&((await oe(P))?.hash??null)!==ce){S({key:P,run:()=>ae(P)});continue}if(Re()||i!==re)return;switch(O.kind){case"adopt":await _e(P,H,ce,ke);break;case"pull":await Te(P,H);break;case"push":$e(Ce(P))?await dt(P,O.baseSeq):await ft(P,O.baseSeq);break;case"pushCreate":$e(Ce(P))?await dt(P,0):await ft(P,0);break;case"pushDelete":await Sn(P);break;case"deleteLocal":await yn(P),ye(P);break;case"conflict":await Te(P,H);break;case"dropShadow":ye(P);break;case"none":break}}X&&(X=!1,ne.length=0),B.size||ut(),ue(),M&&b();for(let P of d.folders)if(!(s(P)===null||!r(P,"folder")))try{await ee.mkdir(q(P),{recursive:!0})}catch{}u.cursor=d.seq,u.lastSyncAt=Date.now(),G.save(u)},Ur=async()=>{if(!y||!u)return;let i=u.cursor,d=await y.changes(u.vaultId,i);if(d.changes.length===0&&d.seq>i||d.changes.length>0&&d.changes[0].seq!==i+1){await et();return}for(let p of d.changes)await bn(p)},Ie=null,vn=[],_n=()=>{Ie&&vn.push(Ie.close()),Ie=null},Hr=()=>{if(!a||Ie||!E)return;Ie=mr.watch(E,{ignoreInitial:!0,depth:12,ignored:d=>{let g=se.basename(d);return it(g)||!!e.ignoreNames?.includes(g)}});let i=d=>{if(!E)return;let g=se.relative(E,d);if(!g||g.startsWith(".."))return;let p=n(g);p&&D(p)};Ie.on("change",i),Ie.on("add",i),Ie.on("unlink",()=>wt()),Ie.on("unlinkDir",()=>wt())},gt=()=>{_?.stop(),_=null},zr=()=>{if(!a||!y||!u||_)return;let i=T;i&&(_=Er({baseUrl:i.cloudUrl,vaultId:u.vaultId,token:i.token},{getSince:()=>u?.cursor??0,onHello:d=>{u&&d>u.cursor&&S({run:Ur})},onChange:d=>{S({run:()=>bn(d)})},onReset:()=>{S({run:et})},onOpen:()=>{(h==="offline"||h==="starting")&&A("idle",null),S({run:Nt})},onDown:()=>{(h==="idle"||h==="syncing")&&A("offline")},onPresence:d=>t.onPresence?.(u?.vaultId??"",d),onPresenceRoster:d=>t.onPresenceRoster?.(u?.vaultId??"",d)}))},qr=async()=>{let i=await Ee(o);if(i.cloudSync?.deviceId)return i.cloudSync.deviceId;let d=`desk-${Math.random().toString(36).slice(2,10)}${Date.now().toString(36)}`;return await Ae({cloudSync:{...i.cloudSync??{},deviceId:d}},o),d},Wr=async i=>{gt(),_n(),xe.length=0,Ne.clear(),B.clear(),X=!1,Y=!1,ne.length=0;let d=await Ee(o);if(i!==c)return;let g=d.cloudSync;if(g?.enabled===!1){E=null,y=null,A("disabled",null);return}if(!o||o!==fe()){A("auth-required","not-logged-in");return}if(E=e.localRoot,e.requireRootExists){let $=await ee.stat(E).then(R=>R.isDirectory()).catch(()=>!1);if(i!==c)return;if(!$){A("error",`vault-missing: ${E}`),W();return}}if(i!==c)return;let p=t.loadCreds();if(!p.cloudUrl||!p.token){y=null,A("auth-required","not-logged-in");return}A("starting",null);let k=g?.deviceId??await qr();if(i!==c)return;let I=e.clientIdSuffix?`${k}#${e.clientIdSuffix}`:k;T={cloudUrl:p.cloudUrl,token:p.token},y=Sr({baseUrl:p.cloudUrl,token:p.token,clientId:I});try{let $=e.vaultId==="first"?g?.vaultId:e.vaultId;if(!$){let M=await y.listVaults();if(i!==c)return;if(!M.length)throw new Error("\u4E91\u7AEF\u65E0\u53EF\u7528 vault");$=M[0].id,await Ae({cloudSync:{...g??{},vaultId:$}},o)}if(i!==c)return;let R=await an(e.shadowName);if(i!==c||(u=R&&R.vaultRoot===E&&R.vaultId===$&&R.folder===""?R:{vaultRoot:E,folder:"",vaultId:$,cursor:0,lastSyncAt:null,files:{}},i!==c))return;for(let[M,P]of Object.entries(u.pending??{}))B.set(M,P);if(B.size&&(Y=!0),!e.requireRootExists){let M=await ee.stat(E).then(P=>P.isDirectory()).catch(()=>!1);if(i!==c)return;if(!M){if(Object.keys(u.files).length){A("error",`mirror-missing: ${E}`),W();return}if(await ee.mkdir(E,{recursive:!0}),i!==c)return}}Hr();for(let M of u.moves??[])S({key:`move:${he(M)}`,run:()=>Mt(M)});S({run:et}),S({run:async()=>{zr()}})}catch($){if(i!==c)return;F($)?A("auth-required","login-expired"):(A("offline",$?.message||String($)),W())}},kn=()=>{a=!1,gt(),_n(),xe.length=0,Ne.clear(),U();for(let i of[v,C,w])i&&clearTimeout(i);v=C=w=null},Cn=async()=>{Ze&&await new Promise(i=>m.add(i)),await Promise.all(vn.splice(0)),await G.flush(),u=null,y=null,T=null,E=null,L=0,j.clear(),te=null,B.clear(),X=!1,Y=!1,ne.length=0,h="disabled",f=null},Br=()=>{xn()},yt=null,tt=()=>{yt?.(),yt=de().onBeforeQuit(Br);let i=++c;kn();let d=l.catch(()=>{}).then(async()=>{await Cn(),i===c&&(a=!0,await Wr(i))});return l=d,d},xn=()=>{yt?.(),yt=null,++c,kn();let i=l.catch(()=>{}).then(Cn);return l=i,i},Oe=()=>({enabled:h!=="disabled",state:h==="idle"&&x.size?"syncing":h,lastSyncAt:u?.lastSyncAt??null,pending:xe.length+x.size,conflicts:L,skipped:[...j].map(([i,d])=>({path:i,reason:d})),error:f,pendingDeletions:B.size,maxFileBytes:te});return{getStatus:Oe,start(){tt()},notifyLocal(i,d,g){if(!u||h==="disabled"||h==="auth-required")return;let p=n(i),k=g?n(g):null;if(d==="write"&&p){it(p.split("/").pop()||"")||D(p);return}if(d==="remove"){if(!p)return;let I=`${p}/`,$=!1;for(let R of Object.keys(u.files))(R===p||R.startsWith(I))&&($=!0,S({key:R,run:()=>ae(R)}));!$&&p&&S({key:p,run:()=>ae(p)})}},holdLocalMove(i,d){let g=k=>e.serverDir?`${e.serverDir}/${k.replace(/\\/g,"/").normalize("NFC")}`:k.replace(/\\/g,"/").normalize("NFC"),p={from:g(i),to:g(d)};return++re,mt.add(p),()=>{mt.delete(p)}},async notifyLocalMove(i,d,g,p){let k=n(i),I=n(d),$=u??await an(e.shadowName),R=on(i,""),M=R&&(e.serverDir?`${e.serverDir}/${R}`:R);if(!k&&I&&M&&$&&Object.keys($.files).some(P=>P===M||P.startsWith(`${M}/`))&&(k=M),!k&&!I){g?.();return}if(k&&I){let P=u??$;if(!P){g?.();return}let O=p??(Object.keys(P.files).some(ce=>ce.startsWith(`${k}/`))?"folder":"file"),H={from:k,to:I,kind:O};P.moves??=[],P.moves.some(ce=>he(ce)===he(H))||(P.moves.push(H),++re),g&&pt.set(he(H),g),G.save(P);try{await G.flush(!0)}catch(ce){throw P.moves=P.moves.filter(ke=>he(ke)!==he(H)),pt.delete(he(H)),G.save(P),ce}u===P&&a&&h!=="disabled"&&h!=="auth-required"&&S({key:`move:${he(H)}`,run:()=>Mt(H)});return}k&&this.notifyLocal(i,"remove"),I&&(S({key:I,run:()=>ae(I)}),wt()),g?.()},async setEnabled(i){let d=await Ee(o);return await Ae({cloudSync:{...d.cloudSync??{},enabled:i}},o),await tt(),Oe()},async restart(){return await tt(),Oe()},async syncNow(){if(j.clear(),h==="disabled"||h==="auth-required"||!y)await tt();else{for(let i of u?.moves??[])S({key:`move:${he(i)}`,run:()=>Mt(i)});S({run:et})}return Oe()},confirmMassDeletions(){return B.size&&(X=!0,Y=!1,B.clear(),ne.length=0,ue(),S({run:et})),Oe()},stop:xn};function wt(){a&&(C&&clearTimeout(C),C=setTimeout(()=>{C=null,S({run:Nt})},vo))}}import{createHash as Ao}from"node:crypto";function Rr(t){let e=t.replace(/\.md$/i,""),n=t.lastIndexOf("/"),s=n<0?"":t.slice(0,n);return{root:t,fdPrefix:`${e}.fd/`,assetPrefix:s?`${s}/.amadeus/`:".amadeus/"}}function Ir(t,e,n){return!!(e===t.root||e.startsWith(t.fdPrefix)||`${e}/`===t.fdPrefix||n==="binary"&&e.startsWith(t.assetPrefix)||n==="folder"&&(`${e}/`===t.assetPrefix||e.startsWith(t.assetPrefix)))}var Po=t=>Ao("sha256").update(t).digest("hex").slice(0,8),Do=t=>t.replace(/[\\/:*?"<>|]/g," ").trim().slice(0,40)||"shared",Pt="\u4E0E\u6211\u5171\u4EAB";function ln(t){let e=Po(`${t.vaultId}:${t.path}`),n=Rr(t.path),s=t.path.includes("/")?t.path.slice(0,t.path.lastIndexOf("/")):"";return{key:e,vaultId:t.vaultId,rootPath:t.path,title:t.title,localRelDir:`${Pt}/${Do(t.title)}-${e}`,serverDir:s,inScope:(r,o)=>Ir(n,r,o)}}function cn(){let t=de().readCreds(),e=Se(t.cloudUrl??"",t.token??""),n=new AbortController,s=()=>{let f=de().readCreds();if(n.signal.aborted||!e||Se(f.cloudUrl??"",f.token??"")!==e)throw Object.assign(new Error("Cloud account changed; retry from the current account"),{status:401});return f},r=()=>{let f=s();if(!f.cloudUrl||!f.token)throw Object.assign(new Error("\u672A\u767B\u5F55 Forsion \u8D26\u53F7"),{status:401});return f.cloudUrl.replace(/\/+$/,"")},o=async(f,u,y)=>{let _=s();if(!_.cloudUrl||!_.token)throw Object.assign(new Error("\u672A\u767B\u5F55 Forsion \u8D26\u53F7"),{status:401});let T=await fetch(`${_.cloudUrl.replace(/\/+$/,"")}/api/amadeus${u}`,{method:f,headers:{Authorization:`Bearer ${_.token}`,...y!==void 0?{"Content-Type":"application/json"}:{}},body:y!==void 0?JSON.stringify(y):void 0,signal:AbortSignal.any([n.signal,AbortSignal.timeout(2e4)])});if(!T.ok){let L=null;try{L=await T.json()}catch{}throw Object.assign(new Error(L?.detail||`http ${T.status}`),{status:T.status,code:L?.code})}let E=await T.json();return s(),E},a=null,c=async()=>(s(),a||(a=(await o("GET","/vaults")).vaults[0]?.id??"default",a)),l=()=>{try{let f=(s().token??"").split(".")[1],u=JSON.parse(Buffer.from(f.replace(/-/g,"+").replace(/_/g,"/"),"base64").toString());return typeof u.userId=="string"?u.userId:null}catch{return null}},m=async()=>(await o("GET","/shared-with-me")).items.map(u=>{let y=ln(u),_=u.path.split("/").pop()??u.path;return{...u,localPath:`${y.localRelDir}/${_}`}}),h=null;return{stop:()=>n.abort(),call:o,ensureOwnVault:c,myUserId:l,sharedWithMe:m,linkBase:async()=>{if(s(),h)return h;try{h=((await o("GET","/collab/link-base")).webOrigin??"").trim().replace(/\/+$/,"")||r()}catch{h=r()}return h},async heartbeat(f,u){let y=(f??"").replace(/\\/g,"/"),_,T=null,E=u.find(L=>y.startsWith(`${L.localRelDir}/`));E?(_=E.vaultId,T=E.serverDir?`${E.serverDir}/${y.slice(E.localRelDir.length+1)}`:y.slice(E.localRelDir.length+1)):(_=await c(),T=y||null),await o("POST",`/vaults/${encodeURIComponent(_)}/presence`,{page:T})}}}import{promises as Ar}from"node:fs";import $o from"node:path";var un=".forsion-vault.md",dn=t=>`${t}/${un}`;var ge=t=>t.replace(/\\/g,"/").normalize("NFC");function fn(t){let e=ge(t.path);return e?t.kind==="folder"?`${e}/`:t.kind==="page"?`${e.replace(/\.md$/i,"")}.fd/`:null:null}function Ke(t,e,n){let s=ge(n);if(!s)return!1;if(t.some(r=>ge(r.path)===s))return!0;for(let r of e??[]){let o=ge(r);if(!o)continue;let a=`${o.replace(/\.md$/i,"")}.fd`;if(s===o||s.startsWith(`${o}/`)||s===a||s.startsWith(`${a}/`))return!1}return t.some(r=>{let o=fn(r);return!!o&&s.startsWith(o)})}function hn(t,e,n){let s=ge(t),r=ge(e);return s===r?ge(n):s.startsWith(`${r}/`)?ge(n)+s.slice(r.length):null}function lt(t,e,n){let s=!1,r=t.map(o=>{let a=hn(o,e,n);return a===null?o:(s=!0,a)});return{changed:s,next:r}}async function Pr(t){let e=await Ar.readdir(t,{withFileTypes:!0}).catch(()=>[]),n=[];for(let s of e)!s.isDirectory()||s.name.startsWith(".")||await Ar.access($o.join(t,s.name,un)).then(()=>!0,()=>!1)&&n.push(s.name);return n.sort()}var ie={get:"amadeus:sync:get",setEnabled:"amadeus:sync:set-enabled",syncNow:"amadeus:sync:now",confirmDeletions:"amadeus:sync:confirm-deletions",status:"amadeus:sync:status",switchSide:"amadeus:sync:switch-side",collabCall:"amadeus:collab:call",presence:"amadeus:collab:presence",entryGet:"amadeus:entry-sync:get",entryEnable:"amadeus:entry-sync:enable",entryDisable:"amadeus:entry-sync:disable",entryClosure:"amadeus:entry-sync:closure",entryChange:"amadeus:entry-sync:change",otherSideDbs:"amadeus:entry-sync:other-side-dbs"};import{createHash as Mo}from"node:crypto";var Dt=t=>Mo("sha256").update(t).digest("hex").slice(0,8);function Dr(t){return t.replace(/ \(conflict \d{4}-\d{2}-\d{2} \d{4}\)(?=(?:\.[^./]+)?$)/,"")}function Me(t,e=[]){let n=[],s=[];for(let r of t){let o=ge(r.path);if(!o)continue;s.push(o);let a=fn(r);a&&n.push(a)}return{entries:t,exclude:e,prefixes:n,paths:s}}function $r(t,e){let n=Dr(ge(e));if(!n)return!1;if(Ke(t.entries,t.exclude,n))return!0;let s=`${n}/`;for(let r of t.paths)if(r.startsWith(s))return!0;for(let r of t.prefixes)if(r.startsWith(s))return!0;return!1}function ct(t,e,n){let s=!1,r=t.map(o=>{let a=hn(o.path,e,n);return a===null?o:(s=!0,{...o,path:a})});return{changed:s,next:r}}function Mr(t,e,n,s){if(e==="delete"||e==="delete-folder"){let r=ge(n),o=t.filter(a=>{let c=ge(a.path);return!(c===r||e==="delete-folder"&&c.startsWith(`${r}/`))});return{changed:o.length!==t.length,next:o}}return s?ct(t,n,s):{changed:!1,next:t}}function mn(t,e){let n=Ve(t);return!n||n!==t.normalize("NFC").trim()?"\u540D\u79F0\u4E0D\u5408\u6CD5":n.includes("/")?"\u540D\u79F0\u4E0D\u80FD\u5305\u542B /":n===Pt?`\u300C${Pt}\u300D\u662F\u4FDD\u7559\u540D\u79F0`:e.includes(n)?"\u8BE5\u540D\u79F0\u5DF2\u88AB\u5176\u4ED6\u667A\u5E93\u7684\u4E91\u540C\u6B65\u5360\u7528":null}var Nr=["setAmadeusSyncFactory","readCreds","accountId","homeDir"],pn=t=>Nr.every(e=>typeof t[e]=="function"),No=()=>({enabled:!1,state:"disabled",lastSyncAt:null,pending:0,conflicts:0,skipped:[],error:null,pendingDeletions:0,maxFileBytes:null,side:"local"});function gn(t){let e=null,n=()=>{if(!e)throw new Error("Cloud sync is not ready");return e};t.handle(ie.get,()=>e?e.get():No()),t.handle(ie.setEnabled,(s,r)=>n().setEnabled(r)),t.handle(ie.syncNow,()=>n().syncNow()),t.handle(ie.confirmDeletions,()=>n().confirmDeletions()),t.handle(ie.entryGet,()=>n().entryGet()),t.handle(ie.otherSideDbs,()=>n().otherSideDbs()),t.handle(ie.entryEnable,(s,r)=>n().entryEnable(r)),t.handle(ie.entryDisable,(s,r)=>n().entryDisable(r)),t.handle(ie.entryClosure,(s,r,o)=>n().entryClosure(r,o)),t.handle(ie.collabCall,(s,r,o)=>n().collabCall(r,o)),t.handle(ie.switchSide,(s,r)=>n().switchSide(s.sender.id,r)),t.setAmadeusSyncFactory(s=>{Gn(s);let r=Fr(s);return e=r.handlers,r.instance}),t.log("[forsion-extend] amadeus cloud sync registered")}function Fr(t){let e=t.notifyAll,n=()=>t.vaultRoot(),s=0,r=!1,o=cn(),a=new Map,c=()=>{let v=Date.now();for(let[C,w]of a)v-w.at>7e4&&a.delete(C);e(ie.presence,[...a.values()])},l={loadCreds:()=>t.readCreds(),onStatus:v=>e(ie.status,{...v,pendingDeletions:ne(),side:_()?"cloud":"local"}),onPresence:(v,C)=>{let w=C;w?.userId&&(a.set(w.userId,{userId:w.userId,username:String(w.username??"user"),page:w.page??null,at:Number(w.at)||Date.now()}),c())},onPresenceRoster:(v,C)=>{if(Array.isArray(C)){for(let w of C){let b=w;b?.userId&&a.set(b.userId,{userId:b.userId,username:String(b.username??"user"),page:b.page??null,at:Number(b.at)||Date.now()})}c()}}},m=()=>{let v=s;return{...l,onStatus:C=>{v===s&&l.onStatus(C)},onPresence:(C,w)=>{v===s&&l.onPresence(C,w)},onPresenceRoster:(C,w)=>{v===s&&l.onPresenceRoster(C,w)}}},h=at(m()),f=new Map,u=[],y=async()=>{if(!r||!fe())return;let v=s,C=o,w;try{w=await C.sharedWithMe()}catch{return}if(v!==s||!r)return;let b=w.map(S=>ln(S));u=b;let A=new Set(b.map(S=>S.key));for(let[S,x]of f)if(!A.has(S)){if(await x.engine.stop(),v!==s)return;f.delete(S)}for(let S of b){if(f.has(S.key))continue;let x=at(m(),{localRoot:je.join(De(),...S.localRelDir.split("/")),shadowName:`amadeus-sync-${rt()}-share-${S.key}`,vaultId:S.vaultId,serverDir:S.serverDir,inScope:S.inScope});f.set(S.key,{engine:x,plan:S}),x.start()}},_=()=>n()===De(),T=(v,C=v.base)=>{v.base=C;let w=[C,...v.pendingMoves];v.scope.current=Me(w.flatMap(b=>b.entries),w.flatMap(b=>b.exclude))},E=new Map,L=new Set,j=()=>{e(ie.entryChange)},te=async(v,C)=>{let w=E.get(v);if(!w)return;let b=x=>x&&x.startsWith(`${w.cloudName}/`)?x.slice(w.cloudName.length+1):null,A=b(C.path);if(!A)return;let S=!1;await qe(x=>{if(E.get(v)!==w)return!1;let D=(x.entrySync??[]).find(W=>W.vaultRoot===v);if(!D)return!1;let U=C.op,N=b(C.newPath),F=Mr(D.entries,U,A,N),V=N?lt(D.exclude??[],A,N):{changed:!1,next:D.exclude??[]};if(!F.changed&&!V.changed)return!1;S=!0,D.entries=F.next,V.changed&&(D.exclude=V.next),T(w,Me(D.entries,D.exclude??[]))}),S&&E.get(v)===w&&j()},G=v=>{let C=s;return{...m(),onStatus:w=>{C===s&&e(ie.status,{...w,pendingDeletions:ne(),side:"local",binding:v})},onRemoteApplied:async w=>{C===s&&await te(v,w)}}},B=async()=>{let v=fe();if(!r||!v)return;let C=s,w=o,b=rt(v);await t.adoptLegacyCloudState(v,kr);let A=await Ee(v),S=A.entrySync??[];if(C!==s||!r||v!==fe())return;let x=new Map(S.map(D=>[D.vaultRoot,D]));for(let[D,U]of E){let N=x.get(D);if(!(N&&N.cloudName===U.cloudName)&&(await U.engine.stop(),C!==s||(E.delete(D),N&&await _r(`amadeus-sync-${b}-entry-${Dt(D)}`),C!==s)))return}for(let D of S){let U=E.get(D.vaultRoot);if(U){T(U,Me(D.entries,D.exclude??[]));continue}let N={current:Me(D.entries,D.exclude??[])},F=D.cloudName,V=at(G(D.vaultRoot),{accountId:v,localRoot:D.vaultRoot,shadowName:`amadeus-sync-${b}-entry-${Dt(D.vaultRoot)}`,vaultId:"first",serverDir:F,clientIdSuffix:`entry-${Dt(D.vaultRoot)}`,requireRootExists:!0,ignoreNames:[".git","node_modules",".trash"],inScope:W=>W===F?!0:W.startsWith(`${F}/`)?$r(N.current,W.slice(F.length+1)):!1});E.set(D.vaultRoot,{engine:V,scope:N,cloudName:F,base:N.current,pendingMoves:new Set}),V.start()}if(A.cloudSync?.enabled!==!1)for(let D of S)L.has(D.cloudName)||(async()=>{try{let U=await w.ensureOwnVault();await w.call("PUT",`/vaults/${encodeURIComponent(U)}/file`,{path:dn(D.cloudName),content:"",baseSeq:0}),C===s&&L.add(D.cloudName)}catch(U){U?.status===409&&C===s&&L.add(D.cloudName)}})()},X=async(v,C,w,b,A)=>{let S=C.replace(/\\/g,"/").normalize("NFC"),x=w.replace(/\\/g,"/").normalize("NFC"),D=!1,U,N,F,V=A??"file";try{await qe(async W=>{if(E.get(v)!==b)return!1;let q=(W.entrySync??[]).find(oe=>oe.vaultRoot===v);if(!q)return!1;let Q=ct(q.entries,S,x),J=lt(q.exclude??[],S,x),we=Ke(q.entries,q.exclude,S);!A&&await Xe.stat(je.join(v,...x.split("/"))).then(oe=>oe.isDirectory(),()=>!1)&&(V="folder");let Fe=V==="folder"?"folder":/\.md$/i.test(x)?"page":"asset";we&&!Ke(Q.next,J.next,x)&&(Q.next.push({path:x,kind:Fe}),Q.changed=!0),D=Q.changed||J.changed;let Ue=q.entries.filter(oe=>ct([oe],S,x).changed);return we&&!Ue.some(oe=>oe.path===S)&&Ue.push({path:S,kind:Fe}),U=Me(Ue,(q.exclude??[]).filter(oe=>lt([oe],S,x).changed)),N=b.base,b.pendingMoves.add(U),q.entries=Q.next,q.exclude=J.next,F=Me(q.entries,q.exclude),T(b,F),D})}catch(W){throw U&&b.pendingMoves.delete(U),T(b,b.base===F&&N?N:b.base),W}try{U&&await b.engine.notifyLocalMove(S,x,()=>{b.pendingMoves.delete(U),T(b)},V)}catch(W){throw U&&b.pendingMoves.delete(U),await qe(q=>{let Q=q.entrySync?.find(J=>J.vaultRoot===v);if(!Q)return!1;Q.entries=ct(Q.entries,x,S).next,Q.exclude=lt(Q.exclude??[],x,S).next,T(b,Me(Q.entries,Q.exclude))}),W}D&&E.get(v)===b&&j()},Y=v=>{let C=v.replace(/\\/g,"/");for(let{engine:w,plan:b}of f.values())if(C.startsWith(`${b.localRelDir}/`))return{engine:w,rel:C.slice(b.localRelDir.length+1)};return{engine:h,rel:C}};t.setMutationHooks((v,C)=>{if(_()){let w=Y(v);w.engine.notifyLocal(w.rel,C);return}E.get(n()??"")?.engine.notifyLocal(v,C)},(v,C,w)=>{if(_()){let S=Y(v),x=Y(C);if(S.engine===x.engine)return S.engine.notifyLocalMove(S.rel,x.rel,void 0,w);S.engine.notifyLocal(S.rel,"remove"),x.engine.notifyLocal(x.rel,"write");return}let b=n()??"",A=E.get(b);if(A)return X(b,v,C,A,w)},(v,C)=>{if(_()){let w=Y(v),b=Y(C),A=[w.engine.holdLocalMove(w.rel,b.rel)];return w.engine!==b.engine&&A.push(b.engine.holdLocalMove(w.rel,b.rel)),()=>{for(let S of A)S()}}return E.get(n()??"")?.engine.holdLocalMove(v,C)});let ne=()=>{let v=h.getStatus().pendingDeletions;for(let{engine:C}of f.values())v+=C.getStatus().pendingDeletions;for(let{engine:C}of E.values())v+=C.getStatus().pendingDeletions;return v},ue=v=>({...v,pendingDeletions:ne(),side:_()?"cloud":"local"}),ut=()=>{if(!r)return Promise.resolve(h.getStatus());y();for(let{engine:v}of f.values())v.syncNow();for(let{engine:v}of E.values())v.syncNow();return h.syncNow()},Qe=async()=>{++s,r=!1,o.stop();let v=[h.stop(),...[...f.values()].map(({engine:w})=>w.stop()),...[...E.values()].map(({engine:w})=>w.stop())];f.clear(),E.clear(),u=[],L.clear(),a.clear(),c(),await Promise.all(v),await t.awaitPendingVaultWrites();let C=n();if(C&&St(C)){let w=await Ee(),b=w.localVault&&!St(w.localVault)?w.localVault:je.join(t.workspaceDir(),"Amadeus");await Xe.mkdir(b,{recursive:!0}),await Ae({lastVault:b,localVault:b,lastPage:void 0}),await t.activateRoot(b,!1)}j()};return{handlers:{get:()=>ue(h.getStatus()),setEnabled:async v=>{if(!r)throw new Error("Cloud account is changing");let C=s;return await h.setEnabled(v),C!==s?h.getStatus():(await Promise.all([...f.values(),...E.values()].map(({engine:w})=>w.restart())),ue(h.getStatus()))},syncNow:()=>ut(),confirmDeletions:()=>{for(let{engine:v}of f.values())v.confirmMassDeletions();for(let{engine:v}of E.values())v.confirmMassDeletions();return ue(h.confirmMassDeletions())},entryGet:async()=>{let v=await Ee(),C=De();return{vaults:v.entrySync??[],activeRoot:n(),cloudRoot:C,mirrorVaults:await Pr(C)}},otherSideDbs:async()=>{let v=n();if(!v)return null;let C=De(),w=await Ee(),b=v===C?w.localVault&&w.localVault!==C?w.localVault:null:C;if(!b)return null;let A=[],S=500,x=async(D,U)=>{if(A.length>=S)return;let N;try{N=await Xe.readdir(D,{withFileTypes:!0})}catch{return}for(let F of N){if(A.length>=S)break;if(F.name.startsWith(".")||F.isSymbolicLink())continue;let V=U?`${U}/${F.name}`:F.name;if(F.isDirectory())await x(je.join(D,F.name),V);else if(F.isFile()&&/\.db$/i.test(F.name))try{A.push({rel:V,source:await Xe.readFile(je.join(D,F.name),"utf8")})}catch{}}};return await x(b,""),{root:b,vaultName:b===C?"\u4E91\u7AEF":je.basename(b),dbs:A}},entryEnable:async v=>{let C=s,w=o;if(!r||!fe())return{error:"Sign in to enable cloud sync"};let b=n();if(!b||_())return{error:"\u4EC5\u672C\u5730 vault \u53EF\u5F00\u542F\u4E91\u540C\u6B65"};let A=await Ee(),S=A.entrySync??[],x=S.find(D=>D.vaultRoot===b);if(!x){let D=(v.cloudName??je.basename(b)).normalize("NFC").trim(),U=mn(D,S.map(N=>N.cloudName));if(U)return{error:U};if(!v.merge)try{let N=await w.ensureOwnVault(),F=await w.call("GET",`/vaults/${encodeURIComponent(N)}/tree`);if((F.folders??[]).some(W=>W===D||W.startsWith(`${D}/`))||(F.entries??[]).some(W=>W.path===D||W.path.startsWith(`${D}/`)))return{conflict:D}}catch(N){return{error:N?.message||"\u65E0\u6CD5\u8FDE\u63A5\u4E91\u7AEF(\u9996\u6B21\u5F00\u542F\u9700\u8981\u5728\u7EBF)"}}x={vaultRoot:b,cloudName:D,entries:[]},S.push(x),(async()=>{try{let N=await w.ensureOwnVault();await w.call("PUT",`/vaults/${encodeURIComponent(N)}/file`,{path:dn(x.cloudName),content:"",baseSeq:0})}catch{}})()}return C!==s||!r?{error:"Cloud account changed; retry from the current account"}:(await qe(D=>{if(C!==s||!r)return!1;let U=D.entrySync??[],N=U.find(J=>J.vaultRoot===b);if(!N){let J=mn(x.cloudName,U.map(we=>we.cloudName));if(J)throw new Error(J);N={vaultRoot:b,cloudName:x.cloudName,entries:[]},U.push(N)}let F=J=>String(J??"").replace(/\\/g,"/").normalize("NFC"),V=new Set;for(let J of v.entries??[]){let we=F(J.path);we&&(V.add(we),!N.entries.some(Fe=>Fe.path===we)&&N.entries.push({path:we,kind:J.kind==="folder"||J.kind==="asset"?J.kind:"page"}))}let W=(v.exclude??[]).map(F).filter(Boolean),q=new Set([...V,...(v.include??[]).map(F).filter(Boolean)]);N.exclude=[...new Set([...(N.exclude??[]).filter(J=>!q.has(J)),...W])];let Q=new Set(W);N.entries=N.entries.filter(J=>!Q.has(J.path)),D.entrySync=U,x=N},A.cloudAccountId),C!==s?{error:"Cloud account changed; retry from the current account"}:(await B(),E.get(b)?.engine.syncNow(),j(),{ok:!0,cloudName:x.cloudName}))},entryDisable:async v=>{let C=n(),w=!1,b=s;return await qe(A=>{if(b!==s||!r)return!1;let S=(A.entrySync??[]).find(U=>U.vaultRoot===C);if(!C||!S)return!1;let x=String(v??"").replace(/\\/g,"/").normalize("NFC"),D=S.entries.length;if(S.entries=S.entries.filter(U=>U.path!==x),Ke(S.entries,S.exclude,x))S.exclude=[...new Set([...S.exclude??[],x])];else if(S.entries.length===D)return!1;w=!0}),!w||b!==s?{ok:!1}:(await B(),j(),{ok:!0})},entryClosure:(v,C)=>t.relatedClosure(String(v??""),C==="folder"?"folder":"page"),collabCall:async(v,C)=>{let w=o,b=async()=>w.ensureOwnVault(),A=x=>String((C??[])[x]??""),S=x=>(C??[])[x]??{};switch(v){case"listVaults":return(await w.call("GET","/vaults")).vaults;case"activeVaultId":return b();case"pageShare":return w.call("GET",`/vaults/${encodeURIComponent(await b())}/page-shares?path=${encodeURIComponent(A(0))}`);case"createPageShare":return w.call("POST",`/vaults/${encodeURIComponent(await b())}/page-shares`,{path:A(0),...S(1)});case"updatePageShare":return w.call("PATCH",`/vaults/${encodeURIComponent(await b())}/page-shares/${encodeURIComponent(A(0))}`,S(1));case"revokePageShare":return w.call("DELETE",`/vaults/${encodeURIComponent(await b())}/page-shares/${encodeURIComponent(A(0))}`);case"setParticipantRole":return w.call("PATCH",`/vaults/${encodeURIComponent(await b())}/page-shares/${encodeURIComponent(A(0))}/members/${encodeURIComponent(A(1))}`,{role:A(2)});case"removeParticipant":return w.call("DELETE",`/vaults/${encodeURIComponent(await b())}/page-shares/${encodeURIComponent(A(0))}/members/${encodeURIComponent(A(1))}`);case"sharedWithMe":{let x=await w.sharedWithMe();return y(),x}case"leaveShare":{let x=w.myUserId();if(!x)throw new Error("\u672A\u767B\u5F55");return w.call("DELETE",`/vaults/${encodeURIComponent(await b())}/page-shares/${encodeURIComponent(A(0))}/members/${encodeURIComponent(x)}`)}case"publishes":return w.call("GET",`/vaults/${encodeURIComponent(await b())}/shares`);case"listAllShares":{let x=(await w.call("GET","/vaults")).vaults||[],D=w.myUserId(),U=[],N=[];for(let F of x){try{let V=await w.call("GET",`/vaults/${encodeURIComponent(F.id)}/shares`);for(let W of V.shares||[])U.push({...W,vaultId:F.id,vaultName:F.name||""})}catch(V){t.log(`[connect] listAllShares publishes vault ${F.id} failed: ${V?.message}`)}try{let V=await w.call("GET",`/vaults/${encodeURIComponent(F.id)}/page-shares`),W=V?.shares||V?.pageShares||(Array.isArray(V)?V:[]);for(let q of W){let Q=q.created_by??q.createdBy;(!D||!Q||Q===D)&&N.push({...q,vaultId:F.id,vaultName:F.name||""})}}catch(V){t.log(`[connect] listAllShares pageShares vault ${F.id} failed: ${V?.message}`)}}return{publishes:U,pageShares:N,linkBase:await w.linkBase()}}case"createPublish":{let x=await w.call("POST",`/vaults/${encodeURIComponent(await b())}/shares`,{mode:A(0),path:A(1)});return{...x,url:`${await w.linkBase()}/share/${x.token}`}}case"revokePublish":return w.call("DELETE",`/vaults/${encodeURIComponent(await b())}/shares/${encodeURIComponent(A(0))}`);case"revokePublishIn":return w.call("DELETE",`/vaults/${encodeURIComponent(A(0))}/shares/${encodeURIComponent(A(1))}`);case"revokePageShareIn":return w.call("DELETE",`/vaults/${encodeURIComponent(A(0))}/page-shares/${encodeURIComponent(A(1))}`);case"myUserId":return w.myUserId();case"linkBase":return w.linkBase();case"heartbeat":return w.heartbeat((C??[])[0]??null,u);default:throw new Error(`unknown collab fn: ${v}`)}},switchSide:async(v,C)=>{let w=await Ee();if(C==="cloud"){if(!r||!fe())throw new Error("Sign in to open cloud notes");let S=De();await Xe.mkdir(S,{recursive:!0}),w.lastVault&&!St(w.lastVault)&&await Ae({localVault:w.lastVault}),await Ae({lastVault:S});let x=await t.activateRoot(S,!1);return t.bindRenderer(v,S),{...x,side:"cloud"}}let b=w.localVault&&await Xe.stat(w.localVault).then(S=>S.isDirectory()).catch(()=>!1)?w.localVault:null;if(!b){let S=await t.ensureDefaultVault();return t.bindRenderer(v,S.root),{...S,side:"local"}}await Ae({lastVault:b});let A=await t.activateRoot(b,!1);return t.bindRenderer(v,b),{...A,side:"local"}}},instance:{start:()=>{r=!0,h.start(),y(),B()},stopAllSync:Qe,restartAllSync:async()=>{await Qe(),o=cn(),h=at(m()),r=!0,await Promise.all([h.restart(),y(),B()]),j(),e(ie.status,ue(h.getStatus()))}}}}var Fo=["membership","credits"];function va(t){let e={status:0,error:"untrusted"},n={ok:!1,error:"untrusted"};t.handle("auth:openAccountCenter",async(r,o)=>{if(!t.isTrustedSender(r))return n;let{base:a,token:c}=await t.getCloud();if(!a)return{ok:!1};let l=o&&/^[a-z0-9-]+$/i.test(o)?`#${o}`:"",m=`${a}/account${c?`?token=${encodeURIComponent(c)}`:""}${l}`;return await t.openExternal(m),{ok:!0}}),t.handle("auth:openPayCenter",async(r,o)=>{if(!t.isTrustedSender(r))return n;if(o!==void 0&&!Fo.includes(o))return{ok:!1,error:"invalid_tab"};let{base:a,token:c}=await t.getCloud();if(!a)return{ok:!1};let l=`${a}/pay?tab=${o??"membership"}${c?`&token=${encodeURIComponent(c)}`:""}&redirect=${encodeURIComponent(`${a}/account`)}`;return await t.openExternal(l),{ok:!0}});let s=()=>t.getCloud();t.handle("account:quota",async r=>{if(!t.isTrustedSender(r))return e;let o=await s();if(!o.token)return{status:401,json:null};try{return await me(o,"GET","/api/token-quota/my",void 0,15e3)}catch(a){return{status:0,json:{detail:String(a?.message||a)}}}}),t.handle("account:useResetCard",async(r,o)=>{if(!t.isTrustedSender(r))return e;let a=await s();if(!a.token)return{status:401,json:null};if(o!==void 0&&o!=="both")return{status:400,json:{error:"invalid_type",detail:`invalid reset card type: ${o}`}};let c=o??"both";try{return await me(a,"POST","/api/token-quota/reset-card/use",{type:c},15e3)}catch(l){return{status:0,json:{detail:String(l?.message||l)}}}}),t.handle("account:bgConvert",async(r,o)=>{if(!t.isTrustedSender(r))return e;let a=await s();if(!a.token)return{status:401,json:null};if(!Number.isInteger(o)||o<1||o>100)return{status:400,json:{error:"invalid_percent"}};try{return await me(a,"POST","/api/token-quota/background/convert",{percent:o},15e3)}catch(c){return{status:0,json:{detail:String(c?.message||c)}}}}),t.handle("account:bgAutoMain",async(r,o)=>{if(!t.isTrustedSender(r))return e;let a=await s();if(!a.token)return{status:401,json:null};if(typeof o!="boolean")return{status:400,json:{error:"invalid_request"}};try{return await me(a,"POST","/api/token-quota/background/auto-main",{enabled:o},15e3)}catch(c){return{status:0,json:{detail:String(c?.message||c)}}}}),t.handle("feedback:submit",async(r,o)=>{let{base:a,token:c}=await t.getCloud();if(!a||!c)return{ok:!1,error:"not-logged-in"};let l=(o?.description||"").trim();if(!l)return{ok:!1,error:"empty"};if(l.length>1e4)return{ok:!1,error:"description-too-long"};let m=[],h=!1;if(o?.sessionLogJson){let f=Buffer.from(o.sessionLogJson,"utf8");if(f.length>5*1024*1024)return{ok:!1,error:"attachment-too-large"};m.push({filename:o.sessionLogName||"tangu-session.json",mime_type:"application/json",size:f.length,data_base64:f.toString("base64")})}try{let f=await fetch(`${a}/api/feedback`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({description:l,attachments:m}),signal:AbortSignal.timeout(2e4)});if(!f.ok){let y=`HTTP ${f.status}`;try{y=(await f.json())?.detail||y}catch{}return{ok:!1,error:y}}return{ok:!0,id:(await f.json().catch(()=>({})))?.id??null,attachmentSkipped:h}}catch(f){return{ok:!1,error:f?.message||String(f)}}}),t.handle("cloud:fetch",async(r,o)=>{if(!t.isTrustedSender(r))return{status:0,error:"untrusted"};let a=o??{},c=typeof a.path=="string"?a.path:"",l=Math.min(12e4,Math.max(1e3,Number(a.timeoutMs)||15e3)),m=typeof a.method=="string"?a.method.toUpperCase():"GET";if(!/^(GET|POST|PUT|PATCH|DELETE)$/.test(m))return{status:0,error:"bad_method"};if(!c.startsWith("/"))return{status:0,error:"bad_path"};let{base:h,token:f}=await t.getCloud();if(!String(h||""))return{status:0,error:"no_cloud_url"};let u=Tn(h,c);if(!u)return{status:0,error:"bad_path"};if(!f)return{status:401,error:"not_signed_in"};let y=a.body!==void 0&&m!=="GET"&&m!=="DELETE",_=new AbortController,T=setTimeout(()=>_.abort(),l);try{let E=await fetch(u,{method:m,headers:{Authorization:`Bearer ${f}`,...y?{"Content-Type":"application/json"}:{}},body:y?JSON.stringify(a.body):void 0,signal:_.signal});return{status:E.status,json:await E.json().catch(()=>null)}}catch(E){return{status:0,error:String(E?.message||E)}}finally{clearTimeout(T)}}),t.log("[forsion-extend] cloud account handlers registered"),jt(t)?Ut(t):t.log("[forsion-extend] host has no Connect seam (projectsRoot / transpileForServe / mimeOf / setPreviewHooks); Connect stays with the host"),zt(t)?qt(t):t.log("[forsion-extend] host has no remote-sync seam (registerRemoteSyncBackend / readCreds); penzor stays with the host"),Bt(t)?Vt(t):t.log("[forsion-extend] host has no account seam (accountCommit / accountClear / \u2026); account core stays with the host"),pn(t)?gn(t):t.log("[forsion-extend] host has no amadeus seam (setAmadeusSyncFactory); cloud sync stays with the host")}export{Vn as ACCOUNT_SEAM,Nr as AMADEUS_SEAM,Ot as CONNECT_MAX_FILES,In as CONNECT_MAX_FILE_BYTES,An as CONNECT_MAX_TOTAL_BYTES,Fn as FORSION_CONNECT_LOCAL_SDK,Fo as PAY_TABS,Un as PENZOR_MAX_FILE,ie as SYNC_IPC,me as cloudJson,Pn as collectProjectFiles,It as conflictCopyPath,lo as conflictCopyVariant,Bn as createAccountCloud,Fr as createAmadeusCloud,jn as createPenzorRemote,Ht as expectedPartsOf,Se as forsionAccountId,Wn as forsionRefreshToken,nt as forsionWhoami,Bt as hasAccountHost,pn as hasAmadeusHost,jt as hasConnectHost,zt as hasRemoteSyncHost,Nn as makePreviewProxy,$n as readConnectMeta,Vt as registerAccount,gn as registerAmadeus,va as registerCloud,Ut as registerConnect,qt as registerPenzor,qn as shouldRefreshToken,Dr as stripConflictSuffix,co as textFingerprint,zn as tokenAgeMs,us as tokenRemainingMs,Mn as writeConnectMeta};
200
+ /*! Bundled license information:
201
+
202
+ chokidar/index.js:
203
+ (*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
204
+ */
package/dist/main.js CHANGED
@@ -1 +1,179 @@
1
- "use strict";(()=>{})();
1
+ "use strict";(()=>{var qe,T,Tt,Kn,ae,Pt,It,Rt,Ze,Te,ye,Lt,ot,et,tt,Dt,Le={},De=[],jn=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,Ne=Array.isArray;function ee(t,e){for(var n in e)t[n]=e[n];return t}function rt(t){t&&t.parentNode&&t.parentNode.removeChild(t)}function Yn(t,e,n){var r,a,i,s={};for(i in e)i=="key"?r=e[i]:i=="ref"?a=e[i]:s[i]=e[i];if(arguments.length>2&&(s.children=arguments.length>3?qe.call(arguments,2):n),typeof t=="function"&&t.defaultProps!=null)for(i in t.defaultProps)s[i]===void 0&&(s[i]=t.defaultProps[i]);return Ie(t,s,r,a,null)}function Ie(t,e,n,r,a){var i={type:t,props:e,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:a??++Tt,__i:-1,__u:0};return a==null&&T.vnode!=null&&T.vnode(i),i}function R(t){return t.children}function Re(t,e){this.props=t,this.context=e}function de(t,e){if(e==null)return t.__?de(t.__,t.__i+1):null;for(var n;e<t.__k.length;e++)if((n=t.__k[e])!=null&&n.__e!=null)return n.__e;return typeof t.type=="function"?de(t):null}function Qn(t){if(t.__P&&t.__d){var e=t.__v,n=e.__e,r=[],a=[],i=ee({},e);i.__v=e.__v+1,T.vnode&&T.vnode(i),at(t.__P,i,e,t.__n,t.__P.namespaceURI,32&e.__u?[n]:null,r,n??de(e),!!(32&e.__u),a),i.__v=e.__v,i.__.__k[i.__i]=i,zt(r,i,a),e.__e=e.__=null,i.__e!=n&&Ft(i)}}function Ft(t){if((t=t.__)!=null&&t.__c!=null)return t.__e=t.__c.base=null,t.__k.some(function(e){if(e!=null&&e.__e!=null)return t.__e=t.__c.base=e.__e}),Ft(t)}function nt(t){(!t.__d&&(t.__d=!0)&&ae.push(t)&&!Fe.__r++||Pt!=T.debounceRendering)&&((Pt=T.debounceRendering)||It)(Fe)}function Fe(){try{for(var t,e=1;ae.length;)ae.length>e&&ae.sort(Rt),t=ae.shift(),e=ae.length,Qn(t)}finally{ae.length=Fe.__r=0}}function qt(t,e,n,r,a,i,s,l,u,d,m){var f,c,g,h,x,w,_=r&&r.__k||De,p=e.length;for(u=Gn(n,e,_,u,p),f=0;f<p;f++)(g=n.__k[f])!=null&&(c=g.__i!=-1&&_[g.__i]||Le,g.__i=f,w=at(t,g,c,a,i,s,l,u,d,m),h=g.__e,g.ref&&c.ref!=g.ref&&(c.ref&&it(c.ref,null,g),m.push(g.ref,g.__c||h,g)),x==null&&h!=null&&(x=h),4&g.__u?(u=Nt(g,u,t),c.__e&&(c.__e=null)):typeof g.type=="function"&&w!==void 0?u=w:h&&(u=h.nextSibling),g.__u&=-7);return n.__e=x,u}function Gn(t,e,n,r,a){var i,s,l,u,d,m=n.length,f=m,c=0;for(t.__k=new Array(a),i=0;i<a;i++)(s=e[i])!=null&&typeof s!="boolean"&&typeof s!="function"?(typeof s=="string"||typeof s=="number"||typeof s=="bigint"||s.constructor==String?s=t.__k[i]=Ie(null,s,null,null,null):Ne(s)?s=t.__k[i]=Ie(R,{children:s},null,null,null):s.constructor===void 0&&s.__b>0?s=t.__k[i]=Ie(s.type,s.props,s.key,s.ref?s.ref:null,s.__v):t.__k[i]=s,u=i+c,s.__=t,s.__b=t.__b+1,l=null,(d=s.__i=Zn(s,n,u,f))!=-1&&(f--,(l=n[d])&&(l.__u|=2)),l==null||l.__v==null?(d==-1&&(a>m?c--:a<m&&c++),typeof s.type!="function"&&(s.__u|=4)):d!=u&&(d==u-1?c--:d==u+1?c++:(d>u?c--:c++,s.__u|=4))):t.__k[i]=null;if(f)for(i=0;i<m;i++)(l=n[i])!=null&&(2&l.__u)==0&&(l.__e==r&&(r=de(l)),Ot(l,l));return r}function Nt(t,e,n){var r,a;if(typeof t.type=="function"){for(r=t.__k,a=0;r&&a<r.length;a++)r[a]&&(r[a].__=t,e=Nt(r[a],e,n));return e}t.__e!=e&&(e&&t.type&&!e.parentNode&&(e=de(t)),e=n.insertBefore(t.__e,e||null));do e=e&&e.nextSibling;while(e!=null&&e.nodeType==8);return e}function Zn(t,e,n,r){var a,i,s,l=t.key,u=t.type,d=e[n],m=d!=null&&(2&d.__u)==0;if(d===null&&l==null||m&&l==d.key&&u==d.type)return n;if(r>(m?1:0)){for(a=n-1,i=n+1;a>=0||i<e.length;)if((d=e[s=a>=0?a--:i++])!=null&&(2&d.__u)==0&&l==d.key&&u==d.type)return s}return-1}function Mt(t,e,n){e[0]=="-"?t.setProperty(e,n??""):t[e]=n==null?"":typeof n!="number"||jn.test(e)?n:n+"px"}function Ee(t,e,n,r,a){var i,s;e:if(e=="style")if(typeof n=="string")t.style.cssText=n;else{if(typeof r=="string"&&(t.style.cssText=r=""),r)for(e in r)n&&e in n||Mt(t.style,e,"");if(n)for(e in n)r&&n[e]==r[e]||Mt(t.style,e,n[e])}else if(e[0]=="o"&&e[1]=="n")i=e!=(e=e.replace(Lt,"$1")),s=e.toLowerCase(),e=s in t||e=="onFocusOut"||e=="onFocusIn"?s.slice(2):e.slice(2),t.l||(t.l={}),t.l[e+i]=n,n?r?n[ye]=r[ye]:(n[ye]=ot,t.addEventListener(e,i?tt:et,i)):t.removeEventListener(e,i?tt:et,i);else{if(a=="http://www.w3.org/2000/svg")e=e.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(e!="width"&&e!="height"&&e!="href"&&e!="list"&&e!="form"&&e!="tabIndex"&&e!="download"&&e!="rowSpan"&&e!="colSpan"&&e!="role"&&e!="popover"&&e in t)try{t[e]=n??"";break e}catch{}typeof n=="function"||(n==null||n===!1&&e[4]!="-"?t.removeAttribute(e):t.setAttribute(e,e=="popover"&&n==1?"":n))}}function Et(t){return function(e){if(this.l){var n=this.l[e.type+t];if(e[Te]==null)e[Te]=ot++;else if(e[Te]<n[ye])return;return n(T.event?T.event(e):e)}}}function at(t,e,n,r,a,i,s,l,u,d){var m,f,c,g,h,x,w,_,p,b,y,C,E,F,O,re,H=e.type;if(e.constructor!==void 0)return null;128&n.__u&&(u=!!(32&n.__u),i=[l=e.__e=n.__e]),(m=T.__b)&&m(e);e:if(typeof H=="function"){f=s.length;try{if(p=e.props,b=H.prototype&&H.prototype.render,y=(m=H.contextType)&&r[m.__c],C=m?y?y.props.value:m.__:r,n.__c?_=(c=e.__c=n.__c).__=c.__E:(b?e.__c=c=new H(p,C):(e.__c=c=new Re(p,C),c.constructor=H,c.render=to),y&&y.sub(c),c.state||(c.state={}),c.__n=r,g=c.__d=!0,c.__h=[],c._sb=[]),b&&c.__s==null&&(c.__s=c.state),b&&H.getDerivedStateFromProps!=null&&(c.__s==c.state&&(c.__s=ee({},c.__s)),ee(c.__s,H.getDerivedStateFromProps(p,c.__s))),h=c.props,x=c.state,c.__v=e,g)b&&H.getDerivedStateFromProps==null&&c.componentWillMount!=null&&c.componentWillMount(),b&&c.componentDidMount!=null&&c.__h.push(c.componentDidMount);else{if(b&&H.getDerivedStateFromProps==null&&p!==h&&c.componentWillReceiveProps!=null&&c.componentWillReceiveProps(p,C),e.__v==n.__v||!c.__e&&c.shouldComponentUpdate!=null&&c.shouldComponentUpdate(p,c.__s,C)===!1){e.__v!=n.__v&&(c.props=p,c.state=c.__s,c.__d=!1),e.__e=n.__e,e.__k=n.__k,e.__k.some(function(Z){Z&&(Z.__=e)}),De.push.apply(c.__h,c._sb),c._sb=[],c.__h.length&&s.push(c),l=de(n);break e}c.componentWillUpdate!=null&&c.componentWillUpdate(p,c.__s,C),b&&c.componentDidUpdate!=null&&c.__h.push(function(){c.componentDidUpdate(h,x,w)})}if(c.context=C,c.props=p,c.__P=t,c.__e=!1,E=T.__r,F=0,b)c.state=c.__s,c.__d=!1,E&&E(e),m=c.render(c.props,c.state,c.context),De.push.apply(c.__h,c._sb),c._sb=[];else do c.__d=!1,E&&E(e),m=c.render(c.props,c.state,c.context),c.state=c.__s;while(c.__d&&++F<25);c.state=c.__s,c.getChildContext!=null&&(r=ee(ee({},r),c.getChildContext())),b&&!g&&c.getSnapshotBeforeUpdate!=null&&(w=c.getSnapshotBeforeUpdate(h,x)),O=m!=null&&m.type===R&&m.key==null?Ut(m.props.children):m,l=qt(t,Ne(O)?O:[O],e,n,r,a,i,s,l,u,d),c.base=e.__e,e.__u&=-161,c.__h.length&&s.push(c),_&&(c.__E=c.__=null)}catch(Z){if(s.length=f,e.__v=null,u||i!=null){if(Z.then){for(e.__u|=u?160:128;l&&l.nodeType==8&&l.nextSibling;)l=l.nextSibling;i!=null&&(i[i.indexOf(l)]=null),e.__e=l}else if(i!=null)for(re=i.length;re--;)rt(i[re])}else e.__e=n.__e;e.__k==null&&(e.__k=n.__k||[]),Z.then||Bt(e),T.__e(Z,e,n)}}else i==null&&e.__v==n.__v?(e.__k=n.__k,e.__e=n.__e):l=e.__e=eo(n.__e,e,n,r,a,i,s,u,d);return(m=T.diffed)&&m(e),128&e.__u?void 0:l}function Bt(t){t&&(t.__c&&(t.__c.__e=!0),t.__k&&t.__k.some(Bt))}function zt(t,e,n){for(var r=0;r<n.length;r++)it(n[r],n[++r],n[++r]);T.__c&&T.__c(e,t),t.some(function(a){try{t=a.__h,a.__h=[],t.some(function(i){i.call(a)})}catch(i){T.__e(i,a.__v)}})}function Ut(t){return typeof t!="object"||t==null||t.__b>0?t:Ne(t)?t.map(Ut):t.constructor!==void 0?null:ee({},t)}function eo(t,e,n,r,a,i,s,l,u){var d,m,f,c,g,h,x,w=n.props||Le,_=e.props,p=e.type;if(p=="svg"?a="http://www.w3.org/2000/svg":p=="math"?a="http://www.w3.org/1998/Math/MathML":a||(a="http://www.w3.org/1999/xhtml"),i!=null){for(d=0;d<i.length;d++)if((g=i[d])&&"setAttribute"in g==!!p&&(p?g.localName==p:g.nodeType==3)){t=g,i[d]=null;break}}if(t==null){if(p==null)return document.createTextNode(_);t=document.createElementNS(a,p,_.is&&_),l&&(T.__m&&T.__m(e,i),l=!1),i=null}if(p==null)w===_||l&&t.data==_||(t.data=_);else{if(i=p=="textarea"&&_.defaultValue!=null?null:i&&qe.call(t.childNodes),!l&&i!=null)for(w={},d=0;d<t.attributes.length;d++)w[(g=t.attributes[d]).name]=g.value;for(d in w)g=w[d],d=="dangerouslySetInnerHTML"?f=g:d=="children"||d in _||d=="value"&&"defaultValue"in _||d=="checked"&&"defaultChecked"in _||Ee(t,d,null,g,a);for(d in _)g=_[d],d=="children"?c=g:d=="dangerouslySetInnerHTML"?m=g:d=="value"?h=g:d=="checked"?x=g:l&&typeof g!="function"||w[d]===g||Ee(t,d,g,w[d],a);if(m)l||f&&(m.__html==f.__html||m.__html==t.innerHTML)||(t.innerHTML=m.__html),e.__k=[];else if(f&&(t.innerHTML=""),qt(e.type=="template"?t.content:t,Ne(c)?c:[c],e,n,r,p=="foreignObject"?"http://www.w3.org/1999/xhtml":a,i,s,i?i[0]:n.__k&&de(n,0),l,u),i!=null)for(d=i.length;d--;)rt(i[d]);l&&p!="textarea"||(d="value",p=="progress"&&h==null?t.removeAttribute("value"):h!=null&&(h!==t[d]||p=="progress"&&!h||p=="option"&&h!=w[d])&&Ee(t,d,h,w[d],a),d="checked",x!=null&&x!=t[d]&&Ee(t,d,x,w[d],a))}return t}function it(t,e,n){try{if(typeof t=="function"){var r=typeof t.__u=="function";r&&t.__u(),r&&e==null||(t.__u=t(e))}else t.current=e}catch(a){T.__e(a,n)}}function Ot(t,e,n){var r,a;if(T.unmount&&T.unmount(t),(r=t.ref)&&(r.current&&r.current!=t.__e||it(r,null,e)),(r=t.__c)!=null){if(r.componentWillUnmount)try{r.componentWillUnmount()}catch(i){T.__e(i,e)}r.base=r.__P=r.__n=null}if(r=t.__k)for(a=0;a<r.length;a++)r[a]&&Ot(r[a],e,n||typeof t.type!="function");n||rt(t.__e),t.__c=t.__=t.__e=void 0}function to(t,e,n){return this.constructor(t,n)}function st(t,e,n){var r,a,i,s;e==document&&(e=document.documentElement),T.__&&T.__(t,e),a=(r=typeof n=="function")?null:n&&n.__k||e.__k,i=[],s=[],at(e,t=(!r&&n||e).__k=Yn(R,null,[t]),a||Le,Le,e.namespaceURI,!r&&n?[n]:a?null:e.firstChild?qe.call(e.childNodes):null,i,!r&&n?n:a?a.__e:e.firstChild,r,s),zt(i,t,s),t.props.children=null}function Ht(t){function e(n){var r,a;return this.getChildContext||(r=new Set,(a={})[e.__c]=this,this.getChildContext=function(){return a},this.componentWillUnmount=function(){r=null},this.shouldComponentUpdate=function(i){this.props.value!=i.value&&r.forEach(function(s){s.__e=!0,nt(s)})},this.sub=function(i){r.add(i);var s=i.componentWillUnmount;i.componentWillUnmount=function(){r&&r.delete(i),s&&s.call(i)}}),n.children}return e.__c="__cC"+Dt++,e.__=t,e.Provider=e.__l=(e.Consumer=function(n,r){return n.children(r)}).contextType=e,e}qe=De.slice,T={__e:function(t,e,n,r){for(var a,i,s;e=e.__;)if((a=e.__c)&&!a.__)try{if((i=a.constructor)&&i.getDerivedStateFromError!=null&&(a.setState(i.getDerivedStateFromError(t)),s=a.__d),a.componentDidCatch!=null&&(a.componentDidCatch(t,r||{}),s=a.__d),s)return a.__E=a}catch(l){t=l}throw t}},Tt=0,Kn=function(t){return t!=null&&t.constructor===void 0},Re.prototype.setState=function(t,e){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=ee({},this.state),typeof t=="function"&&(t=t(ee({},n),this.props)),t&&ee(n,t),t!=null&&this.__v&&(e&&this._sb.push(e),nt(this))},Re.prototype.forceUpdate=function(t){this.__v&&(this.__e=!0,t&&this.__h.push(t),nt(this))},Re.prototype.render=R,ae=[],It=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,Rt=function(t,e){return t.__v.__b-e.__v.__b},Fe.__r=0,Ze=Math.random().toString(8),Te="__d"+Ze,ye="__a"+Ze,Lt=/(PointerCapture)$|Capture$/i,ot=0,et=Et(!1),tt=Et(!0),Dt=0;var be,q,lt,$t,_e=0,Qt=[],z=T,Xt=z.__b,Wt=z.__r,Vt=z.diffed,Jt=z.__c,Kt=z.unmount,jt=z.__;function ze(t,e){z.__h&&z.__h(q,t,_e||e),_e=0;var n=q.__H||(q.__H={__:[],__h:[]});return t>=n.__.length&&n.__.push({}),n.__[t]}function v(t){return _e=1,no(en,t)}function no(t,e,n){var r=ze(be++,2);if(r.t=t,!r.__c&&(r.__=[n?n(e):en(void 0,e),function(l){var u=r.__N?r.__N[0]:r.__[0],d=r.t(u,l);u!==d&&(r.__N=[d,r.__[1]],r.__c.setState({}))}],r.__c=q,!q.__f)){var a=function(l,u,d){if(!r.__c.__H)return!0;var m=!1,f=r.__c.props!==l;if(r.__c.__H.__.some(function(g){if(g.__N){m=!0;var h=g.__[0];g.__=g.__N,g.__N=void 0,h!==g.__[0]&&(f=!0)}}),i){var c=i.call(this,l,u,d);return m?c||f:c}return!m||f};q.__f=!0;var i=q.shouldComponentUpdate,s=q.componentWillUpdate;q.componentWillUpdate=function(l,u,d){if(this.__e){var m=i;i=void 0,a(l,u,d),i=m}s&&s.call(this,l,u,d)},q.shouldComponentUpdate=a}return r.__N||r.__}function N(t,e){var n=ze(be++,3);!z.__s&&Zt(n.__H,e)&&(n.__=t,n.u=e,q.__H.__h.push(n))}function $(t){return _e=5,ve(function(){return{current:t}},[])}function ve(t,e){var n=ze(be++,7);return Zt(n.__H,e)&&(n.__=t(),n.__H=e,n.__h=t),n.__}function ie(t,e){return _e=8,ve(function(){return t},e)}function Gt(t){var e=q.context[t.__c],n=ze(be++,9);return n.c=t,e?(n.__==null&&(n.__=!0,e.sub(q)),e.props.value):t.__}function oo(){for(var t;t=Qt.shift();){var e=t.__H;if(t.__P&&e)try{e.__h.some(Be),e.__h.some(ct),e.__h=[]}catch(n){e.__h=[],z.__e(n,t.__v)}}}z.__b=function(t){q=null,Xt&&Xt(t)},z.__=function(t,e){t&&e.__k&&e.__k.__m&&(t.__m=e.__k.__m),jt&&jt(t,e)},z.__r=function(t){Wt&&Wt(t),be=0;var e=(q=t.__c).__H;e&&(lt===q?(e.__h=[],q.__h=[],e.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(e.__h.some(Be),e.__h.some(ct),e.__h=[],be=0)),lt=q},z.diffed=function(t){Vt&&Vt(t);var e=t.__c;e&&e.__H&&(e.__H.__h.length&&(Qt.push(e)!==1&&$t===z.requestAnimationFrame||(($t=z.requestAnimationFrame)||ro)(oo)),e.__H.__.some(function(n){n.u&&(n.__H=n.u,n.u=void 0)})),lt=q=null},z.__c=function(t,e){e.some(function(n){try{n.__h.some(Be),n.__h=n.__h.filter(function(r){return!r.__||ct(r)})}catch(r){e.some(function(a){a.__h&&(a.__h=[])}),e=[],z.__e(r,n.__v)}}),Jt&&Jt(t,e)},z.unmount=function(t){Kt&&Kt(t);var e,n=t.__c;n&&n.__H&&(n.__H.__.some(function(r){try{Be(r)}catch(a){e=a}}),n.__H=void 0,e&&z.__e(e,n.__v))};var Yt=typeof requestAnimationFrame=="function";function ro(t){var e,n=function(){clearTimeout(r),Yt&&cancelAnimationFrame(e),setTimeout(t)},r=setTimeout(n,35);Yt&&(e=requestAnimationFrame(n))}function Be(t){var e=q,n=t.__c;typeof n=="function"&&(t.__c=void 0,n()),q=e}function ct(t){var e=q;t.__c=t.__(),q=e}function Zt(t,e){return!t||t.length!==e.length||e.some(function(n,r){return n!==t[r]})}function en(t,e){return typeof e=="function"?e(t):e}var ao={"page.account":"\u8D26\u53F7","page.quota":"\u989D\u5EA6\u4E0E\u79EF\u5206","page.security":"\u5B89\u5168","page.usage":"\u7528\u91CF\u8BB0\u5F55","page.feedback":"\u53CD\u9988","common.cancel":"\u53D6\u6D88","common.copied":"\u5DF2\u590D\u5236","common.copyFailed":"\u590D\u5236\u5931\u8D25","common.done":"\u5B8C\u6210","common.loadFailed":"\u6CA1\u80FD\u52A0\u8F7D","common.loadMore":"\u52A0\u8F7D\u66F4\u591A","common.loading":"\u52A0\u8F7D\u4E2D\u2026","common.openInBrowser":"\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00","common.retry":"\u91CD\u8BD5","common.save":"\u4FDD\u5B58","common.thisWeek":"\u672C\u5468","common.today":"\u4ECA\u65E5","common.unlimited":"\u4E0D\u9650","signin.button":"\u767B\u5F55 Forsion","signin.desc":"\u767B\u5F55 Forsion \u8D26\u53F7\u540E\uFF0C\u53EF\u4EE5\u5728\u8FD9\u91CC\u7BA1\u7406\u8D26\u53F7\u3001\u989D\u5EA6\u3001\u5B89\u5168\u4E0E\u53CD\u9988\u3002","signin.pending":"\u7B49\u5F85\u5728\u6D4F\u89C8\u5668\u4E2D\u5B8C\u6210\u767B\u5F55\u2026","signin.deviceHint":"\u6D4F\u89C8\u5668\u4F1A\u81EA\u52A8\u6253\u5F00\u767B\u5F55\u9875\uFF1B\u6CA1\u6709\u6253\u5F00\u7684\u8BDD\uFF0C\u7528\u624B\u673A\u626B\u7801\u6216\u6253\u5F00\u4E0B\u9762\u7684\u94FE\u63A5\uFF0C\u5E76\u6838\u5BF9\u9A8C\u8BC1\u7801\u3002","signin.code":"\u9A8C\u8BC1\u7801","signin.openLink":"\u6253\u5F00\u767B\u5F55\u9875","signin.copyLink":"\u590D\u5236\u94FE\u63A5","signin.qrLabel":"\u767B\u5F55\u4E8C\u7EF4\u7801","account.profile.title":"\u4E2A\u4EBA\u8D44\u6599","account.profile.desc":"\u5934\u50CF\u3001\u6635\u79F0\uFF0C\u4EE5\u53CA\u7ED1\u5B9A\u7684\u624B\u673A\u548C\u90AE\u7BB1","account.avatar.change":"\u66F4\u6362\u5934\u50CF","account.avatar.saved":"\u5934\u50CF\u5DF2\u66F4\u65B0","account.nickname.edit":"\u4FEE\u6539\u6635\u79F0","account.nickname.label":"\u6635\u79F0","account.nickname.saved":"\u6635\u79F0\u5DF2\u66F4\u65B0","account.role.admin":"\u7BA1\u7406\u5458","account.username":"\u7528\u6237\u540D {name}","account.contact.phone":"\u624B\u673A","account.contact.email":"\u90AE\u7BB1","account.contact.unbound":"\u672A\u7ED1\u5B9A","account.contact.manage":"\u53BB\u5B89\u5168\u9875\u7BA1\u7406","account.web.open":"\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u4E2A\u4EBA\u4E2D\u5FC3","account.web.desc":"\u4E91\u7A7A\u95F4\u3001AI \u5927\u8111\u3001\u6295\u7A3F\u4E0E\u4E3B\u9898\u5728\u7F51\u9875\u4E2A\u4EBA\u4E2D\u5FC3\u7BA1\u7406\u3002","member.title":"\u4F1A\u5458","member.desc":"\u5F53\u524D\u6863\u4F4D\u3001\u65B9\u6848\u4E0E\u5230\u671F\u65E5","member.upgrade":"\u5347\u7EA7\u4F1A\u5458","member.renew":"\u7EED\u8D39","member.freeName":"\u514D\u8D39\u7248","member.freeHint":"\u5347\u7EA7\u4F1A\u5458\u53EF\u4EE5\u83B7\u5F97\u66F4\u591A AI \u989D\u5EA6","member.expires":"{date} \u5230\u671F","member.noExpiry":"\u957F\u671F\u6709\u6548","member.loadFailed":"\u4F1A\u5458\u4FE1\u606F\u6682\u65F6\u62FF\u4E0D\u5230\u3002","local.title":"\u8FD9\u53F0\u7535\u8111\u4E0A\u7684\u8D26\u53F7","local.desc":"\u5728\u767B\u5F55\u8FC7\u7684\u8D26\u53F7\u4E4B\u95F4\u5207\u6362","local.current":"\u5F53\u524D","local.switch":"\u5207\u6362","local.add":"\u767B\u5F55\u5176\u4ED6\u8D26\u53F7","local.signOut":"\u9000\u51FA\u767B\u5F55","local.empty":"\u8FD8\u6CA1\u6709\u4FDD\u5B58\u7684\u8D26\u53F7","local.loadFailed":"\u8D26\u53F7\u5217\u8868\u6682\u65F6\u8BFB\u4E0D\u5230","quota.ai.title":"AI \u989D\u5EA6","quota.ai.desc":"\u4ECA\u65E5\u548C\u672C\u5468\u5404\u8FD8\u5269\u591A\u5C11\uFF1B\u7528\u5B8C\u540E\u53EF\u4EE5\u7528\u989D\u5EA6\u91CD\u7F6E\u5361\u6062\u590D","quota.resetDaily":"\u6BCF\u5929 0:00 \u91CD\u7F6E\uFF08\u5317\u4EAC\u65F6\u95F4\uFF09","quota.resetWeekly":"{date} 0:00 \u91CD\u7F6E\uFF08\u5317\u4EAC\u65F6\u95F4\uFF09","card.title":"\u989D\u5EA6\u91CD\u7F6E\u5361","card.desc":"\u628A\u4ECA\u65E5\u548C\u672C\u5468\u7684 AI \u989D\u5EA6\u6062\u590D\u5230 100%","card.owned":"\u6301\u6709 {n} \u5F20","card.use":"\u4F7F\u7528\u4E00\u5F20","card.useConfirm":"\u786E\u8BA4\u4F7F\u7528","card.used":"\u5DF2\u4F7F\u7528 1 \u5F20\u989D\u5EA6\u91CD\u7F6E\u5361","card.left":"\u8FD8\u5269 {n} \u5F20","card.noneHint":"\u6CA1\u6709\u989D\u5EA6\u91CD\u7F6E\u5361\u4E86\uFF0C\u53EF\u4EE5\u7528\u79EF\u5206\u5151\u6362\u3002","card.exchange":"\u7528\u79EF\u5206\u5151\u6362","card.price":"\u6BCF\u5F20 {price} \u79EF\u5206\uFF0C\u4E00\u6B21 1\u201350 \u5F20","card.count":"\u5151\u6362\u5F20\u6570","card.cost":"\u82B1\u8D39 {cost} \u79EF\u5206","card.countHint":"\u586B 1\u201350","card.exchangeButton":"\u5151\u6362","card.exchangeConfirm":"\u786E\u8BA4\u82B1\u8D39 {cost} \u79EF\u5206","card.exchanged":"\u5DF2\u5151\u6362 {n} \u5F20\u989D\u5EA6\u91CD\u7F6E\u5361","points.title":"\u79EF\u5206","points.desc":"\u79EF\u5206\u53EF\u4EE5\u5151\u6362\u989D\u5EA6\u91CD\u7F6E\u5361\uFF0C\u4E5F\u80FD\u5728 AI \u989D\u5EA6\u7528\u5B8C\u540E\u81EA\u52A8\u62B5\u6263","points.balance":"\u4F59\u989D","points.balanceFailed":"\u4F59\u989D\u6682\u65F6\u62FF\u4E0D\u5230","points.recharge":"\u5145\u503C\u79EF\u5206","points.autoDeduct":"\u79EF\u5206\u81EA\u52A8\u62B5\u6263","points.autoDeductDesc":"AI \u989D\u5EA6\u7528\u5B8C\u540E\uFF0C\u81EA\u52A8\u7528\u79EF\u5206\u7EE7\u7EED","bg.title":"\u540E\u53F0\u989D\u5EA6","bg.desc":"Muse \u4E0E\u81EA\u52A8\u5316\u4F7F\u7528\uFF0C\u548C AI \u989D\u5EA6\u5206\u5F00\u8BA1\u7B97","bg.autoMain":"\u7528\u5B8C\u540E\u6539\u7528 AI \u989D\u5EA6\u7EE7\u7EED","bg.autoMainDesc":"\u5173\u7740\u65F6\uFF0C\u540E\u53F0\u989D\u5EA6\u7528\u5B8C\u540E Muse \u4E0E\u81EA\u52A8\u5316\u4F1A\u6682\u505C","bg.convert":"\u4ECE AI \u989D\u5EA6\u8F6C\u5165","bg.convertDesc":"\u6309 AI \u989D\u5EA6\u4E0A\u9650\u7684\u6BD4\u4F8B\u8F6C\u5165\uFF0C\u672C\u5468\u671F\u5185\u6709\u6548","bg.convertConfirm":"\u786E\u8BA4\u8F6C\u5165 {pct}%","bg.converted":"\u5DF2\u4ECE AI \u989D\u5EA6\u8F6C\u5165 {pct}%","invite.title":"\u9080\u8BF7\u4E0E\u5151\u6362","invite.desc":"\u9080\u8BF7\u597D\u53CB\u6CE8\u518C\uFF0C\u6216\u5151\u6362\u4F60\u6536\u5230\u7684\u7801","invite.myCode":"\u6211\u7684\u9080\u8BF7\u7801","invite.count":"\u5DF2\u9080\u8BF7 {n} \u4EBA","invite.copyCode":"\u590D\u5236\u9080\u8BF7\u7801","invite.copyLink":"\u590D\u5236\u9080\u8BF7\u94FE\u63A5","invite.loadFailed":"\u9080\u8BF7\u7801\u6682\u65F6\u62FF\u4E0D\u5230","invite.claim":"\u586B\u5199\u9080\u8BF7\u7801","invite.claimDesc":"\u6CE8\u518C\u540E 7 \u5929\u5185\uFF0C\u53EF\u4EE5\u8865\u586B\u597D\u53CB\u7684\u9080\u8BF7\u7801","invite.claimPlaceholder":"\u597D\u53CB\u7684\u9080\u8BF7\u7801","invite.claimSubmit":"\u63D0\u4EA4","invite.claimed":"\u9080\u8BF7\u7801\u5DF2\u751F\u6548","redeem.title":"\u5151\u6362\u7801","redeem.desc":"\u5151\u6362\u79EF\u5206\u3001\u4F1A\u5458\u6216\u5176\u4ED6\u5956\u52B1","redeem.placeholder":"\u8F93\u5165\u5151\u6362\u7801","redeem.submit":"\u5151\u6362","redeem.success":"\u5151\u6362\u6210\u529F","redeem.successWith":"\u5151\u6362\u6210\u529F\uFF1A{what}","redeem.gotPoints":"{n} \u79EF\u5206","redeem.gotMembership":"\u4F1A\u5458","sec.methods.title":"\u767B\u5F55\u65B9\u5F0F","sec.methods.desc":"\u624B\u673A\u548C\u90AE\u7BB1\u53EF\u4EE5\u7528\u6765\u767B\u5F55\u3001\u627E\u56DE\u5BC6\u7801","sec.bind":"\u7ED1\u5B9A","sec.change":"\u66F4\u6362","sec.phone":"\u624B\u673A\u53F7","sec.email":"\u90AE\u7BB1\u5730\u5740","sec.newPhone":"\u65B0\u624B\u673A\u53F7","sec.newEmail":"\u65B0\u90AE\u7BB1\u5730\u5740","sec.phonePlaceholder":"\u4E2D\u56FD\u5927\u9646\u53F7\u7801\u76F4\u63A5\u586B\uFF0C\u5176\u4ED6\u5730\u533A\u5E26 +\u533A\u53F7","sec.emailPlaceholder":"name@example.com","sec.code":"\u9A8C\u8BC1\u7801","sec.codePlaceholder":"\u8F93\u5165\u9A8C\u8BC1\u7801","sec.sendCode":"\u53D1\u9001\u9A8C\u8BC1\u7801","sec.resendIn":"{s} \u79D2\u540E\u91CD\u53D1","sec.codeSent":"\u9A8C\u8BC1\u7801\u5DF2\u53D1\u9001","sec.bindSubmit":"\u786E\u8BA4\u7ED1\u5B9A","sec.phoneBound":"\u624B\u673A\u5DF2\u7ED1\u5B9A","sec.emailBound":"\u90AE\u7BB1\u5DF2\u7ED1\u5B9A","sec.devices.title":"\u767B\u5F55\u8BBE\u5907","sec.devices.desc":"\u62C5\u5FC3\u8D26\u53F7\u88AB\u522B\u4EBA\u7528\u4E86\uFF0C\u53EF\u4EE5\u8BA9\u6240\u6709\u8BBE\u5907\u91CD\u65B0\u767B\u5F55","sec.logoutAll":"\u9000\u51FA\u6240\u6709\u8BBE\u5907","sec.logoutAllDesc":"\u5305\u62EC\u8FD9\u53F0\u7535\u8111\uFF0C\u6240\u6709\u8BBE\u5907\u90FD\u8981\u91CD\u65B0\u767B\u5F55","sec.logoutAllConfirm":"\u786E\u8BA4\u9000\u51FA\u6240\u6709\u8BBE\u5907","sec.logoutAllDone":"\u5DF2\u9000\u51FA\u6240\u6709\u8BBE\u5907","pw.title":"\u5BC6\u7801","pw.desc":"{min}\u2013{max} \u4F4D\uFF0C\u542B\u5C0F\u5199\u5B57\u6BCD\u3001\u5927\u5199\u5B57\u6BCD\u548C\u7279\u6B8A\u5B57\u7B26\uFF0C\u4E0D\u80FD\u6709\u7A7A\u683C","pw.change":"\u4FEE\u6539\u5BC6\u7801","pw.modeLabel":"\u4FEE\u6539\u65B9\u5F0F","pw.mode.current":"\u7528\u5F53\u524D\u5BC6\u7801","pw.mode.code":"\u7528\u9A8C\u8BC1\u7801","pw.current":"\u5F53\u524D\u5BC6\u7801","pw.currentRequired":"\u8BF7\u8F93\u5165\u5F53\u524D\u5BC6\u7801","pw.new":"\u65B0\u5BC6\u7801","pw.confirm":"\u518D\u8F93\u4E00\u6B21\u65B0\u5BC6\u7801","pw.mismatch":"\u4E24\u6B21\u8F93\u5165\u7684\u65B0\u5BC6\u7801\u4E0D\u4E00\u81F4","pw.submit":"\u4FEE\u6539\u5BC6\u7801","pw.submitReset":"\u8BBE\u7F6E\u65B0\u5BC6\u7801","pw.changed":"\u5BC6\u7801\u5DF2\u66F4\u65B0","pw.noPasswordYet":"\u8FD9\u4E2A\u8D26\u53F7\u8FD8\u6CA1\u6709\u8BBE\u7F6E\u5BC6\u7801\uFF0C\u8BF7\u6539\u7528\u9A8C\u8BC1\u7801\u8BBE\u7F6E\u3002","pw.codeNeedsContact":"\u7ED1\u5B9A\u624B\u673A\u6216\u90AE\u7BB1\u540E\uFF0C\u624D\u80FD\u7528\u9A8C\u8BC1\u7801\u8BBE\u7F6E\u5BC6\u7801\u3002","pw.via":"\u9A8C\u8BC1\u7801\u53D1\u5230","pw.codeTo":"\u9A8C\u8BC1\u7801\u4F1A\u53D1\u5230 {target}","pw.rulesLabel":"\u5BC6\u7801\u89C4\u5219","pw.req.length":"{min}\u2013{max} \u4F4D","pw.req.lower":"\u542B\u5C0F\u5199\u5B57\u6BCD","pw.req.upper":"\u542B\u5927\u5199\u5B57\u6BCD","pw.req.special":"\u542B\u7279\u6B8A\u5B57\u7B26","pw.req.space":"\u4E0D\u542B\u7A7A\u683C","pw.rule.format":"\u5BC6\u7801\u683C\u5F0F\u4E0D\u6B63\u786E","pw.rule.min":"\u5BC6\u7801\u81F3\u5C11 8 \u4F4D","pw.rule.max":"\u5BC6\u7801\u4E0D\u80FD\u8D85\u8FC7 64 \u4F4D","pw.rule.space":"\u5BC6\u7801\u4E0D\u80FD\u5305\u542B\u7A7A\u683C","pw.rule.lower":"\u5BC6\u7801\u5FC5\u987B\u5305\u542B\u5C0F\u5199\u5B57\u6BCD","pw.rule.upper":"\u5BC6\u7801\u5FC5\u987B\u5305\u542B\u5927\u5199\u5B57\u6BCD","pw.rule.special":"\u5BC6\u7801\u5FC5\u987B\u5305\u542B\u7279\u6B8A\u5B57\u7B26","del.title":"\u6CE8\u9500\u8D26\u53F7","del.desc":"\u6C38\u4E45\u5220\u9664\u8D26\u53F7\u548C\u5168\u90E8\u6570\u636E\uFF0C\u65E0\u6CD5\u6062\u590D","del.start":"\u6CE8\u9500\u8D26\u53F7","del.warn":"\u6CE8\u9500\u540E\uFF0C\u8D26\u53F7\u3001\u79EF\u5206\u3001\u4F1A\u5458\u3001\u4E91\u7A7A\u95F4\u548C\u5168\u90E8\u6570\u636E\u90FD\u4F1A\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u627E\u56DE\u3002","del.methodLabel":"\u9A8C\u8BC1\u65B9\u5F0F","del.byCode":"\u9A8C\u8BC1\u7801","del.byPassword":"\u5BC6\u7801","del.codeLabel":"\u53D1\u5230 {target} \u7684\u9A8C\u8BC1\u7801","del.passwordLabel":"\u8D26\u53F7\u5BC6\u7801","del.submit":"\u6CE8\u9500\u8D26\u53F7","del.confirm":"\u786E\u8BA4\u6C38\u4E45\u6CE8\u9500","del.done":"\u8D26\u53F7\u5DF2\u6CE8\u9500","usage.overview.title":"\u7528\u91CF\u6982\u89C8","usage.overview.desc":"\u6240\u9009\u65F6\u95F4\u6BB5\u5185\u7684\u8BF7\u6C42\u4E0E AI \u989D\u5EA6\u6D88\u8017","usage.range":"\u65F6\u95F4\u8303\u56F4","usage.days":"{n} \u5929","usage.requests":"\u8BF7\u6C42\u6B21\u6570","usage.successRate":"\u6210\u529F\u7387","usage.consumption":"AI \u989D\u5EA6\u6D88\u8017","usage.ofToday":"\u5360\u4ECA\u65E5\u989D\u5EA6\u4E0A\u9650","usage.unlimitedNote":"\u4F60\u7684 AI \u989D\u5EA6\u4E0D\u9650\uFF0C\u6D88\u8017\u65E0\u6CD5\u6298\u7B97\u6210\u767E\u5206\u6BD4\u3002","usage.noLimitNote":"\u4ECA\u65E5\u989D\u5EA6\u4E0A\u9650\u4E3A 0 \u6216\u6682\u65F6\u62FF\u4E0D\u5230\uFF0C\u6D88\u8017\u65E0\u6CD5\u6298\u7B97\u6210\u767E\u5206\u6BD4\u3002","usage.byModel.title":"\u6309\u6A21\u578B","usage.byModel.desc":"\u5404\u6A21\u578B\u7684\u8BF7\u6C42\u6570\u4E0E\u989D\u5EA6\u6D88\u8017","usage.byApp.title":"\u6309\u5E94\u7528","usage.byApp.desc":"\u5404\u5E94\u7528\u7684\u8BF7\u6C42\u6570\u4E0E\u989D\u5EA6\u6D88\u8017","usage.col.model":"\u6A21\u578B","usage.col.app":"\u5E94\u7528","usage.col.requests":"\u8BF7\u6C42","usage.col.consumption":"\u989D\u5EA6\u6D88\u8017","usage.empty":"\u8FD9\u6BB5\u65F6\u95F4\u6CA1\u6709\u7528\u91CF","usage.appUnknown":"\u5176\u4ED6","usage.recent.title":"\u6700\u8FD1\u6D88\u8017","usage.recent.desc":"\u6BCF\u6B21\u8C03\u7528\u5360\u4ECA\u65E5\u989D\u5EA6\u4E0A\u9650\u7684\u6BD4\u4F8B","usage.recentEmpty":"\u8FD8\u6CA1\u6709\u6D88\u8017\u8BB0\u5F55","usage.failed":"\u5931\u8D25","usage.shown":"\u5DF2\u663E\u793A {shown} / {total} \u6761","fb.list.title":"\u6211\u7684\u53CD\u9988","fb.list.desc":"\u63D0\u4EA4\u8FC7\u7684\u95EE\u9898\u548C\u5EFA\u8BAE\uFF0C\u56DE\u590D\u4F1A\u663E\u793A\u5728\u8FD9\u91CC","fb.new":"\u65B0\u5EFA\u53CD\u9988","fb.empty":"\u8FD8\u6CA1\u6709\u53CD\u9988","fb.untitled":"\u672A\u547D\u540D\u53CD\u9988","fb.unread":"\u6709\u65B0\u56DE\u590D","fb.shown":"\u5DF2\u663E\u793A {n} \u6761","fb.submitted":"\u5DF2\u63D0\u4EA4\uFF0C\u6211\u4EEC\u4F1A\u5C3D\u5FEB\u56DE\u590D","fb.descLabel":"\u63CF\u8FF0\u95EE\u9898\u6216\u5EFA\u8BAE","fb.descPlaceholder":"\u53D1\u751F\u4E86\u4EC0\u4E48\uFF0C\u4F60\u671F\u671B\u600E\u6837\u2026\u2026","fb.imagesHint":"\u6700\u591A\u9644 {n} \u5F20\u622A\u56FE\uFF08\u6BCF\u5F20\u4E0D\u8D85\u8FC7 5MB\uFF09\uFF0C\u53EF\u4EE5\u7C98\u8D34\u6216\u62D6\u8FDB\u6765\u3002","fb.addImages":"\u6DFB\u52A0\u622A\u56FE","fb.removeImage":"\u79FB\u9664\u8FD9\u5F20\u56FE","fb.submit":"\u63D0\u4EA4","fb.back":"\u8FD4\u56DE\u5217\u8868","fb.you":"\u4F60","fb.support":"Forsion \u56E2\u961F","fb.attachment":"\u9644\u4EF6","fb.imagePreview":"\u67E5\u770B\u5927\u56FE","fb.closedNote":"\u8FD9\u4E2A\u5DE5\u5355\u5DF2\u5173\u95ED\uFF0C\u4E0D\u80FD\u518D\u56DE\u590D\u3002\u6709\u65B0\u95EE\u9898\u8BF7\u65B0\u5EFA\u53CD\u9988\u3002","fb.replyPlaceholder":"\u56DE\u590D\u2026","fb.replySend":"\u53D1\u9001\u56DE\u590D","fb.replySent":"\u56DE\u590D\u5DF2\u53D1\u9001","fb.status.open":"\u5F85\u5904\u7406","fb.status.in_progress":"\u5904\u7406\u4E2D","fb.status.resolved":"\u5DF2\u89E3\u51B3","fb.status.closed":"\u5DF2\u5173\u95ED","err.accountGone":"\u8FD9\u4E2A\u8D26\u53F7\u5DF2\u9000\u51FA\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55","err.adminCannotDelete":"\u7BA1\u7406\u5458\u8D26\u53F7\u4E0D\u80FD\u81EA\u52A9\u6CE8\u9500","err.avatarInvalid":"\u8FD9\u5F20\u56FE\u7247\u8BFB\u4E0D\u51FA\u6765\uFF0C\u6362\u4E00\u5F20\u8BD5\u8BD5","err.avatarTooLarge":"\u56FE\u7247\u592A\u5927\u4E86\uFF0C\u6362\u4E00\u5F20\u5C0F\u4E00\u70B9\u7684","err.backgroundUnavailable":"\u540E\u53F0\u989D\u5EA6\u6682\u65F6\u4E0D\u53EF\u7528","err.captcha":"\u9700\u8981\u5728\u6D4F\u89C8\u5668\u4E2D\u5B8C\u6210\u4EBA\u673A\u9A8C\u8BC1","err.codeCooldown":"\u53D1\u9001\u592A\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5","err.codeInvalid":"\u9A8C\u8BC1\u7801\u4E0D\u5BF9\u6216\u5DF2\u8FC7\u671F","err.codeRequired":"\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801","err.codeSendFailed":"\u9A8C\u8BC1\u7801\u6CA1\u53D1\u51FA\u53BB\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5","err.currentPasswordWrong":"\u5F53\u524D\u5BC6\u7801\u4E0D\u5BF9","err.deleteTargetInvalid":"\u9A8C\u8BC1\u7801\u53EA\u80FD\u53D1\u5230\u8D26\u53F7\u7ED1\u5B9A\u7684\u624B\u673A\u6216\u90AE\u7BB1","err.deleteVerifyFailed":"\u9A8C\u8BC1\u6CA1\u901A\u8FC7\uFF0C\u8D26\u53F7\u6CA1\u6709\u6CE8\u9500","err.emailInUse":"\u8FD9\u4E2A\u90AE\u7BB1\u5DF2\u88AB\u5176\u4ED6\u8D26\u53F7\u4F7F\u7528","err.emailInvalid":"\u90AE\u7BB1\u683C\u5F0F\u4E0D\u5BF9","err.featureDisabled":"\u8FD9\u9879\u529F\u80FD\u6682\u65F6\u5173\u95ED\u4E86","err.feedbackEmpty":"\u8BF7\u5199\u4E00\u4E0B\u95EE\u9898\u6216\u5EFA\u8BAE","err.feedbackTooLong":"\u63CF\u8FF0\u592A\u957F\u4E86\uFF08\u6700\u591A 10000 \u5B57\uFF09","err.generic":"\u64CD\u4F5C\u6CA1\u6709\u6210\u529F\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5","err.imageRead":"\u56FE\u7247\u8BFB\u4E0D\u51FA\u6765","err.imageTooLarge":"\u6BCF\u5F20\u56FE\u7247\u4E0D\u80FD\u8D85\u8FC7 5MB","err.imageType":"\u53EA\u80FD\u6DFB\u52A0\u56FE\u7247","err.insufficientMainQuota":"AI \u989D\u5EA6\u5DF2\u7528\u5B8C\uFF0C\u6CA1\u6709\u53EF\u8F6C\u5165\u7684\u989D\u5EA6","err.insufficientPoints":"\u79EF\u5206\u4E0D\u591F","err.invalidCount":"\u5F20\u6570\u8981\u5728 1\u201350 \u4E4B\u95F4","err.invalidInviteCode":"\u9080\u8BF7\u7801\u65E0\u6548\u6216\u5DF2\u5931\u6548","err.inviteAlreadyUsed":"\u4F60\u5DF2\u7ECF\u7528\u8FC7\u9080\u8BF7\u7801\u4E86","err.inviteEmpty":"\u8BF7\u8F93\u5165\u9080\u8BF7\u7801","err.inviteOwnCode":"\u4E0D\u80FD\u586B\u81EA\u5DF1\u7684\u9080\u8BF7\u7801","err.inviteWindowExpired":"\u5DF2\u8D85\u8FC7\u6CE8\u518C\u540E 7 \u5929\u7684\u8865\u586B\u671F","err.loginCodeExpired":"\u767B\u5F55\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55","err.loginInProgress":"\u6B63\u5728\u767B\u5F55\u4E2D","err.loginTimeout":"\u767B\u5F55\u8D85\u65F6\uFF0C\u8BF7\u91CD\u8BD5","err.loginUnsupported":"\u8FD9\u4E2A\u4E91\u7AEF\u4E0D\u652F\u6301\u684C\u9762\u7AEF\u767B\u5F55","err.network":"\u7F51\u7EDC\u8FDE\u63A5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5","err.noCloudUrl":"\u8BF7\u5148\u5728\u300C\u8FDE\u63A5\u300D\u91CC\u586B\u5199\u4E91\u7AEF\u5730\u5740","err.noResetCard":"\u6CA1\u6709\u53EF\u7528\u7684\u989D\u5EA6\u91CD\u7F6E\u5361","err.openFailed":"\u6CA1\u80FD\u6253\u5F00\u6D4F\u89C8\u5668","err.passwordRequired":"\u8BF7\u586B\u5199\u5F53\u524D\u5BC6\u7801\u548C\u65B0\u5BC6\u7801","err.phoneInUse":"\u8FD9\u4E2A\u624B\u673A\u53F7\u5DF2\u88AB\u5176\u4ED6\u8D26\u53F7\u4F7F\u7528","err.phoneInvalid":"\u624B\u673A\u53F7\u683C\u5F0F\u4E0D\u5BF9\uFF08\u5176\u4ED6\u5730\u533A\u8BF7\u5E26 +\u533A\u53F7\uFF09","err.redeemEmpty":"\u8BF7\u8F93\u5165\u5151\u6362\u7801","err.redeemExpired":"\u5151\u6362\u7801\u5DF2\u8FC7\u671F","err.redeemInactive":"\u5151\u6362\u7801\u5DF2\u505C\u7528","err.redeemNotFound":"\u5151\u6362\u7801\u4E0D\u5B58\u5728","err.redeemUsedUp":"\u5151\u6362\u7801\u5DF2\u88AB\u7528\u5B8C","err.redeemUserLimit":"\u4F60\u5DF2\u7ECF\u5151\u6362\u8FC7\u8FD9\u4E2A\u7801\u4E86","err.replyEmpty":"\u8BF7\u8F93\u5165\u56DE\u590D\u5185\u5BB9","err.replyTooLong":"\u56DE\u590D\u592A\u957F\u4E86\uFF08\u6700\u591A 10000 \u5B57\uFF09","err.server":"\u670D\u52A1\u5668\u51FA\u9519\u4E86\uFF08{status}\uFF09\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5","err.session":"\u767B\u5F55\u72B6\u6001\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55","err.signedOut":"\u8BF7\u5148\u767B\u5F55 Forsion","err.targetInvalid":"\u624B\u673A\u53F7\u6216\u90AE\u7BB1\u683C\u5F0F\u4E0D\u5BF9","err.ticketNotFound":"\u8FD9\u6761\u53CD\u9988\u4E0D\u5B58\u5728\u6216\u5DF2\u5220\u9664","err.tooFrequent":"\u64CD\u4F5C\u592A\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5","err.tooManyImages":"\u6700\u591A\u6DFB\u52A0 5 \u5F20\u56FE\u7247","err.unavailable":"\u8FD9\u4E2A\u7248\u672C\u7684\u684C\u9762\u7AEF\u8FD8\u4E0D\u652F\u6301\u8FD9\u4E2A\u64CD\u4F5C\uFF0C\u8BF7\u66F4\u65B0 Forsion"},io={"page.account":"Account","page.quota":"Quota & points","page.security":"Security","page.usage":"Usage","page.feedback":"Feedback","common.cancel":"Cancel","common.copied":"Copied","common.copyFailed":"Couldn't copy","common.done":"Done","common.loadFailed":"Couldn't load","common.loadMore":"Load more","common.loading":"Loading\u2026","common.openInBrowser":"Open in browser","common.retry":"Retry","common.save":"Save","common.thisWeek":"This week","common.today":"Today","common.unlimited":"Unlimited","signin.button":"Sign in to Forsion","signin.desc":"Sign in to your Forsion account to manage your account, quota, security and feedback here.","signin.pending":"Waiting for you to finish in your browser\u2026","signin.deviceHint":"Your browser opens the sign-in page on its own. If it doesn't, scan the code with your phone or open the link below, and check that the code matches.","signin.code":"Code","signin.openLink":"Open sign-in page","signin.copyLink":"Copy link","signin.qrLabel":"Sign-in QR code","account.profile.title":"Profile","account.profile.desc":"Your photo and nickname, plus the phone and email linked to your account","account.avatar.change":"Change photo","account.avatar.saved":"Photo updated","account.nickname.edit":"Edit nickname","account.nickname.label":"Nickname","account.nickname.saved":"Nickname updated","account.role.admin":"Admin","account.username":"Username {name}","account.contact.phone":"Phone","account.contact.email":"Email","account.contact.unbound":"Not linked","account.contact.manage":"Manage in Security","account.web.open":"Open the account center in your browser","account.web.desc":"Cloud storage, AI Brain, submissions and themes are managed in the web account center.","member.title":"Membership","member.desc":"Your tier, plan and expiry date","member.upgrade":"Upgrade membership","member.renew":"Renew","member.freeName":"Free plan","member.freeHint":"Upgrade to get more AI quota","member.expires":"Expires {date}","member.noExpiry":"No expiry","member.loadFailed":"Couldn't load your membership.","local.title":"Accounts on this computer","local.desc":"Switch between accounts you've signed in with","local.current":"Current","local.switch":"Switch","local.add":"Sign in to another account","local.signOut":"Sign out","local.empty":"No saved accounts yet","local.loadFailed":"Couldn't read the account list","quota.ai.title":"AI quota","quota.ai.desc":"What's left today and this week; a quota reset card restores it","quota.resetDaily":"Resets daily at 0:00 (Beijing time)","quota.resetWeekly":"Resets {date} at 0:00 (Beijing time)","card.title":"Quota reset card","card.desc":"Restores today's and this week's AI quota to 100%","card.owned":"You have {n}","card.use":"Use one","card.useConfirm":"Confirm","card.used":"Used 1 quota reset card","card.left":"{n} left","card.noneHint":"You have no quota reset cards left. You can exchange points for more.","card.exchange":"Exchange points","card.price":"{price} points each, 1\u201350 at a time","card.count":"Number of cards","card.cost":"Costs {cost} points","card.countHint":"Enter 1\u201350","card.exchangeButton":"Exchange","card.exchangeConfirm":"Spend {cost} points","card.exchanged":"Quota reset cards added: {n}","points.title":"Points","points.desc":"Exchange points for quota reset cards, or spend them automatically when your AI quota runs out","points.balance":"Balance","points.balanceFailed":"Couldn't load your balance","points.recharge":"Buy points","points.autoDeduct":"Pay with points automatically","points.autoDeductDesc":"When your AI quota runs out, keep going with points","bg.title":"Background quota","bg.desc":"Used by Muse and automations, counted separately from your AI quota","bg.autoMain":"Continue with AI quota when used up","bg.autoMainDesc":"When off, Muse and automations pause once the background quota runs out","bg.convert":"Move from AI quota","bg.convertDesc":"Moves a share of your AI quota limit, valid for the current period","bg.convertConfirm":"Move {pct}%","bg.converted":"Moved {pct}% from your AI quota","invite.title":"Invites & codes","invite.desc":"Invite friends to join, or redeem a code you received","invite.myCode":"My invite code","invite.count":"{n} invited","invite.copyCode":"Copy code","invite.copyLink":"Copy invite link","invite.loadFailed":"Couldn't load your invite code","invite.claim":"Enter an invite code","invite.claimDesc":"Within 7 days of signing up, you can enter a friend's invite code","invite.claimPlaceholder":"Friend's invite code","invite.claimSubmit":"Submit","invite.claimed":"Invite code applied","redeem.title":"Redemption code","redeem.desc":"Redeem points, membership or other rewards","redeem.placeholder":"Enter a code","redeem.submit":"Redeem","redeem.success":"Redeemed","redeem.successWith":"Redeemed: {what}","redeem.gotPoints":"{n} points","redeem.gotMembership":"membership","sec.methods.title":"Sign-in methods","sec.methods.desc":"Your phone and email can be used to sign in and reset your password","sec.bind":"Link","sec.change":"Change","sec.phone":"Phone number","sec.email":"Email address","sec.newPhone":"New phone number","sec.newEmail":"New email address","sec.phonePlaceholder":"Mainland China numbers as is; others with +country code","sec.emailPlaceholder":"name@example.com","sec.code":"Verification code","sec.codePlaceholder":"Enter the code","sec.sendCode":"Send code","sec.resendIn":"Resend in {s}s","sec.codeSent":"Code sent","sec.bindSubmit":"Link","sec.phoneBound":"Phone linked","sec.emailBound":"Email linked","sec.devices.title":"Signed-in devices","sec.devices.desc":"If you think someone else is using your account, sign out on every device","sec.logoutAll":"Sign out everywhere","sec.logoutAllDesc":"Including this computer: every device has to sign in again","sec.logoutAllConfirm":"Confirm sign out everywhere","sec.logoutAllDone":"Signed out everywhere","pw.title":"Password","pw.desc":"{min}\u2013{max} characters, with a lowercase letter, an uppercase letter and a special character, and no spaces","pw.change":"Change password","pw.modeLabel":"How to change it","pw.mode.current":"With current password","pw.mode.code":"With a verification code","pw.current":"Current password","pw.currentRequired":"Enter your current password","pw.new":"New password","pw.confirm":"Confirm new password","pw.mismatch":"The new passwords don't match","pw.submit":"Change password","pw.submitReset":"Set new password","pw.changed":"Password updated","pw.noPasswordYet":"This account doesn't have a password yet. Set one with a verification code instead.","pw.codeNeedsContact":"Link a phone or email first to set a password with a verification code.","pw.via":"Send the code to","pw.codeTo":"The code goes to {target}","pw.rulesLabel":"Password rules","pw.req.length":"{min}\u2013{max} characters","pw.req.lower":"A lowercase letter","pw.req.upper":"An uppercase letter","pw.req.special":"A special character","pw.req.space":"No spaces","pw.rule.format":"Invalid password","pw.rule.min":"Password must be at least 8 characters","pw.rule.max":"Password can't be longer than 64 characters","pw.rule.space":"Password can't contain spaces","pw.rule.lower":"Password needs a lowercase letter","pw.rule.upper":"Password needs an uppercase letter","pw.rule.special":"Password needs a special character","del.title":"Delete account","del.desc":"Permanently delete your account and all its data. This can't be undone","del.start":"Delete account","del.warn":"Deleting your account removes your account, points, membership, cloud storage and all other data for good.","del.methodLabel":"Verify with","del.byCode":"Verification code","del.byPassword":"Password","del.codeLabel":"Code sent to {target}","del.passwordLabel":"Account password","del.submit":"Delete account","del.confirm":"Delete permanently","del.done":"Account deleted","usage.overview.title":"Overview","usage.overview.desc":"Requests and AI quota used in the selected period","usage.range":"Time range","usage.days":"{n} days","usage.requests":"Requests","usage.successRate":"Success rate","usage.consumption":"AI quota used","usage.ofToday":"Of your daily limit","usage.unlimitedNote":"Your AI quota is unlimited, so usage isn't shown as a percentage.","usage.noLimitNote":"Your daily limit is 0 or unavailable right now, so usage isn't shown as a percentage.","usage.byModel.title":"By model","usage.byModel.desc":"Requests and quota used per model","usage.byApp.title":"By app","usage.byApp.desc":"Requests and quota used per app","usage.col.model":"Model","usage.col.app":"App","usage.col.requests":"Requests","usage.col.consumption":"Quota used","usage.empty":"No usage in this period","usage.appUnknown":"Other","usage.recent.title":"Recent usage","usage.recent.desc":"Each call as a share of your daily limit","usage.recentEmpty":"No usage yet","usage.failed":"Failed","usage.shown":"Showing {shown} of {total}","fb.list.title":"My feedback","fb.list.desc":"Issues and suggestions you've sent; replies show up here","fb.new":"New feedback","fb.empty":"No feedback yet","fb.untitled":"Untitled feedback","fb.unread":"New reply","fb.shown":"Showing {n}","fb.submitted":"Sent. We'll reply as soon as we can","fb.descLabel":"Describe the issue or suggestion","fb.descPlaceholder":"What happened, and what did you expect?","fb.imagesHint":"Attach up to {n} screenshots (5 MB each). You can paste or drop them here.","fb.addImages":"Add screenshots","fb.removeImage":"Remove this image","fb.submit":"Send","fb.back":"Back to list","fb.you":"You","fb.support":"Forsion team","fb.attachment":"Attachment","fb.imagePreview":"View image","fb.closedNote":"This ticket is closed and can't take replies. Send new feedback for a new issue.","fb.replyPlaceholder":"Reply\u2026","fb.replySend":"Send reply","fb.replySent":"Reply sent","fb.status.open":"Open","fb.status.in_progress":"In progress","fb.status.resolved":"Resolved","fb.status.closed":"Closed","err.accountGone":"This account is signed out. Sign in again","err.adminCannotDelete":"Admin accounts can't be deleted here","err.avatarInvalid":"Couldn't read this image. Try another one","err.avatarTooLarge":"This image is too large. Try a smaller one","err.backgroundUnavailable":"Background quota is unavailable right now","err.captcha":"You need to finish a verification check in your browser","err.codeCooldown":"Too many codes requested. Try again shortly","err.codeInvalid":"The code is wrong or has expired","err.codeRequired":"Enter the verification code","err.codeSendFailed":"Couldn't send the code. Try again later","err.currentPasswordWrong":"Your current password is incorrect","err.deleteTargetInvalid":"Codes can only go to the phone or email linked to your account","err.deleteVerifyFailed":"Verification failed, so your account wasn't deleted","err.emailInUse":"This email is already used by another account","err.emailInvalid":"Enter a valid email address","err.featureDisabled":"This feature is turned off for now","err.feedbackEmpty":"Describe the issue or suggestion first","err.feedbackTooLong":"The description is too long (10,000 characters max)","err.generic":"That didn't work. Try again later","err.imageRead":"Couldn't read the image","err.imageTooLarge":"Each image must be 5 MB or less","err.imageType":"Only images can be added","err.insufficientMainQuota":"Your AI quota is used up, so there's nothing to move","err.insufficientPoints":"Not enough points","err.invalidCount":"Choose between 1 and 50 cards","err.invalidInviteCode":"This invite code is invalid or has expired","err.inviteAlreadyUsed":"You've already used an invite code","err.inviteEmpty":"Enter an invite code","err.inviteOwnCode":"You can't use your own invite code","err.inviteWindowExpired":"The 7-day window after sign-up has passed","err.loginCodeExpired":"The sign-in code expired. Sign in again","err.loginInProgress":"A sign-in is already in progress","err.loginTimeout":"Sign-in timed out. Try again","err.loginUnsupported":"This cloud doesn't support desktop sign-in","err.network":"Network error. Check your connection and try again","err.noCloudUrl":"Set the cloud address under Connection first","err.noResetCard":"You have no quota reset cards","err.openFailed":"Couldn't open the browser","err.passwordRequired":"Enter your current and new password","err.phoneInUse":"This phone number is already used by another account","err.phoneInvalid":"Enter a valid phone number (with +country code outside mainland China)","err.redeemEmpty":"Enter a code","err.redeemExpired":"This code has expired","err.redeemInactive":"This code is no longer active","err.redeemNotFound":"This code doesn't exist","err.redeemUsedUp":"This code has been used up","err.redeemUserLimit":"You've already redeemed this code","err.replyEmpty":"Write a reply first","err.replyTooLong":"The reply is too long (10,000 characters max)","err.server":"Server error ({status}). Try again later","err.session":"You've been signed out. Sign in again","err.signedOut":"Sign in to Forsion first","err.targetInvalid":"Enter a valid phone number or email","err.ticketNotFound":"This feedback doesn't exist or was deleted","err.tooFrequent":"Too many attempts. Try again shortly","err.tooManyImages":"You can add up to 5 images","err.unavailable":"This version of the desktop app can't do that yet. Update Forsion"},tn={zh:ao,en:io},we=t=>t==="en"?"en":"zh";function ut(t,e,n){let r=tn[t][e]??tn.zh[e]??e;return n?r.replace(/\{(\w+)\}/g,(a,i)=>i in n?String(n[i]):a):r}var nn=t=>(e,n)=>ut(t,e,n),te=(t,e)=>"raw"in t?t.raw:e(t.key,t.vars);var L=()=>typeof window<"u"&&window.tangu||{};function on(t){let e=typeof t?.status=="number"?t.status:0;if(e>=200&&e<300)return{ok:!0,status:e,data:t?.json??null};let n=t?.json&&typeof t.json=="object"?t.json:null,r=typeof n?.error=="string"?n.error:typeof n?.code=="string"?n.code:null,a=typeof n?.detail=="string"?n.detail:typeof n?.message=="string"?n.message:null;return{ok:!1,status:e,code:r,detail:a,transport:typeof t?.error=="string"?t.error:null}}var dt=t=>({ok:!1,status:0,code:null,detail:null,transport:t});async function k(t,e={}){let n=L().cloudFetch;if(!n)return dt("no_bridge");try{return on(await n({path:t,...e}))}catch(r){return dt(String(r?.message||r))}}async function Ue(t,e){if(!t)return e();try{return on(await t())}catch(n){return dt(String(n?.message||n))}}var Oe=t=>t.status===401&&(t.transport==="not_signed_in"||t.code===null&&t.detail===null&&t.transport===null);function se(t){return String(t?.message??t??"").replace(/^Error invoking remote method '[^']*':\s*/,"").replace(/^(?:[A-Za-z]*Error):\s*/,"").trim()}async function He(t){let e=L().cloudInvoke;if(!e)return!1;try{return!!(await e("auth:openPayCenter",t))?.ok}catch{return!1}}async function $e(t){let e=L().openAccountCenter;if(!e)return!1;try{return!!(await e(t)).ok}catch{return!1}}function rn(t){return typeof t!="string"?{ok:!1,rule:"format"}:t.length<8?{ok:!1,rule:"min"}:t.length>64?{ok:!1,rule:"max"}:/\s/.test(t)?{ok:!1,rule:"space"}:/[a-z]/.test(t)?/[A-Z]/.test(t)?/[^A-Za-z0-9]/.test(t)?{ok:!0}:{ok:!1,rule:"special"}:{ok:!1,rule:"upper"}:{ok:!1,rule:"lower"}}function an(t){return{length:t.length>=8&&t.length<=64,lower:/[a-z]/.test(t),upper:/[A-Z]/.test(t),special:/[^A-Za-z0-9]/.test(t),space:t.length>0&&!/\s/.test(t)}}var sn={\u5BC6\u7801\u683C\u5F0F\u4E0D\u6B63\u786E:"format","\u5BC6\u7801\u81F3\u5C11 8 \u4F4D":"min","\u5BC6\u7801\u4E0D\u80FD\u8D85\u8FC7 64 \u4F4D":"max",\u5BC6\u7801\u4E0D\u80FD\u5305\u542B\u7A7A\u683C:"space",\u5BC6\u7801\u5FC5\u987B\u5305\u542B\u5C0F\u5199\u5B57\u6BCD:"lower",\u5BC6\u7801\u5FC5\u987B\u5305\u542B\u5927\u5199\u5B57\u6BCD:"upper",\u5BC6\u7801\u5FC5\u987B\u5305\u542B\u7279\u6B8A\u5B57\u7B26:"special"};var ln={no_reset_card:"err.noResetCard",invalid_type:"err.generic",invalid_count:"err.invalidCount",insufficient_points:"err.insufficientPoints",insufficient_main_quota:"err.insufficientMainQuota",background_unavailable:"err.backgroundUnavailable",invalid_percent:"err.generic",invalid_request:"err.generic",invalid_invite_code:"err.invalidInviteCode",already_used:"err.inviteAlreadyUsed",window_expired:"err.inviteWindowExpired",FEATURE_DISABLED:"err.featureDisabled",CAPTCHA_FAILED:"err.captcha"},cn={"Current password is incorrect":"err.currentPasswordWrong","Current and new password are required":"err.passwordRequired",\u9A8C\u8BC1\u7801\u65E0\u6548\u6216\u5DF2\u8FC7\u671F:"err.codeInvalid","Invalid or expired verification code":"err.codeInvalid",\u8D26\u53F7\u6216\u9A8C\u8BC1\u7801\u9519\u8BEF:"err.codeInvalid",\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801:"err.codeRequired","Email already in use":"err.emailInUse","Phone number already in use":"err.phoneInUse","Invalid email format":"err.emailInvalid","Email is required":"err.emailInvalid","Invalid phone number format":"err.phoneInvalid","Phone number is required":"err.phoneInvalid","Invalid phone number or email format":"err.targetInvalid","Please wait before requesting another code":"err.codeCooldown","Failed to send verification code":"err.codeSendFailed","Invalid target for account deletion":"err.deleteTargetInvalid","\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u65E0\u6CD5\u6CE8\u9500\u8D26\u6237":"err.deleteVerifyFailed",\u7BA1\u7406\u5458\u8D26\u53F7\u4E0D\u80FD\u81EA\u52A9\u6CE8\u9500:"err.adminCannotDelete",\u79EF\u5206\u4F59\u989D\u4E0D\u8DB3:"err.insufficientPoints","\u5151\u6362\u5F20\u6570\u9700\u4E3A 1-50 \u7684\u6574\u6570":"err.invalidCount",\u6CA1\u6709\u53EF\u7528\u7684\u91CD\u7F6E\u5361:"err.noResetCard","\u4E3B\u989D\u5EA6\u5DF2\u7528\u5B8C,\u6CA1\u6709\u53EF\u8F6C\u5165\u7684\u989D\u5EA6":"err.insufficientMainQuota",\u540E\u53F0\u989D\u5EA6\u6682\u4E0D\u53EF\u7528:"err.backgroundUnavailable",\u9080\u8BF7\u7801\u65E0\u6548\u6216\u5DF2\u5931\u6548:"err.invalidInviteCode","\u5DF2\u8D85\u8FC7\u6CE8\u518C\u540E 7 \u5929\u7684\u8865\u586B\u671F":"err.inviteWindowExpired",\u4F60\u5DF2\u4F7F\u7528\u8FC7\u9080\u8BF7\u7801:"err.inviteAlreadyUsed","You have already used an invite code":"err.inviteAlreadyUsed","Cannot use your own invite code":"err.inviteOwnCode","Invite code is required":"err.inviteEmpty","code is required":"err.redeemEmpty","Redemption code not found":"err.redeemNotFound","Redemption code is not active":"err.redeemInactive","Redemption code has expired":"err.redeemExpired","Redemption code has reached maximum uses":"err.redeemUsedUp","You have already used this code the maximum number of times":"err.redeemUserLimit",avatar_too_large:"err.avatarTooLarge","description is required":"err.feedbackEmpty","description too long (max 10000 chars)":"err.feedbackTooLong","content is required":"err.replyEmpty","content too long (max 10000 chars)":"err.replyTooLong","Ticket not found":"err.ticketNotFound","Too many attachments (max 5)":"err.tooManyImages","Attachment type not allowed (image / json / text only)":"err.imageType","\u4EBA\u673A\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5":"err.captcha"},ft={format:"pw.rule.format",min:"pw.rule.min",max:"pw.rule.max",space:"pw.rule.space",lower:"pw.rule.lower",upper:"pw.rule.upper",special:"pw.rule.special"};function so(t){if(t.code&&ln[t.code])return ln[t.code];if(t.detail){if(cn[t.detail])return cn[t.detail];let e=sn[t.detail];if(e)return ft[e];if(t.detail.startsWith("Attachment exceeds 5MB"))return"err.imageTooLarge"}return null}function K(t){let e=so(t);return e?{key:e}:Oe(t)?{key:"err.signedOut"}:t.status===0?{key:"err.network"}:t.status===401?{key:"err.session"}:t.status===429?{key:"err.tooFrequent"}:t.detail?{raw:t.detail}:t.status>=500?{key:"err.server",vars:{status:t.status}}:{key:"err.generic"}}function ke(t){let e=t.trim();return e?/cancelled\.?$/i.test(e)?null:e==="A sign-in is already in progress."?{key:"err.loginInProgress"}:e.startsWith("\u767B\u5F55\u8D85\u65F6")?{key:"err.loginTimeout"}:e.startsWith("\u767B\u5F55\u7801\u5DF2\u8FC7\u671F")?{key:"err.loginCodeExpired"}:e.startsWith("\u65E0\u6CD5\u8FDE\u63A5")?{key:"err.network"}:e.startsWith("\u4E91\u7AEF\u4E0D\u652F\u6301 CLI \u767B\u5F55")?{key:"err.loginUnsupported"}:e.startsWith("\u8BF7\u5148\u586B\u5199 Forsion \u4E91\u7AEF\u5730\u5740")?{key:"err.noCloudUrl"}:e.startsWith("Account is no longer signed in")?{key:"err.accountGone"}:{raw:e}:{key:"err.generic"}}var mt=Ht(null);function A(){let t=Gt(mt);if(!t)throw new Error("forsion-extend: page rendered outside its host root");return t}var le=()=>A().t;function ce(){let t=$(!0);return N(()=>(t.current=!0,()=>{t.current=!1}),[]),t}var un={pending:!1,error:null,success:null,captcha:!1};function P(){let t=ce(),[e,n]=v(un),r=$(!1),a=ie(async s=>{if(r.current)return;r.current=!0,n({pending:!0,error:null,success:null,captcha:!1});let l;try{l=await s()}catch(u){l={error:{raw:String(u?.message||u)}}}r.current=!1,t.current&&n({pending:!1,error:l?.error??null,success:l?.success??null,captcha:!!l?.captcha})},[]),i=ie(()=>{r.current||n(un)},[]);return{...e,run:a,clear:i}}var X=t=>({error:K(t),captcha:t.status===403&&t.code==="CAPTCHA_FAILED"});function dn(){let[t,e]=v(0),n=$(null);N(()=>()=>{n.current&&clearInterval(n.current)},[]);let r=ie((i=60)=>{n.current&&clearInterval(n.current),e(i),n.current=setInterval(()=>{e(s=>s<=1?(n.current&&clearInterval(n.current),n.current=null,0):s-1)},1e3)},[]),a=ie(()=>{n.current&&clearInterval(n.current),n.current=null,e(0)},[]);return{left:t,start:r,stop:a}}function Q(t){let[e,n]=v({state:"loading"}),r=$(0),a=$(t);a.current=t;let i=ie((u=!1)=>{let d=++r.current;u||n({state:"loading"}),(async()=>{let m;try{m=await a.current()}catch(f){m={ok:!1,status:0,code:null,detail:null,transport:String(f?.message||f)}}d===r.current&&(m.ok?n({state:"ready",data:m.data,gen:d}):Oe(m)?n({state:"signedOut"}):(m.status===401&&L().authStatus?.().catch(()=>{}),n({state:"error",fail:m})))})()},[]);N(()=>{i();let u=L().onAuthChanged?.(()=>i());return()=>{r.current++,u?.()}},[i]);let s=ie(()=>i(),[i]),l=ie(()=>i(!0),[i]);switch(e.state){case"ready":{let u=e.gen,d=m=>n(f=>f.state==="ready"&&f.gen===u?{...f,data:m(f.data)}:f);return{state:"ready",data:e.data,reload:l,update:d}}case"error":return{state:"error",error:K(e.fail),retry:s};default:return e}}var fn=`
2
+ .fx-acct { color: var(--text); }
3
+ .fx-acct .fx-panel > .settings-panel-head:last-child { border-bottom-color: transparent; }
4
+ .fx-acct .fx-panel > .fx-block + .fx-block,
5
+ .fx-acct .fx-panel > .fx-sub + .fx-block { border-top: var(--border-width) solid var(--border); }
6
+
7
+ .fx-acct .fx-row-control { gap: 8px; align-items: center; flex-wrap: wrap; }
8
+ .fx-acct .fx-row--wide .fx-row-control { flex: 0 1 460px; }
9
+ .fx-acct .fx-row-control > .fx-inline { flex: 1 1 auto; justify-content: flex-end; }
10
+ .fx-acct .fx-sub { padding: 12px 15px; }
11
+ .fx-acct .settings-control-row + .fx-sub,
12
+ .fx-acct .fx-sub--tight { padding-top: 0; }
13
+ .fx-acct .fx-sub > :first-child { margin-top: 0; }
14
+
15
+ .fx-acct .fx-muted { color: var(--text-faint); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
16
+ .fx-acct .fx-value { color: var(--text); font-size: var(--ui-font-body); line-height: var(--ui-line-body); font-variant-numeric: tabular-nums; }
17
+ .fx-acct .fx-value.is-empty { color: var(--text-faint); }
18
+ .fx-acct .fx-big { color: var(--text); font-size: var(--ui-font-title); line-height: var(--ui-line-title); font-weight: 600; font-variant-numeric: tabular-nums; }
19
+ .fx-acct .fx-grow { flex: 1 1 auto; }
20
+ .fx-acct .fx-inline { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; min-width: 0; }
21
+
22
+ .fx-acct .fx-link { display: inline-flex; align-items: center; gap: 4px; padding: 0; color: var(--accent-ink); font-size: inherit; line-height: inherit; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
23
+ .fx-acct .fx-link:disabled { opacity: 0.5; cursor: default; }
24
+ .fx-acct .fx-msg { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin-top: 8px; font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
25
+ .fx-acct .fx-msg.is-error { color: var(--danger); }
26
+ .fx-acct .fx-msg.is-ok { color: var(--green); }
27
+ .fx-acct .fx-note { margin: 0; color: var(--text-faint); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
28
+ .fx-acct .fx-note.is-warn { color: var(--warning); }
29
+ .fx-acct .fx-note.is-error { color: var(--danger); }
30
+
31
+ .fx-acct .fx-tag { display: inline-flex; align-items: center; gap: 3px; padding: 1px 7px; border: var(--border-width) solid var(--overlay-strong); border-radius: var(--radius-pill); color: var(--text-muted); font-size: var(--ui-font-caption); line-height: var(--ui-line-caption); font-weight: 500; white-space: nowrap; vertical-align: middle; }
32
+ .fx-acct .fx-tag--accent { border-color: transparent; background: var(--accent-light); color: var(--accent-ink); }
33
+ .fx-acct .fx-tag--danger { margin-left: 6px; border-color: transparent; background: var(--danger-light); color: var(--danger); }
34
+ .fx-acct .fx-status--open,
35
+ .fx-acct .fx-status--in_progress { border-color: transparent; background: var(--accent-light); color: var(--accent-ink); }
36
+ .fx-acct .fx-status--resolved { border-color: var(--green); color: var(--green); }
37
+
38
+ .fx-acct .btn.fx-danger-solid,
39
+ .fx-acct .btn.fx-danger-solid:hover { border-color: var(--danger); background: var(--danger); color: var(--on-danger); }
40
+ .fx-acct .fx-panel--danger { border-color: var(--danger-light); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
41
+ .fx-acct .fx-panel--danger .settings-panel-icon { background: var(--danger-light); color: var(--danger); }
42
+
43
+ .fx-acct .fx-input { width: 100%; min-width: 0; font-size: var(--ui-font-body); line-height: var(--ui-line-body); }
44
+ .fx-acct .fx-inline > .fx-input { flex: 1 1 160px; width: auto; }
45
+ .fx-acct .fx-input--name { max-width: 260px; }
46
+ .fx-acct .fx-input.fx-input--count { flex: 0 0 76px; width: 76px; text-align: right; font-variant-numeric: tabular-nums; }
47
+ .fx-acct .fx-input.fx-input--code { flex: 0 1 180px; width: auto; }
48
+ .fx-acct .fx-textarea { resize: vertical; min-height: 64px; font-family: inherit; }
49
+ .fx-acct .fx-form { display: grid; gap: 12px; }
50
+ .fx-acct .fx-form > .fx-seg { justify-self: start; }
51
+ .fx-acct .fx-field { display: grid; gap: 5px; min-width: 0; }
52
+ .fx-acct .fx-field > span { color: var(--text-muted); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
53
+ .fx-acct .fx-field > .fx-msg { margin-top: 0; }
54
+ .fx-acct .fx-cost { white-space: nowrap; }
55
+ .fx-acct .fx-code { padding: 3px 8px; border-radius: var(--radius-sm); background: var(--overlay-light); color: var(--text); font-family: var(--font-mono); font-size: var(--ui-font-body); line-height: var(--ui-line-body); letter-spacing: 0.06em; user-select: all; }
56
+
57
+ .fx-acct .fx-rules { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: -4px 0 0; padding: 0; list-style: none; color: var(--text-faint); font-size: var(--ui-font-caption); line-height: var(--ui-line-caption); }
58
+ .fx-acct .fx-rules li { display: inline-flex; align-items: center; gap: 5px; }
59
+ .fx-acct .fx-rules li.is-ok { color: var(--green); }
60
+ .fx-acct .fx-rules li.is-bad { color: var(--text-muted); }
61
+ .fx-acct .fx-rule-dot { width: 4px; height: 4px; margin: 0 3px; border-radius: 50%; background: currentColor; }
62
+
63
+ .fx-acct .fx-quota-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px 28px; padding: 14px 15px 16px; }
64
+ .fx-acct .fx-quota-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 7px; }
65
+ .fx-acct .fx-quota-label { color: var(--text-muted); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
66
+ .fx-acct .fx-quota-value { color: var(--text); font-size: var(--ui-font-title); line-height: var(--ui-line-title); font-weight: 600; font-variant-numeric: tabular-nums; }
67
+ .fx-acct .fx-bar { height: 6px; overflow: hidden; border-radius: var(--radius-pill); background: var(--overlay-medium); }
68
+ .fx-acct .fx-bar > span { display: block; height: 100%; border-radius: inherit; background: var(--accent-ink); transition: width var(--duration-slow) var(--ease-out); }
69
+ .fx-acct .fx-quota.is-low .fx-bar > span { background: var(--warning); }
70
+ .fx-acct .fx-quota.is-low .fx-quota-value { color: var(--warning); }
71
+ .fx-acct .fx-quota-note { margin-top: 6px; color: var(--text-faint); font-size: var(--ui-font-caption); line-height: var(--ui-line-caption); }
72
+ .fx-acct .fx-ceremony { display: flex; flex-wrap: wrap; gap: 4px 18px; margin-top: 8px; padding: 8px 11px; border-radius: var(--radius-sm); background: var(--accent-light); color: var(--text); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); font-variant-numeric: tabular-nums; }
73
+ .fx-acct .fx-ceremony b { color: var(--accent-ink); font-weight: 650; }
74
+
75
+ .fx-acct .fx-identity { display: flex; align-items: center; gap: 14px; padding: 14px 15px; }
76
+ .fx-acct .fx-avatar { position: relative; flex: 0 0 auto; width: 56px; height: 56px; display: grid; place-items: center; overflow: hidden; padding: 0; border-radius: 50%; background: var(--accent-light); color: var(--accent-ink); cursor: pointer; }
77
+ .fx-acct .fx-avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
78
+ .fx-acct .fx-avatar-initial { font-size: var(--ui-font-title); line-height: var(--ui-line-title); font-weight: 600; }
79
+ .fx-acct .fx-avatar-mask { position: absolute; inset: 0; display: grid; place-items: center; background: var(--overlay-scrim); color: #fff; opacity: 0; transition: opacity var(--duration-fast); }
80
+ .fx-acct .fx-avatar:hover .fx-avatar-mask,
81
+ .fx-acct .fx-avatar:focus-visible .fx-avatar-mask,
82
+ .fx-acct .fx-avatar:disabled .fx-avatar-mask { opacity: 1; }
83
+ .fx-acct .fx-avatar:focus-visible { outline: var(--focus-ring) solid var(--accent-ink); outline-offset: 2px; }
84
+ .fx-acct .fx-identity-main { min-width: 0; flex: 1 1 auto; display: grid; gap: 2px; }
85
+ .fx-acct .fx-identity-main > .fx-msg { margin-top: 4px; }
86
+ .fx-acct .fx-name-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
87
+ .fx-acct .fx-name { overflow: hidden; color: var(--text); font-size: var(--ui-font-title); line-height: var(--ui-line-title); font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
88
+ .fx-acct .fx-icon-btn { flex: 0 0 auto; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-sm); color: var(--text-faint); }
89
+ .fx-acct .fx-icon-btn:hover { background: var(--overlay-light); color: var(--accent-ink); }
90
+ .fx-acct .fx-link-row { display: inline-flex; align-items: center; gap: 6px; margin-right: -6px; padding: 4px 6px; border-radius: var(--radius-sm); color: var(--text); font-size: var(--ui-font-body); line-height: var(--ui-line-body); }
91
+ .fx-acct .fx-link-row > svg { color: var(--text-faint); }
92
+ .fx-acct .fx-link-row:hover { background: var(--overlay-light); color: var(--accent-ink); }
93
+ .fx-acct .fx-link-row.is-empty { color: var(--text-faint); }
94
+
95
+ .fx-acct .fx-member { display: flex; align-items: center; gap: 12px; padding: 14px 15px; }
96
+ .fx-acct .fx-tier { flex: 0 0 auto; min-width: 52px; padding: 3px 10px; border: var(--border-width) solid var(--overlay-strong); border-radius: var(--radius-pill); color: var(--text-muted); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); font-weight: 650; letter-spacing: 0.02em; text-align: center; }
97
+ .fx-acct .fx-tier--paid { border-color: transparent; background: var(--accent-light); color: var(--accent-ink); }
98
+ .fx-acct .fx-tier--pro { border-color: transparent; background: var(--action-fill); color: var(--on-action); }
99
+ .fx-acct .fx-member-copy { min-width: 0; display: grid; gap: 2px; }
100
+ .fx-acct .fx-member-copy strong { color: var(--text); font-size: var(--ui-font-heading); line-height: var(--ui-line-heading); font-weight: 600; }
101
+
102
+ .fx-acct .fx-list { display: flex; flex-direction: column; }
103
+ .fx-acct .fx-list-row { width: 100%; min-height: 48px; display: flex; align-items: center; gap: 10px; padding: 8px 15px; color: var(--text); text-align: left; }
104
+ .fx-acct .fx-list-row + .fx-list-row { border-top: var(--border-width) solid var(--border); }
105
+ .fx-acct .fx-list-row--button { cursor: pointer; transition: background var(--duration-fast); }
106
+ .fx-acct .fx-list-row--button:hover { background: var(--overlay-light); }
107
+ .fx-acct .fx-list-row--button > svg { flex: 0 0 auto; color: var(--text-faint); }
108
+ .fx-acct .fx-list-icon { flex: 0 0 auto; display: inline-flex; color: var(--text-muted); }
109
+ .fx-acct .fx-list-main { min-width: 0; flex: 1 1 auto; display: grid; gap: 2px; }
110
+ .fx-acct .fx-list-main strong { display: block; overflow: hidden; color: var(--text); font-size: var(--ui-font-body); line-height: var(--ui-line-body); font-weight: 560; text-overflow: ellipsis; white-space: nowrap; }
111
+ .fx-acct .fx-list-main small { display: block; overflow: hidden; color: var(--text-faint); font-size: var(--ui-font-caption); line-height: var(--ui-line-caption); text-overflow: ellipsis; white-space: nowrap; }
112
+ .fx-acct .fx-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: transparent; }
113
+ .fx-acct .fx-dot.is-on { background: var(--accent-ink); }
114
+ .fx-acct .fx-footer { flex-wrap: wrap; }
115
+ .fx-acct .fx-footer > .fx-muted { margin-right: auto; }
116
+ .fx-acct .fx-page-foot { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; padding: 2px 4px 8px; color: var(--text-faint); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
117
+ .fx-acct .fx-page-foot > .fx-msg { flex-basis: 100%; margin-top: 0; }
118
+
119
+ .fx-acct .fx-signin-body { min-height: 260px; }
120
+ .fx-acct .fx-signin-lead { max-width: 44ch; margin: 0; color: var(--text); font-size: var(--ui-font-body); line-height: var(--ui-line-body); }
121
+ .fx-acct .fx-device { max-width: 540px; display: flex; align-items: center; gap: 16px; margin-top: 18px; padding: 12px; border-radius: var(--radius-md); background: var(--overlay-subtle); text-align: left; }
122
+ .fx-acct .fx-sub > .fx-device { margin-top: 0; }
123
+ .fx-acct .fx-qr { flex: 0 0 auto; border-radius: var(--radius-sm); background: #fff; }
124
+ .fx-acct .fx-device-copy { min-width: 0; display: grid; gap: 8px; }
125
+ .fx-acct .fx-device-copy > p { max-width: none; margin: 0; color: var(--text-muted); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
126
+ .fx-acct .fx-device-code { display: flex; align-items: baseline; gap: 8px; color: var(--text-faint); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
127
+ .fx-acct .fx-device-code code { color: var(--text); font-family: var(--font-mono); font-size: var(--ui-font-title); line-height: var(--ui-line-title); letter-spacing: 0.12em; user-select: all; }
128
+
129
+ .fx-acct .fx-skel { display: block; border-radius: var(--radius-sm); background: var(--overlay-medium); animation: fx-acct-pulse 1.4s ease-in-out infinite; }
130
+ .fx-acct .fx-skel--icon { flex: 0 0 auto; width: 30px; height: 30px; }
131
+ .fx-acct .fx-skel--title { width: 120px; height: 12px; margin-bottom: 7px; }
132
+ .fx-acct .fx-skel--line { width: 220px; max-width: 70%; height: 9px; }
133
+ .fx-acct .fx-skel--row { width: 100%; height: 12px; }
134
+ .fx-acct .fx-skel--row + .fx-skel--row { margin-top: 10px; }
135
+ .fx-acct .fx-skel--stat { width: 64px; height: 20px; margin: 4px 0; }
136
+ @keyframes fx-acct-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
137
+
138
+ .fx-acct .fx-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); transition: opacity var(--duration-fast); }
139
+ .fx-acct .fx-stats.is-refreshing { opacity: 0.55; }
140
+ .fx-acct .fx-stat { min-width: 0; display: grid; align-content: start; gap: 2px; padding: 14px 15px; }
141
+ .fx-acct .fx-stat + .fx-stat { border-left: var(--border-width) solid var(--border); }
142
+ .fx-acct .fx-stat-label { color: var(--text-faint); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); }
143
+ .fx-acct .fx-stat-value { color: var(--text); font-size: var(--ui-font-display); line-height: var(--ui-line-display); font-weight: 600; font-variant-numeric: tabular-nums; }
144
+ .fx-acct .fx-stat-sub { color: var(--text-faint); font-size: var(--ui-font-caption); line-height: var(--ui-line-caption); }
145
+ .fx-acct .fx-table-wrap { overflow-x: auto; }
146
+ .fx-acct .fx-table { width: 100%; border-collapse: collapse; font-size: var(--ui-font-body); line-height: var(--ui-line-body); }
147
+ .fx-acct .fx-table th { padding: 8px 15px; border-bottom: var(--border-width) solid var(--border); color: var(--text-faint); font-size: var(--ui-font-meta); line-height: var(--ui-line-meta); font-weight: 500; text-align: left; }
148
+ .fx-acct .fx-table td { padding: 8px 15px; border-bottom: var(--border-width) solid var(--border); color: var(--text); overflow-wrap: anywhere; }
149
+ .fx-acct .fx-table tr:last-child td { border-bottom-color: transparent; }
150
+ .fx-acct .fx-table .is-num { width: 1%; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
151
+
152
+ .fx-acct .fx-composer { border-bottom: var(--border-width) solid var(--border); transition: background var(--duration-fast); }
153
+ .fx-acct .fx-composer.is-drag { background: var(--accent-light); }
154
+ .fx-acct .fx-thumbs { display: flex; flex-wrap: wrap; gap: 8px; }
155
+ .fx-acct .fx-thumb { position: relative; flex: 0 0 auto; width: 72px; height: 72px; overflow: hidden; padding: 0; border: var(--border-width) solid var(--overlay-medium); border-radius: var(--radius-sm); background: var(--overlay-subtle); }
156
+ .fx-acct .fx-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
157
+ .fx-acct button.fx-thumb { cursor: zoom-in; }
158
+ .fx-acct .fx-thumb > button { position: absolute; top: 3px; right: 3px; width: 18px; height: 18px; display: grid; place-items: center; border-radius: 50%; background: var(--overlay-scrim); color: #fff; }
159
+ .fx-acct .fx-back { margin-bottom: 10px; }
160
+ .fx-acct .fx-thread { display: flex; flex-direction: column; gap: 10px; padding: 14px 15px; }
161
+ .fx-acct .fx-bubble { max-width: 86%; padding: 9px 12px; border-radius: var(--radius-md); background: var(--overlay-light); }
162
+ .fx-acct .fx-bubble--user { align-self: flex-end; }
163
+ .fx-acct .fx-bubble--admin { align-self: flex-start; background: var(--accent-light); }
164
+ .fx-acct .fx-bubble-meta { margin-bottom: 4px; color: var(--text-faint); font-size: var(--ui-font-caption); line-height: var(--ui-line-caption); }
165
+ .fx-acct .fx-bubble-text { color: var(--text); font-size: var(--ui-font-body); line-height: var(--ui-line-body); white-space: pre-wrap; overflow-wrap: anywhere; }
166
+ .fx-acct .fx-bubble .fx-thumbs { margin-top: 8px; }
167
+ .fx-acct .fx-lightbox { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 24px; background: var(--overlay-scrim); cursor: zoom-out; }
168
+ .fx-acct .fx-lightbox img { max-width: 100%; max-height: 100%; border-radius: var(--radius-md); }
169
+
170
+ @media (max-width: 560px) {
171
+ .fx-acct .fx-stats { grid-template-columns: minmax(0, 1fr); }
172
+ .fx-acct .fx-stat + .fx-stat { border-left-color: transparent; border-top: var(--border-width) solid var(--border); }
173
+ .fx-acct .fx-device { flex-direction: column; align-items: flex-start; }
174
+ }
175
+ @media (prefers-reduced-motion: reduce) {
176
+ .fx-acct .fx-skel { animation: none; }
177
+ .fx-acct .fx-bar > span { transition: none; }
178
+ }
179
+ `;function Xe(t){let e=String(t||"").trim();if(!e)return"";let n=e.startsWith("+")?4:3;return e.length<=n+4?`${e.slice(0,2)}***`:`${e.slice(0,n)}****${e.slice(-4)}`}function We(t){let e=String(t||"").trim(),n=e.lastIndexOf("@");if(n<=0)return e?`${e.slice(0,1)}***`:"";let r=e.slice(0,n);return`${r.slice(0,r.length<=2?1:2)}***${e.slice(n)}`}function mn(t){let e=String(t||"").trim().toLowerCase()||"free";return e.charAt(0).toUpperCase()+e.slice(1)}var lo=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function pn(t,e){let n=String(t||"").trim(),r,a,i=/^(\d{4})-(\d{2})-(\d{2})$/.exec(n);if(i)r=Number(i[2]),a=Number(i[3]);else{let s=new Date(n);if(!n||Number.isNaN(s.getTime()))return null;let l=new Intl.DateTimeFormat("en-US",{timeZone:"Asia/Shanghai",month:"numeric",day:"numeric"}).formatToParts(s);r=Number(l.find(u=>u.type==="month")?.value),a=Number(l.find(u=>u.type==="day")?.value)}return!(r>=1&&r<=12)||!(a>=1&&a<=31)?null:e==="zh"?`${r}\u6708${a}\u65E5`:`${lo[r-1]} ${a}`}var pt=t=>t==="zh"?"zh-CN":"en-US";function gn(t){if(t==null||t==="")return null;let e=new Date(typeof t=="string"&&/^\d+$/.test(t)?Number(t):t);return Number.isNaN(e.getTime())?null:e}function hn(t,e){let n=gn(t);return n?new Intl.DateTimeFormat(pt(e),{year:"numeric",month:"short",day:"numeric"}).format(n):"\u2014"}function xe(t,e){let n=gn(t);return n?new Intl.DateTimeFormat(pt(e),{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}).format(n):"\u2014"}function W(t,e){let n=typeof t=="number"?t:Number(t);return Number.isFinite(n)?new Intl.NumberFormat(pt(e),{maximumFractionDigits:2}).format(n):"\u2014"}var fe=class extends Error{};async function bn(t,e=256){if(t.size>20971520)throw new fe;let n=URL.createObjectURL(t);try{let r=new Image;await new Promise((m,f)=>{r.onload=()=>m(),r.onerror=()=>f(new Error("image decode failed")),r.src=n});let a=r.naturalWidth,i=r.naturalHeight;if(!a||!i)throw new Error("empty image");if(a*i>5e7)throw new fe;let s=Math.min(1,e/Math.max(a,i)),l=document.createElement("canvas");l.width=Math.max(1,Math.round(a*s)),l.height=Math.max(1,Math.round(i*s));let u=l.getContext("2d");if(!u)throw new Error("canvas unavailable");u.fillStyle="#fff",u.fillRect(0,0,l.width,l.height),u.drawImage(r,0,0,l.width,l.height);let d=l.toDataURL("image/jpeg",.85);if(d.length>262144)throw new fe;return d}finally{URL.revokeObjectURL(n)}}function vn(t){let e=String(t||"").trim();if(!e)return"?";let n=Array.from(e)[0];return/[㐀-鿿]/.test(n)?n:Array.from(e).slice(0,2).join("").toUpperCase()}var co=0;function o(t,e,n,r,a,i){e||(e={});var s,l,u=e;if("ref"in u)for(l in u={},e)l=="ref"?s=e[l]:u[l]=e[l];var d={type:t,props:u,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--co,__i:-1,__u:0,__source:a,__self:i};if(typeof t=="function"&&(s=t.defaultProps))for(l in s)u[l]===void 0&&(u[l]=s[l]);return T.vnode&&T.vnode(d),d}var uo={user:"M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z M4 20c.8-3.5 4-5.5 8-5.5s7.2 2 8 5.5",gauge:"M4 16a8 8 0 1 1 16 0 M12 16l4-5 M12 16h.01",shield:"M12 3l7 3v5c0 4.5-3 8.2-7 10-4-1.8-7-5.5-7-10V6l7-3Z",chart:"M4 20V10 M10 20V4 M16 20v-7 M21 20H3",message:"M5 4h14a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-7l-5 4v-4H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1Z",card:"M4 6h16a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1Z M3 10h18 M7 15h4",coins:"M9 11a5 5 0 1 0 0-10 5 5 0 0 0 0 10Z M15.5 9.2A5 5 0 1 1 9.8 16",clock:"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Z M12 7v5l3 2",gift:"M4 11h16v9H4z M3 7h18v4H3z M12 7v13 M12 7c-1.5-3-5-3-5-1s3 1 5 1c2 0 5 1 5-1s-3.5-2-5 1",key:"M8 15a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z M11 11h10 M17 11v3 M20 11v2",laptop:"M5 5h14v10H5z M3 19h18",alert:"M12 4l9 16H3l9-16Z M12 10v4 M12 17h.01",external:"M14 4h6v6 M20 4l-9 9 M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5",copy:"M9 9h11v11H9z M5 15H4V4h11v1",check:"M5 12.5l4.5 4.5L19 7.5",chevron:"M9 6l6 6-6 6",back:"M15 6l-6 6 6 6",pencil:"M4 20h4L19 9l-4-4L4 16v4Z M13.5 6.5l4 4",plus:"M12 5v14 M5 12h14",refresh:"M20 11a8 8 0 0 0-14.3-4.9L4 8 M4 4v4h4 M4 13a8 8 0 0 0 14.3 4.9L20 16 M20 20v-4h-4",phone:"M8 3h8a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1Z M11 18h2",mail:"M4 6h16v12H4z M4 7l8 6 8-6",image:"M4 5h16v14H4z M4 16l5-5 4 4 3-3 4 4 M15.5 9.5h.01",x:"M6 6l12 12 M18 6L6 18",logout:"M15 4h4v16h-4 M10 8l-4 4 4 4 M6 12h10"};function I({name:t,size:e=14,class:n}){return o("svg",{class:n,width:e,height:e,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.8","stroke-linecap":"round","stroke-linejoin":"round","aria-hidden":"true",focusable:"false",children:o("path",{d:uo[t]})})}function Ce({size:t=12}){return o("svg",{class:"spin",width:t,height:t,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","aria-hidden":"true",focusable:"false",children:o("path",{d:"M21 12a9 9 0 1 1-6.2-8.56"})})}var me=(t=>(t[t.Border=-1]="Border",t[t.Data=0]="Data",t[t.Function=1]="Function",t[t.Position=2]="Position",t[t.Timing=3]="Timing",t[t.Alignment=4]="Alignment",t))(me||{}),fo=[0,1],yn=[1,0],_n=[2,3],wn=[3,2],mo={L:fo,M:yn,Q:_n,H:wn},po=/^\d*$/,go=/^[A-Z0-9 $%*+./:-]*$/,gt="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",xt=1,yt=40,xn=3,ho=3,Ve=40,bo=10,kn=[[-1,7,10,15,20,26,18,20,24,30,18,20,24,26,30,22,24,28,30,28,28,28,28,30,30,26,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,10,16,26,18,24,16,18,22,22,26,30,22,22,24,24,28,28,26,26,26,26,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28],[-1,13,22,18,26,18,24,18,22,20,24,28,26,24,20,30,24,28,28,26,30,28,30,30,30,30,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,17,28,22,16,22,28,26,26,24,28,24,28,22,24,24,30,28,28,26,28,30,24,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30]],Cn=[[-1,1,1,1,1,1,2,2,2,2,4,4,4,4,4,6,6,6,6,7,8,8,9,9,10,12,12,12,13,14,15,16,17,18,19,19,20,21,22,24,25],[-1,1,1,1,2,2,4,4,4,5,5,5,8,9,9,10,10,11,13,14,16,17,17,18,20,21,23,25,26,28,29,31,33,35,37,38,40,43,45,47,49],[-1,1,1,2,2,4,4,6,6,8,8,8,10,12,16,12,17,16,18,21,20,23,23,25,27,29,34,34,35,38,40,43,45,48,51,53,56,59,62,65,68],[-1,1,1,2,4,4,4,5,6,8,8,11,11,16,16,18,16,19,21,25,25,25,34,30,32,35,37,40,42,45,48,51,54,57,60,63,66,70,74,77,81]],ht=class{constructor(e,n,r,a){if(this.version=e,this.ecc=n,e<xt||e>yt)throw new RangeError("Version value out of range");if(a<-1||a>7)throw new RangeError("Mask value out of range");this.size=e*4+17;let i=Array.from({length:this.size}).fill(!1);for(let l=0;l<this.size;l++)this.modules.push(i.slice()),this.types.push(i.map(()=>0));this.drawFunctionPatterns();let s=this.addEccAndInterleave(r);if(this.drawCodewords(s),a===-1){let l=1e9;for(let u=0;u<8;u++){this.applyMask(u),this.drawFormatBits(u);let d=this.getPenaltyScore();d<l&&(a=u,l=d),this.applyMask(u)}}this.mask=a,this.applyMask(a),this.drawFormatBits(a)}size;mask;modules=[];types=[];getModule(e,n){return e>=0&&e<this.size&&n>=0&&n<this.size&&this.modules[n][e]}drawFunctionPatterns(){for(let r=0;r<this.size;r++)this.setFunctionModule(6,r,r%2===0,me.Timing),this.setFunctionModule(r,6,r%2===0,me.Timing);this.drawFinderPattern(3,3),this.drawFinderPattern(this.size-4,3),this.drawFinderPattern(3,this.size-4);let e=this.getAlignmentPatternPositions(),n=e.length;for(let r=0;r<n;r++)for(let a=0;a<n;a++)r===0&&a===0||r===0&&a===n-1||r===n-1&&a===0||this.drawAlignmentPattern(e[r],e[a]);this.drawFormatBits(0),this.drawVersion()}drawFormatBits(e){let n=this.ecc[1]<<3|e,r=n;for(let i=0;i<10;i++)r=r<<1^(r>>>9)*1335;let a=(n<<10|r)^21522;for(let i=0;i<=5;i++)this.setFunctionModule(8,i,ne(a,i));this.setFunctionModule(8,7,ne(a,6)),this.setFunctionModule(8,8,ne(a,7)),this.setFunctionModule(7,8,ne(a,8));for(let i=9;i<15;i++)this.setFunctionModule(14-i,8,ne(a,i));for(let i=0;i<8;i++)this.setFunctionModule(this.size-1-i,8,ne(a,i));for(let i=8;i<15;i++)this.setFunctionModule(8,this.size-15+i,ne(a,i));this.setFunctionModule(8,this.size-8,!0)}drawVersion(){if(this.version<7)return;let e=this.version;for(let r=0;r<12;r++)e=e<<1^(e>>>11)*7973;let n=this.version<<12|e;for(let r=0;r<18;r++){let a=ne(n,r),i=this.size-11+r%3,s=Math.floor(r/3);this.setFunctionModule(i,s,a),this.setFunctionModule(s,i,a)}}drawFinderPattern(e,n){for(let r=-4;r<=4;r++)for(let a=-4;a<=4;a++){let i=Math.max(Math.abs(a),Math.abs(r)),s=e+a,l=n+r;s>=0&&s<this.size&&l>=0&&l<this.size&&this.setFunctionModule(s,l,i!==2&&i!==4,me.Position)}}drawAlignmentPattern(e,n){for(let r=-2;r<=2;r++)for(let a=-2;a<=2;a++)this.setFunctionModule(e+a,n+r,Math.max(Math.abs(a),Math.abs(r))!==1,me.Alignment)}setFunctionModule(e,n,r,a=me.Function){this.modules[n][e]=r,this.types[n][e]=a}addEccAndInterleave(e){let n=this.version,r=this.ecc;if(e.length!==Je(n,r))throw new RangeError("Invalid argument");let a=Cn[r[0]][n],i=kn[r[0]][n],s=Math.floor(bt(n)/8),l=a-s%a,u=Math.floor(s/a),d=[],m=Ao(i);for(let c=0,g=0;c<a;c++){let h=e.slice(g,g+u-i+(c<l?0:1));g+=h.length;let x=Po(h,m);c<l&&h.push(0),d.push(h.concat(x))}let f=[];for(let c=0;c<d[0].length;c++)d.forEach((g,h)=>{(c!==u-i||h>=l)&&f.push(g[c])});return f}drawCodewords(e){if(e.length!==Math.floor(bt(this.version)/8))throw new RangeError("Invalid argument");let n=0;for(let r=this.size-1;r>=1;r-=2){r===6&&(r=5);for(let a=0;a<this.size;a++)for(let i=0;i<2;i++){let s=r-i,u=(r+1&2)===0?this.size-1-a:a;!this.types[u][s]&&n<e.length*8&&(this.modules[u][s]=ne(e[n>>>3],7-(n&7)),n++)}}}applyMask(e){if(e<0||e>7)throw new RangeError("Mask value out of range");for(let n=0;n<this.size;n++)for(let r=0;r<this.size;r++){let a;switch(e){case 0:a=(r+n)%2===0;break;case 1:a=n%2===0;break;case 2:a=r%3===0;break;case 3:a=(r+n)%3===0;break;case 4:a=(Math.floor(r/3)+Math.floor(n/2))%2===0;break;case 5:a=r*n%2+r*n%3===0;break;case 6:a=(r*n%2+r*n%3)%2===0;break;case 7:a=((r+n)%2+r*n%3)%2===0;break;default:throw new Error("Unreachable")}!this.types[n][r]&&a&&(this.modules[n][r]=!this.modules[n][r])}}getPenaltyScore(){let e=0;for(let i=0;i<this.size;i++){let s=!1,l=0,u=[0,0,0,0,0,0,0];for(let d=0;d<this.size;d++)this.modules[i][d]===s?(l++,l===5?e+=xn:l>5&&e++):(this.finderPenaltyAddHistory(l,u),s||(e+=this.finderPenaltyCountPatterns(u)*Ve),s=this.modules[i][d],l=1);e+=this.finderPenaltyTerminateAndCount(s,l,u)*Ve}for(let i=0;i<this.size;i++){let s=!1,l=0,u=[0,0,0,0,0,0,0];for(let d=0;d<this.size;d++)this.modules[d][i]===s?(l++,l===5?e+=xn:l>5&&e++):(this.finderPenaltyAddHistory(l,u),s||(e+=this.finderPenaltyCountPatterns(u)*Ve),s=this.modules[d][i],l=1);e+=this.finderPenaltyTerminateAndCount(s,l,u)*Ve}for(let i=0;i<this.size-1;i++)for(let s=0;s<this.size-1;s++){let l=this.modules[i][s];l===this.modules[i][s+1]&&l===this.modules[i+1][s]&&l===this.modules[i+1][s+1]&&(e+=ho)}let n=0;for(let i of this.modules)n=i.reduce((s,l)=>s+(l?1:0),n);let r=this.size*this.size,a=Math.ceil(Math.abs(n*20-r*10)/r)-1;return e+=a*bo,e}getAlignmentPatternPositions(){if(this.version===1)return[];{let e=Math.floor(this.version/7)+2,n=this.version===32?26:Math.ceil((this.version*4+4)/(e*2-2))*2,r=[6];for(let a=this.size-7;r.length<e;a-=n)r.splice(1,0,a);return r}}finderPenaltyCountPatterns(e){let n=e[1],r=n>0&&e[2]===n&&e[3]===n*3&&e[4]===n&&e[5]===n;return(r&&e[0]>=n*4&&e[6]>=n?1:0)+(r&&e[6]>=n*4&&e[0]>=n?1:0)}finderPenaltyTerminateAndCount(e,n,r){return e&&(this.finderPenaltyAddHistory(n,r),n=0),n+=this.size,this.finderPenaltyAddHistory(n,r),this.finderPenaltyCountPatterns(r)}finderPenaltyAddHistory(e,n){n[0]===0&&(e+=this.size),n.pop(),n.unshift(e)}};function oe(t,e,n){if(e<0||e>31||t>>>e)throw new RangeError("Value out of range");for(let r=e-1;r>=0;r--)n.push(t>>>r&1)}function ne(t,e){return(t>>>e&1)!==0}var Se=class{constructor(e,n,r){if(this.mode=e,this.numChars=n,this.bitData=r,n<0)throw new RangeError("Invalid argument");this.bitData=r.slice()}getData(){return this.bitData.slice()}},vo=[1,10,12,14],xo=[2,9,11,13],yo=[4,8,16,16];function Sn(t,e){return t[Math.floor((e+7)/17)+1]}function An(t){let e=[];for(let n of t)oe(n,8,e);return new Se(yo,t.length,e)}function _o(t){if(!Pn(t))throw new RangeError("String contains non-numeric characters");let e=[];for(let n=0;n<t.length;){let r=Math.min(t.length-n,3);oe(Number.parseInt(t.substring(n,n+r),10),r*3+1,e),n+=r}return new Se(vo,t.length,e)}function wo(t){if(!Mn(t))throw new RangeError("String contains unencodable characters in alphanumeric mode");let e=[],n;for(n=0;n+2<=t.length;n+=2){let r=gt.indexOf(t.charAt(n))*45;r+=gt.indexOf(t.charAt(n+1)),oe(r,11,e)}return n<t.length&&oe(gt.indexOf(t.charAt(n)),6,e),new Se(xo,t.length,e)}function ko(t){return t===""?[]:Pn(t)?[_o(t)]:Mn(t)?[wo(t)]:[An(So(t))]}function Pn(t){return po.test(t)}function Mn(t){return go.test(t)}function Co(t,e){let n=0;for(let r of t){let a=Sn(r.mode,e);if(r.numChars>=1<<a)return Number.POSITIVE_INFINITY;n+=4+a+r.bitData.length}return n}function So(t){t=encodeURI(t);let e=[];for(let n=0;n<t.length;n++)t.charAt(n)!=="%"?e.push(t.charCodeAt(n)):(e.push(Number.parseInt(t.substring(n+1,n+3),16)),n+=2);return e}function bt(t){if(t<xt||t>yt)throw new RangeError("Version number out of range");let e=(16*t+128)*t+64;if(t>=2){let n=Math.floor(t/7)+2;e-=(25*n-10)*n-55,t>=7&&(e-=36)}return e}function Je(t,e){return Math.floor(bt(t)/8)-kn[e[0]][t]*Cn[e[0]][t]}function Ao(t){if(t<1||t>255)throw new RangeError("Degree out of range");let e=[];for(let r=0;r<t-1;r++)e.push(0);e.push(1);let n=1;for(let r=0;r<t;r++){for(let a=0;a<e.length;a++)e[a]=vt(e[a],n),a+1<e.length&&(e[a]^=e[a+1]);n=vt(n,2)}return e}function Po(t,e){let n=e.map(r=>0);for(let r of t){let a=r^n.shift();n.push(0),e.forEach((i,s)=>n[s]^=vt(i,a))}return n}function vt(t,e){if(t>>>8||e>>>8)throw new RangeError("Byte out of range");let n=0;for(let r=7;r>=0;r--)n=n<<1^(n>>>7)*285,n^=(e>>>r&1)*t;return n}function Mo(t,e,n=1,r=40,a=-1,i=!0){if(!(xt<=n&&n<=r&&r<=yt)||a<-1||a>7)throw new RangeError("Invalid value");let s,l;for(s=n;;s++){let f=Je(s,e)*8,c=Co(t,s);if(c<=f){l=c;break}if(s>=r)throw new RangeError("Data too long")}for(let f of[yn,_n,wn])i&&l<=Je(s,f)*8&&(e=f);let u=[];for(let f of t){oe(f.mode[0],4,u),oe(f.numChars,Sn(f.mode,s),u);for(let c of f.getData())u.push(c)}let d=Je(s,e)*8;oe(0,Math.min(4,d-u.length),u),oe(0,(8-u.length%8)%8,u);for(let f=236;u.length<d;f^=253)oe(f,8,u);let m=Array.from({length:Math.ceil(u.length/8)},()=>0);return u.forEach((f,c)=>m[c>>>3]|=f<<7-(c&7)),new ht(s,e,m,a)}function En(t,e){let{ecc:n="L",boostEcc:r=!1,minVersion:a=1,maxVersion:i=40,maskPattern:s=-1,border:l=1}=e||{},u=typeof t=="string"?ko(t):Array.isArray(t)?[An(t)]:void 0;if(!u)throw new Error(`uqr only supports encoding string and binary data, but got: ${typeof t}`);let d=Mo(u,mo[n],a,i,s,r),m=Eo({version:d.version,maskPattern:d.mask,size:d.size,data:d.modules,types:d.types},l);return e?.invert&&(m.data=m.data.map(f=>f.map(c=>!c))),e?.onEncoded?.(m),m}function Eo(t,e=1){if(!e)return t;let{size:n}=t,r=n+e*2;t.size=r,t.data.forEach(i=>{for(let s=0;s<e;s++)i.unshift(!1),i.push(!1)});for(let i=0;i<e;i++)t.data.unshift(Array.from({length:r},s=>!1)),t.data.push(Array.from({length:r},s=>!1));let a=me.Border;t.types.forEach(i=>{for(let s=0;s<e;s++)i.unshift(a),i.push(a)});for(let i=0;i<e;i++)t.types.unshift(Array.from({length:r},s=>a)),t.types.push(Array.from({length:r},s=>a));return t}function B(t){return o("section",{class:`settings-panel fx-panel${t.danger?" fx-panel--danger":""}`,"aria-label":t.label,children:[o("div",{class:`settings-panel-head${t.actions?" settings-panel-head--actions":""}`,children:[t.icon&&o("span",{class:"settings-panel-icon",children:o(I,{name:t.icon,size:16})}),o("div",{children:[o("strong",{children:t.title}),t.desc&&o("p",{children:t.desc})]}),t.actions&&o("div",{class:"settings-panel-actions settings-panel-actions--wide",children:t.actions})]}),t.children]})}function V(t){return o("div",{class:`settings-control-row settings-setting-row fx-row fx-block${t.class?` ${t.class}`:""}`,children:[o("div",{class:"settings-control-copy",children:o("span",{children:[o("strong",{children:t.label}),t.desc&&o("small",{children:t.desc})]})}),t.children!==void 0&&t.children!==null&&o("div",{class:"settings-row-control fx-row-control",children:t.children})]})}function U(t){return o("div",{class:`fx-sub${t.class?` ${t.class}`:""}`,children:t.children})}function _t(t){return o("button",{type:"button",role:"switch","aria-checked":t.checked,"aria-label":t.label,class:`settings-switch${t.checked?" active":""}`,disabled:t.disabled,onClick:()=>t.onChange(!t.checked),children:o("span",{})})}function S(t){let e=t.variant??"ghost",n=e==="danger-solid"?"btn sm danger fx-danger-solid":`btn sm ${e}`;return o("button",{type:t.submit?"submit":"button",class:n,disabled:t.disabled||t.pending,"aria-busy":t.pending||void 0,"aria-label":t.label,title:t.title,"data-armed":t.armed?"true":void 0,onClick:t.onClick,children:[t.pending&&o(Ce,{}),t.children]})}var To=5e3;function pe(t){let[e,n]=v(!1),r=$(null),a=()=>{r.current&&clearTimeout(r.current),r.current=null,n(!1)};N(()=>()=>{r.current&&clearTimeout(r.current)},[]),N(()=>{(t.pending||t.disabled)&&a()},[t.pending,t.disabled]);let i=()=>{if(!e){n(!0),r.current&&clearTimeout(r.current),r.current=setTimeout(()=>{r.current=null,n(!1)},To);return}a(),t.onConfirm()},s=t.variant??"ghost";return o(S,{variant:e?s==="danger"||s==="danger-solid"?"danger-solid":"primary":s,armed:e,pending:t.pending,disabled:t.disabled,onClick:i,children:e?t.confirmLabel:t.label})}function M(t){let e=le(),{a:n}=t;return n.error?o("div",{class:"fx-msg is-error",role:"alert",children:[o("span",{children:te(n.error,e)}),n.captcha&&o("button",{type:"button",class:"fx-link",onClick:()=>void $e(t.captchaSection??"security"),children:[e("common.openInBrowser")," ",o(I,{name:"external",size:12})]})]}):n.success?o("div",{class:"fx-msg is-ok",role:"status",children:te(n.success,e)}):null}function J(t){return o("p",{class:`fx-note${t.tone?` is-${t.tone}`:""}`,children:t.children})}function ue(t){return o("div",{class:"settings-empty-row fx-block",children:t.children})}function Ae(t){let e=le(),n=t.display;return o("div",{class:`fx-quota${n.low?" is-low":""}`,children:[o("div",{class:"fx-quota-top",children:[o("span",{class:"fx-quota-label",children:t.label}),o("span",{class:"fx-quota-value",children:n.unlimited?e("common.unlimited"):n.text})]}),o("div",{class:"fx-bar",role:"progressbar","aria-label":t.label,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":n.pct,"aria-valuetext":n.unlimited?e("common.unlimited"):n.text,children:o("span",{style:{width:`${n.pct}%`}})}),t.note&&o("div",{class:"fx-quota-note",children:t.note})]})}function ge(t){return o("div",{class:"seg fx-seg",role:"radiogroup","aria-label":t.label,children:t.options.map(e=>o("button",{type:"button",role:"radio","aria-checked":e.value===t.value,class:e.value===t.value?"active":"",onClick:()=>{e.value!==t.value&&t.onChange(e.value)},children:e.label}))})}async function Io(t){try{return await navigator.clipboard.writeText(t),!0}catch{try{let e=document.createElement("textarea");e.value=t,e.setAttribute("readonly",""),e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select();let n=document.execCommand("copy");return e.remove(),n}catch{return!1}}}function Ke(t){let e=le(),[n,r]=v("idle"),a=$(null);N(()=>()=>{a.current&&clearTimeout(a.current)},[]);let i=async()=>{let s=await Io(t.text);r(s?"copied":"failed"),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>r("idle"),1800)};return o(S,{disabled:t.disabled||!t.text,onClick:()=>void i(),children:[o(I,{name:n==="copied"?"check":"copy",size:12}),n==="copied"?e("common.copied"):n==="failed"?e("common.copyFailed"):t.label]})}function Ro(t){let e=ve(()=>{try{return En(t.value,{ecc:"M",border:2})}catch{return null}},[t.value]);if(!e)return null;let n="";e.data.forEach((a,i)=>a.forEach((s,l)=>{s&&(n+=`M${l} ${i}h1v1h-1z`)}));let r=t.size??148;return o("svg",{class:"fx-qr",width:r,height:r,viewBox:`0 0 ${e.size} ${e.size}`,"shape-rendering":"crispEdges",role:"img","aria-label":t.label,children:[o("rect",{width:e.size,height:e.size,fill:"#fff"}),o("path",{d:n,fill:"#000"})]})}function wt(t){let e=le(),{device:n}=t;return o("div",{class:"fx-device",children:[o(Ro,{value:n.url,label:e("signin.qrLabel")}),o("div",{class:"fx-device-copy",children:[o("p",{children:e("signin.deviceHint")}),n.userCode&&o("div",{class:"fx-device-code",children:[o("span",{children:e("signin.code")}),o("code",{children:n.userCode})]}),o("div",{class:"fx-inline",children:[o("button",{type:"button",class:"fx-link",onClick:()=>window.open(n.url,"_blank"),children:[e("signin.openLink")," ",o(I,{name:"external",size:12})]}),o(Ke,{text:n.url,label:e("signin.copyLink")})]})]})]})}function G(){let t=le(),e=P(),[n,r]=v(null);N(()=>L().onAuthDevice?.(i=>r(i)),[]);let a=()=>void e.run(async()=>{let i=L().forsionLogin;if(!i)return{error:{key:"err.unavailable"}};try{await i()}catch(s){r(null);let l=ke(se(s));return l?{error:l}:void 0}});return o("section",{class:"settings-panel fx-panel fx-signin","aria-label":t("signin.button"),children:o("div",{class:"settings-state fx-signin-body",children:[o("span",{class:"settings-state-icon",children:o(I,{name:"user",size:18})}),o("p",{class:"fx-signin-lead",children:t("signin.desc")}),o("div",{class:"settings-state-actions",children:o(S,{variant:"primary",pending:e.pending,onClick:a,children:e.pending?t("signin.pending"):t("signin.button")})}),n&&o(wt,{device:n}),o(M,{a:e})]})})}function j(t){let e=le(),n=t.panels??2,r=t.rows??2;return o("div",{class:"fx-skeleton","aria-busy":"true","aria-label":e("common.loading"),children:Array.from({length:n},(a,i)=>o("section",{class:"settings-panel fx-panel",children:[o("div",{class:"settings-panel-head",children:[o("span",{class:"fx-skel fx-skel--icon"}),o("div",{children:[o("span",{class:"fx-skel fx-skel--title"}),o("span",{class:"fx-skel fx-skel--line"})]})]}),Array.from({length:r},(s,l)=>o("div",{class:"settings-control-row",children:o("span",{class:"fx-skel fx-skel--row"})},l))]},i))})}function Y(t){let e=le();return o("section",{class:"settings-panel fx-panel",children:o("div",{class:"settings-state fx-error-state",role:"alert",children:[o("span",{class:"settings-state-icon",children:o(I,{name:"alert",size:18})}),o("strong",{children:e("common.loadFailed")}),o("p",{children:te(t.error,e)}),o("div",{class:"settings-state-actions",children:o(S,{variant:"primary",onClick:t.onRetry,children:[o(I,{name:"refresh",size:12})," ",e("common.retry")]})})]})})}function In(){let t=Q(async()=>{let[n,r,a]=await Promise.all([k("/auth/me"),k("/membership/my"),k("/features")]);return n.ok?{ok:!0,status:n.status,data:{me:n.data,membership:r.ok?r.data?.membership??null:null,membershipFailed:!r.ok,features:a.ok&&a.data&&typeof a.data=="object"?a.data:{}}}:n});if(t.state==="loading")return o(j,{panels:3});if(t.state==="signedOut")return o(G,{});if(t.state==="error")return o(Y,{error:t.error,onRetry:t.retry});let{data:e}=t;return o(R,{children:[o(Lo,{me:e.me,onPatch:n=>t.update(r=>({...r,me:{...r.me,...n}}))}),o(Do,{membership:e.membership,failed:e.membershipFailed,payment:e.features.payment!==!1,onRetry:t.reload}),o(Fo,{}),o(No,{})]})}function Lo(t){let{t:e}=A(),{me:n}=t,r=P(),a=P(),[i,s]=v(!1),[l,u]=v(""),d=$(null),m=n.nickname||n.username,f=h=>{h&&r.run(async()=>{let x;try{x=await bn(h)}catch(_){return{error:{key:_ instanceof fe?"err.avatarTooLarge":"err.avatarInvalid"}}}let w=await k("/settings",{method:"PUT",body:{avatar:x}});return w.ok?(t.onPatch({avatar:x}),{success:{key:"account.avatar.saved"}}):{error:K(w)}})},c=()=>{a.clear(),u(m||""),s(!0)},g=()=>{let h=l.trim();if(!h||h===m){s(!1);return}a.run(async()=>{let x=await k("/settings",{method:"PUT",body:{nickname:h}});return x.ok?(t.onPatch({nickname:h}),s(!1),{success:{key:"account.nickname.saved"}}):{error:K(x)}})};return o(B,{icon:"user",title:e("account.profile.title"),desc:e("account.profile.desc"),children:[o("div",{class:"fx-identity fx-block",children:[o("button",{type:"button",class:"fx-avatar",disabled:r.pending,onClick:()=>d.current?.click(),"aria-label":e("account.avatar.change"),title:e("account.avatar.change"),children:[n.avatar?o("img",{src:n.avatar,alt:""}):o("span",{class:"fx-avatar-initial",children:vn(m)}),o("span",{class:"fx-avatar-mask",children:r.pending?o(Ce,{size:14}):o(I,{name:"pencil",size:14})})]}),o("input",{ref:d,type:"file",accept:"image/png,image/jpeg,image/webp,image/gif,image/avif",hidden:!0,onChange:h=>{let x=h.currentTarget;f(x.files?.[0]),x.value=""}}),o("div",{class:"fx-identity-main",children:[i?o("form",{class:"fx-inline",onSubmit:h=>{h.preventDefault(),g()},children:[o("input",{class:"fx-input fx-input--name",value:l,maxLength:40,autoFocus:!0,"aria-label":e("account.nickname.label"),onInput:h=>u(h.currentTarget.value),onKeyDown:h=>{h.key==="Escape"&&(h.preventDefault(),s(!1))}}),o(S,{variant:"primary",submit:!0,pending:a.pending,children:e("common.save")}),o(S,{disabled:a.pending,onClick:()=>s(!1),children:e("common.cancel")})]}):o("div",{class:"fx-name-row",children:[o("span",{class:"fx-name",children:m}),o("button",{type:"button",class:"fx-icon-btn",onClick:c,"aria-label":e("account.nickname.edit"),title:e("account.nickname.edit"),children:o(I,{name:"pencil",size:13})}),n.role==="ADMIN"&&o("span",{class:"fx-tag",children:e("account.role.admin")})]}),o("div",{class:"fx-muted",children:e("account.username",{name:n.username})}),o(M,{a}),o(M,{a:r})]})]}),o(Tn,{kind:"phone",value:n.phone}),o(Tn,{kind:"email",value:n.email})]})}function Tn(t){let{t:e,goTo:n}=A(),r=!!t.value,a=r?t.kind==="phone"?Xe(t.value):We(t.value):e("account.contact.unbound"),i=t.kind==="phone"?e("account.contact.phone"):e("account.contact.email");return o(V,{label:i,children:n?o("button",{type:"button",class:`fx-link-row${r?"":" is-empty"}`,onClick:()=>n("security"),title:e("account.contact.manage"),children:[o("span",{children:a}),o(I,{name:"chevron",size:12})]}):o("span",{class:`fx-value${r?"":" is-empty"}`,children:a})})}function Do(t){let{t:e,locale:n}=A(),r=P(),a=t.membership&&(t.membership.status===void 0||t.membership.status==="active")?t.membership:null,i=mn(a?.tier),s=i==="Free",l=s?"free":i.toLowerCase()==="pro"?"pro":"paid",u=()=>void r.run(async()=>await He("membership")?void 0:{error:{key:"err.openFailed"}});return o(B,{icon:"card",title:e("member.title"),desc:e("member.desc"),actions:t.payment&&!t.failed?o(S,{variant:"primary",pending:r.pending,onClick:u,children:e(s?"member.upgrade":"member.renew")}):void 0,children:[!t.failed&&o("div",{class:"fx-member fx-block",children:[o("span",{class:`fx-tier fx-tier--${l}`,children:i}),o("div",{class:"fx-member-copy",children:[o("strong",{children:s?e("member.freeName"):a?.plan?.name||i}),o("span",{class:"fx-muted",children:s?e("member.freeHint"):a?.expiresAt?e("member.expires",{date:hn(a.expiresAt,n)}):e("member.noExpiry")})]})]}),t.failed&&o("div",{class:"fx-sub",children:o(J,{tone:"warn",children:[e("member.loadFailed")," ",o("button",{type:"button",class:"fx-link",onClick:t.onRetry,children:e("common.retry")})]})}),r.error&&o("div",{class:"fx-sub fx-sub--tight",children:o(M,{a:r})})]})}function Fo(){let{t}=A(),e=ce(),[n,r]=v(null),[a,i]=v(!1),[s,l]=v(null),[u,d]=v(null),m=P(),f=P(),c=P(),g=!!L().authAccounts;N(()=>{let p=0,b=()=>{let E=L().authAccounts;if(!E)return;let F=++p;i(!1),E().then(O=>{F===p&&r(Array.isArray(O)?O:[])}).catch(()=>{F===p&&i(!0)})};b();let y=L().onAuthChanged?.(b),C=L().onAuthDevice?.(E=>d(E));return()=>{p++,y?.(),C?.()}},[]);let h=p=>{l(p),m.run(async()=>{let b=L().forsionSwitchAccount;if(!b)return{error:{key:"err.unavailable"}};try{await b(p)}catch(y){let C=ke(se(y));return C?{error:C}:void 0}finally{e.current&&l(null)}})},x=()=>void f.run(async()=>{let p=L().forsionLogin;if(!p)return{error:{key:"err.unavailable"}};d(null);try{await p()}catch(b){e.current&&d(null);let y=ke(se(b));return y?{error:y}:void 0}}),w=()=>void c.run(async()=>{let p=L().forsionLogout;if(!p)return{error:{key:"err.unavailable"}};try{await p()}catch(b){return{error:{raw:se(b)||t("err.generic")}}}}),_=m.pending||f.pending||c.pending;return o(B,{icon:"laptop",title:t("local.title"),desc:t("local.desc"),children:[g&&n===null&&!a&&o(ue,{children:[o(Ce,{})," ",t("common.loading")]}),a&&o("div",{class:"fx-sub",children:o(J,{tone:"warn",children:t("local.loadFailed")})}),n&&n.length===0&&o(ue,{children:t("local.empty")}),n&&n.length>0&&o("div",{class:"fx-list fx-block",role:"list",children:n.map(p=>o("div",{class:"fx-list-row",role:"listitem",children:[o("span",{class:"fx-list-icon",children:o(I,{name:"user",size:14})}),o("span",{class:"fx-list-main",children:[o("strong",{children:p.nickname||p.username||"Forsion"}),o("small",{children:[p.username&&p.nickname?p.username:null,qo(p.cloudUrl)].filter(Boolean).join(" \xB7 ")})]}),p.active?o("span",{class:"fx-tag fx-tag--accent",children:[o(I,{name:"check",size:11})," ",t("local.current")]}):o(S,{pending:s===p.id,disabled:_&&s!==p.id,onClick:()=>h(p.id),children:t("local.switch")})]},p.id))}),f.pending&&u&&o("div",{class:"fx-sub",children:o(wt,{device:u})}),o("div",{class:"settings-panel-footer fx-footer",children:[o(S,{pending:f.pending,disabled:_&&!f.pending,onClick:x,children:[o(I,{name:"plus",size:12})," ",f.pending?t("signin.pending"):t("local.add")]}),o(S,{pending:c.pending,disabled:_&&!c.pending,onClick:w,children:[o(I,{name:"logout",size:12})," ",t("local.signOut")]})]}),(m.error||f.error||c.error)&&o("div",{class:"fx-sub fx-sub--tight",children:[o(M,{a:m}),o(M,{a:f}),o(M,{a:c})]})]})}function qo(t){try{return new URL(t).host}catch{return t}}function No(){let{t}=A(),e=P();return o("div",{class:"fx-page-foot",children:[o("button",{type:"button",class:"fx-link",disabled:e.pending,onClick:()=>void e.run(async()=>await $e()?void 0:{error:{key:"err.openFailed"}}),children:[t("account.web.open")," ",o(I,{name:"external",size:12})]}),o("span",{class:"fx-muted",children:t("account.web.desc")}),o(M,{a:e})]})}function D(t){if(typeof t=="number")return Number.isFinite(t)?t:null;if(typeof t=="string"&&t.trim()!==""){let e=Number(t);return Number.isFinite(e)?e:null}return null}function Bo(t,e){let n=D(e);if(n===null||n<0)return null;if(n===0)return 0;let r=Math.max(0,D(t)??0);return Math.min(100,Math.max(0,Math.floor(r/n*100)))}var zo=15;function he(t,e){let n=Bo(t,e);if(n===null)return{unlimited:!0,pct:100,text:null,low:!1};let r=Math.max(0,D(t)??0),a=n===0&&r>0&&(D(e)??0)>0?"<1%":`${n}%`;return{unlimited:!1,pct:n,text:a,low:n<=zo}}function je(t,e){let n=D(e);if(n===null||n<=0)return null;let r=D(t);if(r===null)return null;let a=Math.max(0,r);if(a===0)return"0%";let i=a/n*100;if(i<.1)return"<0.1%";let s=Math.round(i*10)/10;return s<10?`${s.toFixed(1)}%`:`${Math.round(i).toLocaleString("en-US")}%`}var Uo=t=>t.ok?"ok":t.status===404?"hidden":"failed";function Rn(){let t=Q(async()=>{let[s,l,u,d]=await Promise.all([k("/token-quota/my"),k("/credits/balance"),k("/features"),k("/invite/my-code")]);return s.ok?{ok:!0,status:s.status,data:{quota:s.data??{},balance:l.ok?D(l.data?.balance):null,balanceFailed:!l.ok,features:u.ok&&u.data&&typeof u.data=="object"?u.data:{},invite:d.ok?d.data:null,inviteState:Uo(d)}}:s});if(t.state==="loading")return o(j,{panels:3,rows:2});if(t.state==="signedOut")return o(G,{});if(t.state==="error")return o(Y,{error:t.error,onRetry:t.retry});let{data:e,update:n}=t,r=e.quota.background,a=e.features.redemption_codes!==!1,i=e.features.payment!==!1;return o(R,{children:[o(Oo,{data:e,update:n,onFailed:t.reload}),o(Ho,{data:e,update:n,payment:i,onRetry:t.reload}),r?.modelId?o(Xo,{bg:r,update:n}):null,(e.inviteState!=="hidden"||a)&&o(Wo,{data:e,update:n,redeemEnabled:a,onRedeemed:t.reload})]})}function Oo(t){let{t:e,locale:n}=A(),r=t.data.quota,a=he(r.dailyRemaining,r.dailyLimit),i=he(r.weeklyRemaining,r.weeklyLimit),s=pn(r.weeklyResetAt,n),l=Math.max(0,D(r.resetCards)??0),u=D(r.resetCardPricePoints)??100,d=P(),m=P(),[f,c]=v(null),[g,h]=v("1"),x=/^\d+$/.test(g.trim())?Number(g.trim()):NaN,w=Number.isInteger(x)&&x>=1&&x<=50,_=w?x*u:null,p=t.data.balance,b=_!==null&&p!==null&&p<_,y=()=>void d.run(async()=>{let F={daily:a,weekly:i};c(null);let O=L(),re=await Ue(O.accountUseResetCard?()=>O.accountUseResetCard("both"):null,()=>k("/token-quota/reset-card/use",{method:"POST",body:{type:"both"}}));if(!re.ok)return t.onFailed(),X(re);let H=re.data?.quota,Z=D(re.data?.resetCards);return t.update(Ge=>({...Ge,quota:{...Ge.quota,...H??{},resetCards:Z??Ge.quota.resetCards}})),H&&c({before:F,after:{daily:he(H.dailyRemaining,H.dailyLimit),weekly:he(H.weeklyRemaining,H.weeklyLimit)},cards:Z}),{success:{key:"card.used"}}}),C=()=>void m.run(async()=>{if(!w)return{error:{key:"err.invalidCount"}};let F=await k("/points/exchange-reset-cards",{method:"POST",body:{count:x}});return F.ok?(t.update(O=>({...O,quota:{...O.quota,resetCards:D(F.data?.resetCards)??O.quota.resetCards},balance:D(F.data?.newPointsBalance)??O.balance})),h("1"),{success:{key:"card.exchanged",vars:{n:D(F.data?.cardsGranted)??x}}}):(t.onFailed(),X(F))}),E=F=>F.unlimited?e("common.unlimited"):F.text;return o(B,{icon:"gauge",title:e("quota.ai.title"),desc:e("quota.ai.desc"),children:[o("div",{class:"fx-quota-list fx-block",children:[o(Ae,{label:e("common.today"),display:a,note:a.unlimited?null:e("quota.resetDaily")}),o(Ae,{label:e("common.thisWeek"),display:i,note:i.unlimited||!s?null:e("quota.resetWeekly",{date:s})})]}),o(V,{label:e("card.title"),desc:e("card.desc"),children:[o("span",{class:"fx-value","data-testid":"reset-card-count",children:e("card.owned",{n:l})}),o(pe,{label:e("card.use"),confirmLabel:e("card.useConfirm"),pending:d.pending,disabled:l<=0,onConfirm:y})]}),l<=0&&!d.success&&o(U,{children:o(J,{children:e("card.noneHint")})}),(d.error||d.success)&&o(U,{children:[o(M,{a:d}),d.success&&f&&o("div",{class:"fx-ceremony",role:"status",children:[o("span",{children:[e("common.today")," ",o("b",{children:E(f.before.daily)})," \u2192 ",o("b",{children:E(f.after.daily)})]}),o("span",{children:[e("common.thisWeek")," ",o("b",{children:E(f.before.weekly)})," \u2192 ",o("b",{children:E(f.after.weekly)})]}),f.cards!==null&&o("span",{class:"fx-muted",children:e("card.left",{n:f.cards})})]})]}),o(V,{label:e("card.exchange"),desc:e("card.price",{price:W(u,n)}),class:"fx-row--wide",children:[o("input",{class:"fx-input fx-input--count",type:"number",inputMode:"numeric",min:1,max:50,step:1,value:g,"aria-label":e("card.count"),onInput:F=>{h(F.currentTarget.value),m.clear()}}),o("span",{class:"fx-muted fx-cost",children:_!==null?e("card.cost",{cost:W(_,n)}):e("card.countHint")}),o(pe,{label:e("card.exchangeButton"),confirmLabel:e("card.exchangeConfirm",{cost:_!==null?W(_,n):"\u2014"}),pending:m.pending,disabled:!w||b,onConfirm:C})]}),(b||m.error||m.success)&&o(U,{children:[b&&!m.error&&o(J,{tone:"warn",children:e("err.insufficientPoints")}),o(M,{a:m})]})]})}function Ln(t,e,n){let r=P(),[a,i]=v(null);return{checked:a??t,toggle:l=>{i(l),r.run(async()=>{let u=await e(l);if(i(null),!u.ok)return X(u);n(l)})},action:r}}function Ho(t){let{t:e,locale:n}=A(),r=P(),a=Ln(!!t.data.quota.pointsAutoDeduct,s=>k("/token-quota/auto-deduct",{method:"POST",body:{enabled:s}}),s=>t.update(l=>({...l,quota:{...l.quota,pointsAutoDeduct:s}}))),i=()=>void r.run(async()=>await He("credits")?void 0:{error:{key:"err.openFailed"}});return o(B,{icon:"coins",title:e("points.title"),desc:e("points.desc"),actions:t.payment?o(S,{variant:"primary",pending:r.pending,onClick:i,children:e("points.recharge")}):void 0,children:[o(V,{label:e("points.balance"),children:t.data.balance!==null?o("span",{class:"fx-big","data-testid":"points-balance",children:W(t.data.balance,n)}):o("span",{class:"fx-value is-empty",children:[e("points.balanceFailed")," ",o("button",{type:"button",class:"fx-link",onClick:t.onRetry,children:e("common.retry")})]})}),o(V,{label:e("points.autoDeduct"),desc:e("points.autoDeductDesc"),children:o(_t,{checked:a.checked,disabled:a.action.pending,label:e("points.autoDeduct"),onChange:a.toggle})}),(a.action.error||r.error)&&o(U,{children:[o(M,{a:a.action}),o(M,{a:r})]})]})}var $o=[5,10,20];function Xo(t){let{t:e}=A(),{bg:n}=t,r=he(n.dailyRemaining,n.dailyLimit),a=he(n.weeklyRemaining,n.weeklyLimit),i=P(),[s,l]=v(null),u=Ln(!!n.autoMain,m=>{let f=L();return Ue(f.accountBgAutoMain?()=>f.accountBgAutoMain(m):null,()=>k("/token-quota/background/auto-main",{method:"POST",body:{enabled:m}}))},m=>t.update(f=>({...f,quota:{...f.quota,background:{...f.quota.background??{},autoMain:m}}}))),d=m=>{l(m),i.run(async()=>{let f=L(),c=await Ue(f.accountBgConvert?()=>f.accountBgConvert(m):null,()=>k("/token-quota/background/convert",{method:"POST",body:{percent:m}}));if(l(null),!c.ok)return X(c);let g=c.data?.quota;return g&&t.update(x=>({...x,quota:{...x.quota,...g,resetCards:x.quota.resetCards,resetCardPricePoints:x.quota.resetCardPricePoints}})),{success:{key:"bg.converted",vars:{pct:m}}}})};return o(B,{icon:"clock",title:e("bg.title"),desc:e("bg.desc"),children:[o("div",{class:"fx-quota-list fx-block",children:[o(Ae,{label:e("common.today"),display:r}),o(Ae,{label:e("common.thisWeek"),display:a})]}),o(V,{label:e("bg.autoMain"),desc:e("bg.autoMainDesc"),children:o(_t,{checked:u.checked,disabled:u.action.pending,label:e("bg.autoMain"),onChange:u.toggle})}),o(V,{label:e("bg.convert"),desc:e("bg.convertDesc"),class:"fx-row--wide",children:$o.map(m=>o(pe,{label:`${m}%`,confirmLabel:e("bg.convertConfirm",{pct:m}),pending:i.pending&&s===m,disabled:i.pending&&s!==m,onConfirm:()=>d(m)},m))}),(i.error||i.success||u.action.error)&&o(U,{children:[o(M,{a:u.action}),o(M,{a:i})]})]})}function Wo(t){let{t:e,locale:n}=A(),{invite:r,inviteState:a}=t.data,[i,s]=v(null),[l,u]=v(""),[d,m]=v(""),f=P(),c=P(),g=P();N(()=>{let p=!0;return L().authStatus?.().then(b=>{p&&s(b?.cloudUrl?b.cloudUrl.replace(/\/+$/,""):null)}).catch(()=>{}),()=>{p=!1}},[]);let h=async()=>{let p=await k("/invite/my-code");return t.update(b=>({...b,invite:p.ok?p.data:b.invite,inviteState:p.ok?"ok":p.status===404?"hidden":b.inviteState})),p},x=()=>void f.run(async()=>{let p=l.trim();if(!p)return{error:{key:"err.inviteEmpty"}};let b=await k("/invite/claim",{method:"POST",body:{code:p}});return b.ok?(u(""),h(),{success:{key:"invite.claimed"}}):X(b)}),w=()=>void c.run(async()=>{let p=d.trim();if(!p)return{error:{key:"err.redeemEmpty"}};let b=await k("/redemption/redeem",{method:"POST",body:{code:p}});if(!b.ok)return X(b);m(""),t.onRedeemed();let y=[],C=D(b.data?.creditsAmount);C&&y.push(e("redeem.gotPoints",{n:W(C,n)})),b.data?.membershipPlanId&&y.push(e("redeem.gotMembership"));for(let E of Array.isArray(b.data?.items)?b.data.items:[]){let F=(n==="zh"?E?.label?.zh:E?.label?.en)||E?.label?.zh||E?.label?.en||E?.kind;F&&y.push(F)}return{success:y.length?{key:"redeem.successWith",vars:{what:y.join(n==="zh"?"\u3001":", ")}}:{key:"redeem.success"}}}),_=r?.code&&i?`${i}/auth?invite=${encodeURIComponent(r.code)}`:"";return o(B,{icon:"gift",title:e("invite.title"),desc:e("invite.desc"),children:[a==="ok"&&r?.code&&o(V,{label:e("invite.myCode"),desc:e("invite.count",{n:W(D(r.invitedCount)??0,n)}),class:"fx-row--wide",children:[o("code",{class:"fx-code","data-testid":"invite-code",children:r.code}),o(Ke,{text:r.code,label:e("invite.copyCode")}),o(Ke,{text:_,label:e("invite.copyLink"),disabled:!_})]}),a==="failed"&&o(U,{children:o(J,{tone:"warn",children:[e("invite.loadFailed")," ",o("button",{type:"button",class:"fx-link",disabled:g.pending,onClick:()=>void g.run(async()=>{await h()}),children:e("common.retry")})]})}),a==="ok"&&r?.claim?.eligible&&o(V,{label:e("invite.claim"),desc:e("invite.claimDesc"),class:"fx-row--wide",children:o("form",{class:"fx-inline",onSubmit:p=>{p.preventDefault(),x()},children:[o("input",{class:"fx-input",value:l,placeholder:e("invite.claimPlaceholder"),"aria-label":e("invite.claim"),onInput:p=>u(p.currentTarget.value)}),o(S,{submit:!0,pending:f.pending,children:e("invite.claimSubmit")})]})}),(f.error||f.success)&&o(U,{children:o(M,{a:f})}),t.redeemEnabled&&o(V,{label:e("redeem.title"),desc:e("redeem.desc"),class:"fx-row--wide",children:o("form",{class:"fx-inline",onSubmit:p=>{p.preventDefault(),w()},children:[o("input",{class:"fx-input",value:d,placeholder:e("redeem.placeholder"),"aria-label":e("redeem.title"),onInput:p=>m(p.currentTarget.value)}),o(S,{submit:!0,pending:c.pending,children:e("redeem.submit")})]})}),(c.error||c.success)&&o(U,{children:o(M,{a:c})})]})}var Vo=/^1[3-9]\d{9}$|^\+[1-9]\d{6,14}$/,Jo=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,Dn=(t,e)=>t==="phone"?Vo.test(e):Jo.test(e),Pe=(t,e)=>t==="phone"?Xe(e):We(e);function qn(){let t=Q(()=>k("/auth/me"));if(t.state==="loading")return o(j,{panels:3,rows:2});if(t.state==="signedOut")return o(G,{});if(t.state==="error")return o(Y,{error:t.error,onRetry:t.retry});let e=t.data;return o(R,{children:[o(Ko,{me:e,onBound:(n,r)=>t.update(a=>({...a,[n]:r}))}),o(Qo,{me:e}),o(er,{}),o(tr,{me:e})]})}function Ct(){let t=dn(),e=P();return{cd:t,a:e,send:(a,i,s)=>e.run(async()=>{let l=await k("/auth/send-code",{method:"POST",body:{target:a,type:i,purpose:s}});return l.ok?(t.start(60),{success:{key:"sec.codeSent"}}):X(l)}),reset:()=>{t.stop(),e.clear()}}}function Ko(t){let{t:e}=A(),[n,r]=v(null),[a,i]=v(null);return o(B,{icon:"key",title:e("sec.methods.title"),desc:e("sec.methods.desc"),children:["phone","email"].map(s=>{let l=t.me[s];return o(R,{children:[o(V,{label:e(s==="phone"?"account.contact.phone":"account.contact.email"),desc:l?Pe(s,l):e("account.contact.unbound"),children:o(S,{onClick:()=>{i(null),r(n===s?null:s)},children:e(n===s?"common.cancel":l?"sec.change":"sec.bind")})}),n===s&&o(jo,{kind:s,current:l??null,onDone:u=>{t.onBound(s,u),r(null),i(s)}}),a===s&&n!==s&&o(U,{children:o("div",{class:"fx-msg is-ok",role:"status",children:e(s==="phone"?"sec.phoneBound":"sec.emailBound")})})]},s)})})}function jo(t){let{t:e}=A(),{kind:n}=t,[r,a]=v(""),[i,s]=v(""),l=Ct(),u=P(),d=r.trim(),m=n==="phone"?"err.phoneInvalid":"err.emailInvalid",f=()=>{if(!Dn(n,d)){l.a.run(async()=>({error:{key:m}}));return}l.send(d,n,"bind")},c=()=>void u.run(async()=>{if(!Dn(n,d))return{error:{key:m}};if(!i.trim())return{error:{key:"err.codeRequired"}};let g=n==="phone"?{phone:d,verification_code:i.trim()}:{email:d,verification_code:i.trim()},h=await k(n==="phone"?"/auth/bind-phone":"/auth/bind-email",{method:"POST",body:g});if(!h.ok)return X(h);t.onDone(d)});return o(U,{class:"fx-form",children:[o("label",{class:"fx-field",children:[o("span",{children:t.current?e(n==="phone"?"sec.newPhone":"sec.newEmail"):e(n==="phone"?"sec.phone":"sec.email")}),o("input",{class:"fx-input",type:n==="phone"?"tel":"email",value:r,autoComplete:"off",placeholder:e(n==="phone"?"sec.phonePlaceholder":"sec.emailPlaceholder"),onInput:g=>a(g.currentTarget.value)})]}),o(St,{code:i,setCode:s,sender:l,onSend:f}),o("div",{class:"fx-inline",children:o(S,{variant:"primary",pending:u.pending,onClick:c,children:e("sec.bindSubmit")})}),o(M,{a:u})]})}function St(t){let{t:e}=A(),{cd:n,a:r}=t.sender;return o("div",{class:"fx-field",children:[o("span",{children:t.label??e("sec.code")}),o("div",{class:"fx-inline",children:[o("input",{class:"fx-input fx-input--code",inputMode:"numeric",autoComplete:"one-time-code",value:t.code,placeholder:e("sec.codePlaceholder"),"aria-label":t.label??e("sec.code"),onInput:a=>t.setCode(a.currentTarget.value)}),o(S,{pending:r.pending,disabled:n.left>0||t.disabled,onClick:t.onSend,children:n.left>0?e("sec.resendIn",{s:n.left}):e("sec.sendCode")})]}),o(M,{a:r})]})}function Yo(t){let{t:e}=A(),n=an(t.value),r=t.value.length>0,a=[[n.length,e("pw.req.length",{min:8,max:64})],[n.lower,e("pw.req.lower")],[n.upper,e("pw.req.upper")],[n.special,e("pw.req.special")],[n.space,e("pw.req.space")]];return o("ul",{class:"fx-rules","aria-label":e("pw.rulesLabel"),children:a.map(([i,s])=>o("li",{class:i?"is-ok":r?"is-bad":"",children:[i?o(I,{name:"check",size:11}):r?o(I,{name:"x",size:11}):o("span",{class:"fx-rule-dot","aria-hidden":"true"}),o("span",{children:s})]},s))})}function Nn(t,e){let n=rn(t);return n.ok?t!==e?{error:{key:"pw.mismatch"}}:null:{error:{key:ft[n.rule]}}}function Qo(t){let{t:e}=A(),n=["phone","email"].filter(l=>!!t.me[l]),[r,a]=v("current"),[i,s]=v(!1);return o(B,{icon:"shield",title:e("pw.title"),desc:e("pw.desc",{min:8,max:64}),actions:o(S,{onClick:()=>s(!i),children:e(i?"common.cancel":"pw.change")}),children:i&&o(U,{class:"fx-form",children:[o(ge,{label:e("pw.modeLabel"),value:r,onChange:a,options:[{value:"current",label:e("pw.mode.current")},{value:"code",label:e("pw.mode.code")}]}),r==="current"?o(Go,{onDone:()=>s(!1)}):n.length?o(Zo,{me:t.me,targets:n,onDone:()=>s(!1)}):o(J,{children:e("pw.codeNeedsContact")})]})})}function Bn(t){let{t:e}=A();return o(R,{children:[o("label",{class:"fx-field",children:[o("span",{children:e("pw.new")}),o("input",{class:"fx-input",type:"password",autoComplete:"new-password",value:t.pw,maxLength:72,onInput:n=>t.setPw(n.currentTarget.value)})]}),o(Yo,{value:t.pw}),o("label",{class:"fx-field",children:[o("span",{children:e("pw.confirm")}),o("input",{class:"fx-input",type:"password",autoComplete:"new-password",value:t.confirm,onInput:n=>t.setConfirm(n.currentTarget.value)})]})]})}function Go(t){let{t:e}=A(),[n,r]=v(""),[a,i]=v(""),[s,l]=v(""),u=P(),[d,m]=v(!1),f=()=>void u.run(async()=>{if(!n)return{error:{key:"pw.currentRequired"}};let c=Nn(a,s);if(c)return c;let g=await k("/auth/password",{method:"PUT",body:{currentPassword:n,newPassword:a}});return g.ok?(r(""),i(""),l(""),m(!0),{success:{key:"pw.changed"}}):g.status===404?{error:{key:"pw.noPasswordYet"}}:X(g)});return o(R,{children:[o("label",{class:"fx-field",children:[o("span",{children:e("pw.current")}),o("input",{class:"fx-input",type:"password",autoComplete:"current-password",value:n,onInput:c=>r(c.currentTarget.value)})]}),o(Bn,{pw:a,setPw:i,confirm:s,setConfirm:l}),o("div",{class:"fx-inline",children:[o(S,{variant:"primary",pending:u.pending,onClick:f,children:e("pw.submit")}),d&&o(S,{onClick:t.onDone,children:e("common.done")})]}),o(M,{a:u})]})}function Zo(t){let{t:e}=A(),[n,r]=v(t.targets[0]),[a,i]=v(""),[s,l]=v(""),[u,d]=v(""),m=Ct(),f=P(),[c,g]=v(!1),h=t.me[n]||"",x=()=>void f.run(async()=>{if(!a.trim())return{error:{key:"err.codeRequired"}};let w=Nn(s,u);if(w)return w;let _=n==="phone"?{phone:h,code:a.trim(),newPassword:s}:{email:h,code:a.trim(),newPassword:s},p=await k("/auth/reset-password",{method:"POST",body:_});return p.ok?(i(""),l(""),d(""),g(!0),{success:{key:"pw.changed"}}):X(p)});return o(R,{children:[t.targets.length>1?o(ge,{label:e("pw.via"),value:n,onChange:w=>{r(w),i(""),m.reset()},options:t.targets.map(w=>({value:w,label:Pe(w,t.me[w])}))}):o(J,{children:e("pw.codeTo",{target:Pe(n,h)})}),o(St,{code:a,setCode:i,sender:m,onSend:()=>void m.send(h,n,"reset_password")}),o(Bn,{pw:s,setPw:l,confirm:u,setConfirm:d}),o("div",{class:"fx-inline",children:[o(S,{variant:"primary",pending:f.pending,onClick:x,children:e("pw.submitReset")}),c&&o(S,{onClick:t.onDone,children:e("common.done")})]}),o(M,{a:f})]})}function er(){let{t}=A(),e=P(),n=()=>void e.run(async()=>{let r=await k("/auth/logout-all",{method:"POST"});if(!r.ok)return X(r);try{await L().forsionLogout?.()}catch(a){return{error:{raw:se(a)}}}return{success:{key:"sec.logoutAllDone"}}});return o(B,{icon:"laptop",title:t("sec.devices.title"),desc:t("sec.devices.desc"),children:[o(V,{label:t("sec.logoutAll"),desc:t("sec.logoutAllDesc"),children:o(pe,{label:t("sec.logoutAll"),confirmLabel:t("sec.logoutAllConfirm"),pending:e.pending,onConfirm:n})}),(e.error||e.success)&&o(U,{children:o(M,{a:e})})]})}function tr(t){let{t:e}=A(),n=["phone","email"].filter(_=>!!t.me[_]),[r,a]=v(!1),[i,s]=v(n.length?"code":"password"),[l,u]=v(n[0]??null),[d,m]=v(""),[f,c]=v(""),g=Ct(),h=P(),x=l&&t.me[l]||"",w=()=>void h.run(async()=>{if(i==="code"&&!d.trim())return{error:{key:"err.codeRequired"}};if(i==="password"&&!f)return{error:{key:"pw.currentRequired"}};let _=await k("/auth/delete-account",{method:"POST",body:i==="code"?{verification_code:d.trim()}:{password:f}});if(!_.ok)return X(_);try{await L().forsionLogout?.()}catch{}return{success:{key:"del.done"}}});return o(B,{icon:"alert",danger:!0,title:e("del.title"),desc:e("del.desc"),actions:o(S,{variant:"danger",onClick:()=>{a(!r),h.clear()},children:e(r?"common.cancel":"del.start")}),children:r&&o(U,{class:"fx-form",children:[o(J,{tone:"error",children:e("del.warn")}),n.length>0&&o(ge,{label:e("del.methodLabel"),value:i,onChange:s,options:[{value:"code",label:e("del.byCode")},{value:"password",label:e("del.byPassword")}]}),i==="code"&&l?o(R,{children:[n.length>1&&o(ge,{label:e("pw.via"),value:l,onChange:_=>{u(_),m(""),g.reset()},options:n.map(_=>({value:_,label:Pe(_,t.me[_])}))}),o(St,{code:d,setCode:m,sender:g,label:e("del.codeLabel",{target:Pe(l,x)}),onSend:()=>void g.send(x,l,"delete_account")})]}):o("label",{class:"fx-field",children:[o("span",{children:e("del.passwordLabel")}),o("input",{class:"fx-input",type:"password",autoComplete:"current-password",value:f,onInput:_=>c(_.currentTarget.value)})]}),o("div",{class:"fx-inline",children:o(pe,{variant:"danger",label:e("del.submit"),confirmLabel:e("del.confirm"),pending:h.pending,onConfirm:w})}),o(M,{a:h})]})})}var Un=20;function On(){let t=Q(async()=>{let[e,n]=await Promise.all([k("/token-quota/my"),k(`/token-quota/my/logs?limit=${Un}&offset=0`)]);if(!e.ok)return e;let r=n.ok&&Array.isArray(n.data?.logs)?n.data.logs:null;return{ok:!0,status:e.status,data:{dailyLimit:D(e.data?.dailyLimit),logs:r,total:n.ok?D(n.data?.total)??r?.length??0:0,logsFail:n.ok?null:n}}});return t.state==="loading"?o(j,{panels:3,rows:2}):t.state==="signedOut"?o(G,{}):t.state==="error"?o(Y,{error:t.error,onRetry:t.retry}):o(R,{children:[o(nr,{dailyLimit:t.data.dailyLimit}),o(rr,{base:t.data,onRetry:t.reload})]})}function nr(t){let{t:e,locale:n}=A(),[r,a]=v(30),[i,s]=v({state:"loading"}),[l,u]=v(!1),[d,m]=v(0),f=$(0);N(()=>{let b=++f.current;return u(!0),k(`/usage/stats?days=${r}`).then(y=>{b===f.current&&(u(!1),s(y.ok?{state:"ready",data:y.data??{}}:{state:"error",fail:y}))}),()=>{f.current++}},[r,d]);let c=t.dailyLimit!==null&&t.dailyLimit<0?"usage.unlimitedNote":je(1,t.dailyLimit)===null?"usage.noLimitNote":null,g=b=>je(b,t.dailyLimit)??"\u2014",h=o(ge,{label:e("usage.range"),value:r,onChange:a,options:[{value:7,label:e("usage.days",{n:7})},{value:30,label:e("usage.days",{n:30})},{value:90,label:e("usage.days",{n:90})}]}),x=i.state==="ready"?i.data:null,w=(x?.byModel??[]).filter(Boolean),_=(x?.byProject??[]).filter(Boolean),p=D(x?.successRate);return o(R,{children:[o(B,{icon:"chart",title:e("usage.overview.title"),desc:e("usage.overview.desc"),actions:h,children:[i.state==="error"?o("div",{class:"fx-sub",children:o("div",{class:"fx-msg is-error",role:"alert",children:[o("span",{children:te(K(i.fail),e)}),o("button",{type:"button",class:"fx-link",onClick:()=>m(b=>b+1),children:e("common.retry")})]})}):o("div",{class:`fx-stats fx-block${l&&x?" is-refreshing":""}`,"aria-busy":l||void 0,children:[o(At,{label:e("usage.requests"),value:x?W(D(x.totalRequests)??0,n):null,testId:"usage-requests"}),o(At,{label:e("usage.successRate"),value:x?p===null?"\u2014":`${p.toFixed(1)}%`:null}),o(At,{label:e("usage.consumption"),value:x?g(x.totalPointsCost):null,sub:e("usage.ofToday"),testId:"usage-consumption"})]}),c&&o("div",{class:"fx-sub fx-sub--tight",children:o(J,{children:e(c)})})]}),i.state!=="error"&&o(R,{children:[o(B,{icon:"gauge",title:e("usage.byModel.title"),desc:e("usage.byModel.desc"),children:o(zn,{loading:!x,empty:e("usage.empty"),head:[e("usage.col.model"),e("usage.col.requests"),e("usage.col.consumption")],rows:w.map(b=>[b.modelName||b.modelId||"\u2014",W(D(b.count)??0,n),g(b.pointsCost)])})}),o(B,{icon:"laptop",title:e("usage.byApp.title"),desc:e("usage.byApp.desc"),children:o(zn,{loading:!x,empty:e("usage.empty"),head:[e("usage.col.app"),e("usage.col.requests"),e("usage.col.consumption")],rows:_.map(b=>[Hn(b.projectSource,e("usage.appUnknown")),W(D(b.count)??0,n),g(b.pointsCost)])})})]})]})}var or={tangu:"Tangu","ai-studio":"Forsion AI Studio",desktop:"Forsion Desktop",amadeus:"Amadeus",notebase:"Notebase",calendar:"Forsion Calendar",chat:"Forsion Chat",desk:"Forsion Desk","photo-studio":"Photo Studio",connect:"Forsion Connect"},Hn=(t,e)=>!t||t==="unknown"?e:or[t]??t;function At(t){return o("div",{class:"fx-stat",children:[o("span",{class:"fx-stat-label",children:t.label}),t.value===null?o("span",{class:"fx-skel fx-skel--stat"}):o("strong",{class:"fx-stat-value","data-testid":t.testId,children:t.value}),t.sub&&o("span",{class:"fx-stat-sub",children:t.sub})]})}function zn(t){return t.loading?o("div",{class:"fx-sub",children:[o("span",{class:"fx-skel fx-skel--row"}),o("span",{class:"fx-skel fx-skel--row"})]}):t.rows.length?o("div",{class:"fx-table-wrap fx-block",children:o("table",{class:"fx-table",children:[o("thead",{children:o("tr",{children:t.head.map((e,n)=>o("th",{class:n?"is-num":"",children:e},n))})}),o("tbody",{children:t.rows.map((e,n)=>o("tr",{children:e.map((r,a)=>o("td",{class:a?"is-num":"",children:r},a))},n))})]})}):o(ue,{children:t.empty})}function rr(t){let{t:e,locale:n}=A(),r=ce(),[a,i]=v(t.base.logs??[]),[s,l]=v(t.base.total),u=P();N(()=>{i(t.base.logs??[]),l(t.base.total)},[t.base]);let d=()=>void u.run(async()=>{let f=await k(`/token-quota/my/logs?limit=${Un}&offset=${a.length}`);if(!f.ok)return{error:K(f)};let c=Array.isArray(f.data?.logs)?f.data.logs:[];r.current&&(i(g=>[...g,...c]),l(g=>c.length?D(f.data?.total)??g:a.length))}),m=t.base.dailyLimit;return o(B,{icon:"clock",title:e("usage.recent.title"),desc:e("usage.recent.desc"),children:[t.base.logsFail?o("div",{class:"fx-sub",children:o("div",{class:"fx-msg is-error",role:"alert",children:[o("span",{children:te(K(t.base.logsFail),e)}),o("button",{type:"button",class:"fx-link",onClick:t.onRetry,children:e("common.retry")})]})}):a.length===0?o(ue,{children:e("usage.recentEmpty")}):o("div",{class:"fx-list fx-block",role:"list",children:a.map((f,c)=>o("div",{class:"fx-list-row",role:"listitem",children:[o("span",{class:"fx-list-main",children:[o("strong",{children:[f.modelName||f.modelId||"\u2014",f.success===!1&&o("span",{class:"fx-tag fx-tag--danger",children:e("usage.failed")})]}),o("small",{children:[xe(f.createdAt,n),Hn(f.projectSource,e("usage.appUnknown"))].join(" \xB7 ")})]}),o("span",{class:"fx-value",children:je(f.pointsCost,m)??"\u2014"})]},f.id??c))}),a.length>0&&o("div",{class:"settings-panel-footer fx-footer",children:[o("span",{class:"fx-muted",children:e("usage.shown",{shown:W(a.length,n),total:W(Math.max(s,a.length),n)})}),a.length<s&&o(S,{pending:u.pending,onClick:d,children:e("common.loadMore")})]}),u.error&&o("div",{class:"fx-sub fx-sub--tight",children:o(M,{a:u})})]})}var Me=20,Ye=5,ar=5*1024*1024,Qe=1e4,ir={open:"fb.status.open",in_progress:"fb.status.in_progress",resolved:"fb.status.resolved",closed:"fb.status.closed"};function Xn(t){let{t:e}=A(),n=t.status||"open",r=ir[n];return o("span",{class:`fx-tag fx-status fx-status--${n}`,children:r?e(r):n})}function Wn(){let[t,e]=v(null),n=Q(async()=>{let r=await k(`/feedback?limit=${Me}&offset=0`);return r.ok?{ok:!0,status:r.status,data:Array.isArray(r.data?.tickets)?r.data.tickets:[]}:r});return n.state==="loading"?o(j,{panels:1,rows:3}):n.state==="signedOut"?o(G,{}):n.state==="error"?o(Y,{error:n.error,onRetry:n.retry}):t?o(dr,{id:t,onBack:()=>{e(null),n.reload()}}):o(sr,{first:n.data,onOpen:e,onChanged:n.reload})}function sr(t){let{t:e,locale:n}=A(),r=ce(),[a,i]=v(t.first),[s,l]=v(t.first.length===Me),[u,d]=v(!1),[m,f]=v(!1),c=P();N(()=>{i(t.first),l(t.first.length===Me)},[t.first]);let g=()=>void c.run(async()=>{let h=await k(`/feedback?limit=${Me}&offset=${a.length}`);if(!h.ok)return{error:K(h)};let x=Array.isArray(h.data?.tickets)?h.data.tickets:[];r.current&&(i(w=>{let _=new Set(w.map(p=>p.id));return[...w,...x.filter(p=>!_.has(p.id))]}),l(x.length===Me))});return o(B,{icon:"message",title:e("fb.list.title"),desc:e("fb.list.desc"),actions:u?void 0:o(S,{variant:"primary",onClick:()=>{f(!1),d(!0)},children:[o(I,{name:"plus",size:12})," ",e("fb.new")]}),children:[u&&o(ur,{onCancel:()=>d(!1),onSubmitted:()=>{d(!1),f(!0),t.onChanged()}}),m&&!u&&o(U,{children:o("div",{class:"fx-msg is-ok",role:"status",children:e("fb.submitted")})}),a.length===0?o(ue,{children:e("fb.empty")}):o("div",{class:"fx-list fx-block",role:"list",children:a.map(h=>o("button",{type:"button",class:"fx-list-row fx-list-row--button",role:"listitem",onClick:()=>t.onOpen(h.id),children:[o("span",{class:`fx-dot${h.user_unread?" is-on":""}`,"aria-label":h.user_unread?e("fb.unread"):void 0}),o("span",{class:"fx-list-main",children:[o("strong",{children:h.title||(h.description||"").slice(0,60)||e("fb.untitled")}),o("small",{children:xe(h.updated_at||h.created_at,n)})]}),o(Xn,{status:h.status}),o(I,{name:"chevron",size:12})]},h.id))}),a.length>0&&(s||c.error)&&o("div",{class:"settings-panel-footer fx-footer",children:[o("span",{class:"fx-muted",children:e("fb.shown",{n:W(a.length,n)})}),s&&o(S,{pending:c.pending,onClick:g,children:e("common.loadMore")})]}),c.error&&o(U,{children:o(M,{a:c})})]})}function lr(t){return new Promise((e,n)=>{let r=new FileReader;r.onload=()=>e(String(r.result||"")),r.onerror=()=>n(r.error||new Error("read failed")),r.readAsDataURL(t)})}var cr=0;function ur(t){let{t:e}=A(),n=ce(),[r,a]=v(""),[i,s]=v([]),[l,u]=v(null),[d,m]=v(!1),f=$(null),c=P(),[g,h]=v(0),x=$(0);x.current=i.length;let w=async p=>{u(null);for(let b of Array.from(p||[])){if(!b.type||!b.type.startsWith("image/")){u({key:"err.imageType"});continue}if(b.size>ar){u({key:"err.imageTooLarge"});continue}if(x.current>=Ye){u({key:"err.tooManyImages"});break}x.current++,h(y=>y+1);try{let y=await lr(b);if(!n.current)return;let C={id:`img-${++cr}`,filename:b.name||"image",mime_type:b.type,size:b.size,data_base64:y.replace(/^data:[^;]+;base64,/,""),url:y};s(E=>E.length>=Ye?E:[...E,C])}catch{x.current--,u({key:"err.imageRead"})}finally{n.current&&h(y=>y-1)}}},_=()=>void c.run(async()=>{let p=r.trim();if(!p)return{error:{key:"err.feedbackEmpty"}};if(p.length>Qe)return{error:{key:"err.feedbackTooLong"}};let b=i.map(({filename:C,mime_type:E,size:F,data_base64:O})=>({filename:C,mime_type:E,size:F,data_base64:O})),y=await k("/feedback",{method:"POST",body:{description:p,attachments:b},timeoutMs:12e4});if(!y.ok)return X(y);t.onSubmitted()});return o("div",{class:`fx-sub fx-form fx-composer${d?" is-drag":""}`,onPaste:p=>{let b=Array.from(p.clipboardData?.items||[]).filter(y=>y.kind==="file").map(y=>y.getAsFile()).filter(Boolean);b.length&&(p.preventDefault(),w(b))},onDragOver:p=>{p.preventDefault(),m(!0)},onDragLeave:()=>m(!1),onDrop:p=>{p.preventDefault(),m(!1),w(p.dataTransfer?.files)},children:[o("label",{class:"fx-field",children:[o("span",{children:e("fb.descLabel")}),o("textarea",{class:"fx-input fx-textarea",rows:5,value:r,maxLength:Qe,autoFocus:!0,placeholder:e("fb.descPlaceholder"),onInput:p=>a(p.currentTarget.value)})]}),o("p",{class:"fx-note",children:e("fb.imagesHint",{n:Ye})}),i.length>0&&o("div",{class:"fx-thumbs",children:i.map(p=>o("span",{class:"fx-thumb",children:[o("img",{src:p.url,alt:p.filename}),o("button",{type:"button","aria-label":e("fb.removeImage"),title:e("fb.removeImage"),onClick:()=>{s(b=>b.filter(y=>y.id!==p.id)),u(null)},children:o(I,{name:"x",size:11})})]},p.id))}),l&&o("div",{class:"fx-msg is-error",role:"alert",children:te(l,e)}),o("input",{ref:f,type:"file",accept:"image/*",multiple:!0,hidden:!0,onChange:p=>{let b=p.currentTarget;w(b.files),b.value=""}}),o("div",{class:"fx-inline",children:[o(S,{disabled:i.length>=Ye||c.pending,onClick:()=>f.current?.click(),children:[o(I,{name:"image",size:12})," ",e("fb.addImages")]}),o("span",{class:"fx-grow"}),o(S,{disabled:c.pending,onClick:t.onCancel,children:e("common.cancel")}),o(S,{variant:"primary",pending:c.pending,disabled:g>0,onClick:_,children:e("fb.submit")})]}),o(M,{a:c})]})}function dr(t){let{t:e,locale:n}=A(),[r,a]=v({state:"loading"}),[i,s]=v(0),[l,u]=v(""),[d,m]=v(null),f=P(),c=$(0);N(()=>{let y=++c.current;return k(`/feedback/${encodeURIComponent(t.id)}`).then(C=>{if(y===c.current){if(!C.ok){a({state:"error",fail:C});return}a({state:"ready",data:{ticket:C.data.ticket,replies:C.data.replies??[],attachments:C.data.attachments??[]}}),k(`/feedback/${encodeURIComponent(t.id)}/read`,{method:"POST"})}}),()=>{c.current++}},[t.id,i]),N(()=>{if(!d)return;let y=C=>{C.key==="Escape"&&m(null)};return window.addEventListener("keydown",y),()=>window.removeEventListener("keydown",y)},[d]);let g=o("div",{class:"fx-back",children:o(S,{onClick:t.onBack,children:[o(I,{name:"back",size:12})," ",e("fb.back")]})});if(r.state==="loading")return o(R,{children:[g,o(j,{panels:1,rows:3})]});if(r.state==="error")return o(R,{children:[g,o(Y,{error:K(r.fail),onRetry:()=>{a({state:"loading"}),s(y=>y+1)}})]});let{ticket:h,replies:x,attachments:w}=r.data,_=h.status==="closed",p=y=>w.filter(C=>(C.reply_id??null)===y),b=()=>void f.run(async()=>{let y=l.trim();if(!y)return{error:{key:"err.replyEmpty"}};if(y.length>Qe)return{error:{key:"err.replyTooLong"}};let C=await k(`/feedback/${encodeURIComponent(h.id)}/replies`,{method:"POST",body:{content:y},timeoutMs:6e4});return C.ok?(u(""),s(E=>E+1),{success:{key:"fb.replySent"}}):X(C)});return o(R,{children:[g,o(B,{icon:"message",title:h.title||e("fb.untitled"),actions:o(Xn,{status:h.status}),desc:`#${String(h.id).slice(0,8)} \xB7 ${xe(h.created_at,n)}`,children:[o("div",{class:"fx-thread fx-block",children:[o($n,{who:"user",when:h.created_at,text:h.description||"",files:p(null),onZoom:m}),x.map((y,C)=>o($n,{who:y.author_role==="user"?"user":"admin",when:y.created_at,text:y.content||"",files:y.id?p(y.id):[],onZoom:m},y.id??C))]}),_?o(U,{children:o(J,{children:e("fb.closedNote")})}):o(U,{class:"fx-form",children:[o("textarea",{class:"fx-input fx-textarea",rows:3,value:l,maxLength:Qe,placeholder:e("fb.replyPlaceholder"),"aria-label":e("fb.replyPlaceholder"),onInput:y=>{u(y.currentTarget.value),f.success&&f.clear()}}),o("div",{class:"fx-inline",children:[o("span",{class:"fx-grow"}),o(S,{variant:"primary",pending:f.pending,onClick:b,children:e("fb.replySend")})]}),o(M,{a:f})]})]}),d&&o("div",{class:"fx-lightbox",role:"dialog","aria-label":e("fb.imagePreview"),onClick:()=>m(null),children:o("img",{src:d,alt:""})})]})}function $n(t){let{t:e,locale:n}=A();return o("div",{class:`fx-bubble fx-bubble--${t.who}`,children:[o("div",{class:"fx-bubble-meta",children:[t.who==="user"?e("fb.you"):e("fb.support")," \xB7 ",xe(t.when,n)]}),o("div",{class:"fx-bubble-text",children:t.text}),t.files.length>0&&o("div",{class:"fx-thumbs",children:t.files.map((r,a)=>{let i=r.mime_type||"";if(i.startsWith("image/")&&r.data_base64){let s=`data:${i};base64,${r.data_base64}`;return o("button",{type:"button",class:"fx-thumb",onClick:()=>t.onZoom(s),"aria-label":e("fb.imagePreview"),children:o("img",{src:s,alt:r.filename||""})},r.id??a)}return o("span",{class:"fx-tag",children:[o(I,{name:"card",size:11})," ",r.filename||e("fb.attachment")]},r.id??a)})})]})}var fr="forsion-extend",Vn=[{id:"account",titleKey:"page.account",Component:In},{id:"quota",titleKey:"page.quota",Component:Rn},{id:"security",titleKey:"page.security",Component:qn},{id:"usage",titleKey:"page.usage",Component:On},{id:"feedback",titleKey:"page.feedback",Component:Wn}],mr=t=>`forsion/fx:${fr}:${t}`;function pr(t){let{ctx:e,page:n}=t,[r,a]=v(()=>we(e.getLocale?.()));N(()=>{a(we(e.getLocale?.()));let l=e.subscribeLocale?.(u=>a(we(u)));return()=>{typeof l=="function"&&l()}},[e]);let i=ve(()=>{let l=e.app?.openSettings;return{ctx:e,locale:r,t:nn(r),goTo:typeof l=="function"?u=>l.call(e.app,mr(u)):null}},[e,r]),s=n.Component;return o(mt.Provider,{value:i,children:o("div",{class:"fx-acct","data-fx-page":n.id,lang:r==="zh"?"zh-CN":"en",children:[o("style",{children:fn}),o(s,{})]})})}function Jn(t,e=window){let n=e?.tangu;if(!t||!n?.cloudFetch||!n.cloudInvoke||n.unitPage||typeof t.registerSettingsView!="function")return 0;for(let r of Vn)t.registerSettingsView({id:r.id,category:"forsion",title:()=>ut(we(t.getLocale?.()),r.titleKey),mount(a){return st(o(pr,{ctx:t,page:r}),a),()=>{st(null,a)}}});return Vn.length}typeof ctx<"u"&&Jn(ctx);})();
package/manifest.json CHANGED
@@ -2,11 +2,11 @@
2
2
  "id": "forsion-extend",
3
3
  "name": "Forsion 扩展",
4
4
  "nameEn": "Forsion Extend",
5
- "version": "0.3.0",
5
+ "version": "0.5.0",
6
6
  "apiVersion": 1,
7
7
  "minAppVersion": "2.11.4",
8
8
  "main": "dist/main.js",
9
- "description": "Forsion 云端账号相关的桌面功能:账号登录、登出、切换与登录态续期,个人中心与会员页入口、额度视图与重置卡、后台额度转换、反馈中心提交,插件以当前账号身份调用 Forsion 云端 API 的通用接口,Forsion Connect(Coding Space 项目发布、应用商店上架申请、预览态 AI 代理),以及本地库远程同步的 Forsion 云端后端。随 Forsion 桌面端内置,自动更新。",
10
- "descriptionEn": "The cloud-account features of Forsion Desktop: signing in, signing out, switching accounts and keeping you signed in, account center and membership page shortcuts, quota view and reset cards, background quota conversion, feedback submission, the shared interface plugins use to call the Forsion cloud API as the signed-in account, Forsion Connect (Coding Space project publishing, app store listing requests, and the preview-mode AI proxy), and the Forsion cloud backend for remote sync of the local vault. Built into Forsion Desktop and updated automatically.",
9
+ "description": "Forsion 云端账号在桌面端的功能:登录与切换账号,设置里的「Forsion 云端」(账号、额度与积分、安全、用量记录、反馈),笔记云同步与分享,以及 Forsion Connect 发布。随 Forsion 桌面端内置,自动更新。",
10
+ "descriptionEn": "Your Forsion cloud account on the desktop: signing in and switching accounts, the Forsion Cloud pages in Settings (account, quota & points, security, usage, feedback), note cloud sync and sharing, and Forsion Connect publishing. Built into Forsion Desktop and updated automatically.",
11
11
  "author": "Forsion"
12
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forsion/extend",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Forsion Extend: the cloud-account half of Forsion Desktop plus Forsion Connect (Coding Space publishing and the preview-mode AI proxy), shipped as a built-in bundle (signed, updated through npm).",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -27,12 +27,21 @@
27
27
  "build": "node scripts/build.mjs",
28
28
  "sign": "node scripts/sign.mjs",
29
29
  "verify": "node scripts/verify-package.mjs",
30
- "test": "node --test 'test/*.test.ts'",
31
- "typecheck": "tsc --noEmit"
30
+ "test": "node --test 'test/*.test.ts' && vitest run",
31
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.renderer.json",
32
+ "test:vitest": "vitest run"
32
33
  },
33
34
  "devDependencies": {
34
35
  "@types/node": "^22.10.0",
35
36
  "esbuild": "^0.25.0",
36
- "typescript": "^5.6.0"
37
+ "happy-dom": "^20.14.5",
38
+ "preact": "^10.29.8",
39
+ "typescript": "^5.6.0",
40
+ "uqr": "^0.1.3",
41
+ "vitest": "^3.2.7"
42
+ },
43
+ "dependencies": {
44
+ "chokidar": "^5.0.0",
45
+ "node-diff3": "^3.2.1"
37
46
  }
38
47
  }