9remote 3.0.25 → 3.0.27

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.
Files changed (218) hide show
  1. package/dist/cli.cjs +146 -113
  2. package/dist/server.cjs +206 -203
  3. package/dist/ui/assets/index-I2Ik1Uxe.js +8 -0
  4. package/dist/ui/index.html +1 -1
  5. package/dist/web/404.html +1 -1
  6. package/dist/web/__next.__PAGE__.txt +2 -2
  7. package/dist/web/__next._full.txt +3 -3
  8. package/dist/web/__next._head.txt +1 -1
  9. package/dist/web/__next._index.txt +2 -2
  10. package/dist/web/__next._tree.txt +2 -2
  11. package/dist/web/_next/static/chunks/0fb7b532.2e7a08a3edb2d789.js +14 -0
  12. package/dist/web/_next/static/chunks/1750.2278b084cb33e817.js +1 -0
  13. package/dist/web/_next/static/chunks/5788-f631bcbc039b4da2.js +1 -0
  14. package/dist/web/_next/static/chunks/6552-1ddf0600fddfd553.js +1 -0
  15. package/dist/web/_next/static/chunks/app/_global-error/page-1105b0cfd58cfb3c.js +1 -0
  16. package/dist/web/_next/static/chunks/app/login/{page-5a8b059b59f831f9.js → page-55e34ebc40a79798.js} +1 -1
  17. package/dist/web/_next/static/chunks/app/{page-bd6ebc0a436fea70.js → page-f0bf05d73d9e99d4.js} +2 -2
  18. package/dist/web/_next/static/chunks/app/workspace/browse/page-1105b0cfd58cfb3c.js +1 -0
  19. package/dist/web/_next/static/chunks/app/workspace/editor/page-1105b0cfd58cfb3c.js +1 -0
  20. package/dist/web/_next/static/chunks/app/workspace/files/page-1105b0cfd58cfb3c.js +1 -0
  21. package/dist/web/_next/static/chunks/app/workspace/git/page-1105b0cfd58cfb3c.js +1 -0
  22. package/dist/web/_next/static/chunks/app/workspace/layout-03eff77b255b25d6.js +15 -0
  23. package/dist/web/_next/static/chunks/app/workspace/mobile/page-1105b0cfd58cfb3c.js +1 -0
  24. package/dist/web/_next/static/chunks/app/workspace/page-1105b0cfd58cfb3c.js +1 -0
  25. package/dist/web/_next/static/chunks/app/workspace/remote/page-1105b0cfd58cfb3c.js +1 -0
  26. package/dist/web/_next/static/chunks/app/workspace/terminal/[sessionId]/page-1105b0cfd58cfb3c.js +1 -0
  27. package/dist/web/_next/static/chunks/app/workspace/workspaces/page-1105b0cfd58cfb3c.js +1 -0
  28. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/app-error-1105b0cfd58cfb3c.js +1 -0
  29. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/forbidden-1105b0cfd58cfb3c.js +1 -0
  30. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/not-found-1105b0cfd58cfb3c.js +1 -0
  31. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/unauthorized-1105b0cfd58cfb3c.js +1 -0
  32. package/dist/web/_next/static/chunks/webpack-6c9c0816af64073a.js +1 -0
  33. package/dist/web/_next/static/css/be666ba38225da3a.css +1 -0
  34. package/dist/web/_not-found/__next._full.txt +2 -2
  35. package/dist/web/_not-found/__next._head.txt +1 -1
  36. package/dist/web/_not-found/__next._index.txt +2 -2
  37. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +1 -1
  38. package/dist/web/_not-found/__next._not-found.txt +1 -1
  39. package/dist/web/_not-found/__next._tree.txt +2 -2
  40. package/dist/web/_not-found.html +1 -1
  41. package/dist/web/_not-found.txt +2 -2
  42. package/dist/web/admin/__next._full.txt +2 -2
  43. package/dist/web/admin/__next._head.txt +1 -1
  44. package/dist/web/admin/__next._index.txt +2 -2
  45. package/dist/web/admin/__next._tree.txt +2 -2
  46. package/dist/web/admin/__next.admin.__PAGE__.txt +1 -1
  47. package/dist/web/admin/__next.admin.txt +1 -1
  48. package/dist/web/admin/admins/__next._full.txt +2 -2
  49. package/dist/web/admin/admins/__next._head.txt +1 -1
  50. package/dist/web/admin/admins/__next._index.txt +2 -2
  51. package/dist/web/admin/admins/__next._tree.txt +2 -2
  52. package/dist/web/admin/admins/__next.admin.admins.__PAGE__.txt +1 -1
  53. package/dist/web/admin/admins/__next.admin.admins.txt +1 -1
  54. package/dist/web/admin/admins/__next.admin.txt +1 -1
  55. package/dist/web/admin/admins.html +1 -1
  56. package/dist/web/admin/admins.txt +2 -2
  57. package/dist/web/admin/login/__next._full.txt +2 -2
  58. package/dist/web/admin/login/__next._head.txt +1 -1
  59. package/dist/web/admin/login/__next._index.txt +2 -2
  60. package/dist/web/admin/login/__next._tree.txt +2 -2
  61. package/dist/web/admin/login/__next.admin.login.__PAGE__.txt +1 -1
  62. package/dist/web/admin/login/__next.admin.login.txt +1 -1
  63. package/dist/web/admin/login/__next.admin.txt +1 -1
  64. package/dist/web/admin/login.html +1 -1
  65. package/dist/web/admin/login.txt +2 -2
  66. package/dist/web/admin/modes/__next._full.txt +2 -2
  67. package/dist/web/admin/modes/__next._head.txt +1 -1
  68. package/dist/web/admin/modes/__next._index.txt +2 -2
  69. package/dist/web/admin/modes/__next._tree.txt +2 -2
  70. package/dist/web/admin/modes/__next.admin.modes.__PAGE__.txt +1 -1
  71. package/dist/web/admin/modes/__next.admin.modes.txt +1 -1
  72. package/dist/web/admin/modes/__next.admin.txt +1 -1
  73. package/dist/web/admin/modes.html +1 -1
  74. package/dist/web/admin/modes.txt +2 -2
  75. package/dist/web/admin/ota/__next._full.txt +2 -2
  76. package/dist/web/admin/ota/__next._head.txt +1 -1
  77. package/dist/web/admin/ota/__next._index.txt +2 -2
  78. package/dist/web/admin/ota/__next._tree.txt +2 -2
  79. package/dist/web/admin/ota/__next.admin.ota.__PAGE__.txt +1 -1
  80. package/dist/web/admin/ota/__next.admin.ota.txt +1 -1
  81. package/dist/web/admin/ota/__next.admin.txt +1 -1
  82. package/dist/web/admin/ota.html +1 -1
  83. package/dist/web/admin/ota.txt +2 -2
  84. package/dist/web/admin/turn/__next._full.txt +2 -2
  85. package/dist/web/admin/turn/__next._head.txt +1 -1
  86. package/dist/web/admin/turn/__next._index.txt +2 -2
  87. package/dist/web/admin/turn/__next._tree.txt +2 -2
  88. package/dist/web/admin/turn/__next.admin.turn.__PAGE__.txt +1 -1
  89. package/dist/web/admin/turn/__next.admin.turn.txt +1 -1
  90. package/dist/web/admin/turn/__next.admin.txt +1 -1
  91. package/dist/web/admin/turn.html +1 -1
  92. package/dist/web/admin/turn.txt +2 -2
  93. package/dist/web/admin.html +1 -1
  94. package/dist/web/admin.txt +2 -2
  95. package/dist/web/dev/question/__next._full.txt +3 -3
  96. package/dist/web/dev/question/__next._head.txt +1 -1
  97. package/dist/web/dev/question/__next._index.txt +2 -2
  98. package/dist/web/dev/question/__next._tree.txt +2 -2
  99. package/dist/web/dev/question/__next.dev.question.__PAGE__.txt +2 -2
  100. package/dist/web/dev/question/__next.dev.question.txt +1 -1
  101. package/dist/web/dev/question/__next.dev.txt +1 -1
  102. package/dist/web/dev/question.html +1 -1
  103. package/dist/web/dev/question.txt +3 -3
  104. package/dist/web/index.html +1 -1
  105. package/dist/web/index.txt +3 -3
  106. package/dist/web/login/__next._full.txt +3 -3
  107. package/dist/web/login/__next._head.txt +1 -1
  108. package/dist/web/login/__next._index.txt +2 -2
  109. package/dist/web/login/__next._tree.txt +2 -2
  110. package/dist/web/login/__next.login.__PAGE__.txt +2 -2
  111. package/dist/web/login/__next.login.txt +1 -1
  112. package/dist/web/login.html +1 -1
  113. package/dist/web/login.txt +3 -3
  114. package/dist/web/workspace/__next._full.txt +3 -3
  115. package/dist/web/workspace/__next._head.txt +1 -1
  116. package/dist/web/workspace/__next._index.txt +2 -2
  117. package/dist/web/workspace/__next._tree.txt +2 -2
  118. package/dist/web/workspace/__next.workspace.__PAGE__.txt +1 -1
  119. package/dist/web/workspace/__next.workspace.txt +2 -2
  120. package/dist/web/workspace/browse/__next._full.txt +3 -3
  121. package/dist/web/workspace/browse/__next._head.txt +1 -1
  122. package/dist/web/workspace/browse/__next._index.txt +2 -2
  123. package/dist/web/workspace/browse/__next._tree.txt +2 -2
  124. package/dist/web/workspace/browse/__next.workspace.browse.__PAGE__.txt +1 -1
  125. package/dist/web/workspace/browse/__next.workspace.browse.txt +1 -1
  126. package/dist/web/workspace/browse/__next.workspace.txt +2 -2
  127. package/dist/web/workspace/browse.html +1 -1
  128. package/dist/web/workspace/browse.txt +3 -3
  129. package/dist/web/workspace/editor/__next._full.txt +3 -3
  130. package/dist/web/workspace/editor/__next._head.txt +1 -1
  131. package/dist/web/workspace/editor/__next._index.txt +2 -2
  132. package/dist/web/workspace/editor/__next._tree.txt +2 -2
  133. package/dist/web/workspace/editor/__next.workspace.editor.__PAGE__.txt +1 -1
  134. package/dist/web/workspace/editor/__next.workspace.editor.txt +1 -1
  135. package/dist/web/workspace/editor/__next.workspace.txt +2 -2
  136. package/dist/web/workspace/editor.html +1 -1
  137. package/dist/web/workspace/editor.txt +3 -3
  138. package/dist/web/workspace/files/__next._full.txt +3 -3
  139. package/dist/web/workspace/files/__next._head.txt +1 -1
  140. package/dist/web/workspace/files/__next._index.txt +2 -2
  141. package/dist/web/workspace/files/__next._tree.txt +2 -2
  142. package/dist/web/workspace/files/__next.workspace.files.__PAGE__.txt +1 -1
  143. package/dist/web/workspace/files/__next.workspace.files.txt +1 -1
  144. package/dist/web/workspace/files/__next.workspace.txt +2 -2
  145. package/dist/web/workspace/files.html +1 -1
  146. package/dist/web/workspace/files.txt +3 -3
  147. package/dist/web/workspace/git/__next._full.txt +3 -3
  148. package/dist/web/workspace/git/__next._head.txt +1 -1
  149. package/dist/web/workspace/git/__next._index.txt +2 -2
  150. package/dist/web/workspace/git/__next._tree.txt +2 -2
  151. package/dist/web/workspace/git/__next.workspace.git.__PAGE__.txt +1 -1
  152. package/dist/web/workspace/git/__next.workspace.git.txt +1 -1
  153. package/dist/web/workspace/git/__next.workspace.txt +2 -2
  154. package/dist/web/workspace/git.html +1 -1
  155. package/dist/web/workspace/git.txt +3 -3
  156. package/dist/web/workspace/mobile/__next._full.txt +3 -3
  157. package/dist/web/workspace/mobile/__next._head.txt +1 -1
  158. package/dist/web/workspace/mobile/__next._index.txt +2 -2
  159. package/dist/web/workspace/mobile/__next._tree.txt +2 -2
  160. package/dist/web/workspace/mobile/__next.workspace.mobile.__PAGE__.txt +1 -1
  161. package/dist/web/workspace/mobile/__next.workspace.mobile.txt +1 -1
  162. package/dist/web/workspace/mobile/__next.workspace.txt +2 -2
  163. package/dist/web/workspace/mobile.html +1 -1
  164. package/dist/web/workspace/mobile.txt +3 -3
  165. package/dist/web/workspace/remote/__next._full.txt +3 -3
  166. package/dist/web/workspace/remote/__next._head.txt +1 -1
  167. package/dist/web/workspace/remote/__next._index.txt +2 -2
  168. package/dist/web/workspace/remote/__next._tree.txt +2 -2
  169. package/dist/web/workspace/remote/__next.workspace.remote.__PAGE__.txt +1 -1
  170. package/dist/web/workspace/remote/__next.workspace.remote.txt +1 -1
  171. package/dist/web/workspace/remote/__next.workspace.txt +2 -2
  172. package/dist/web/workspace/remote.html +1 -1
  173. package/dist/web/workspace/remote.txt +3 -3
  174. package/dist/web/workspace/terminal/default/__next._full.txt +3 -3
  175. package/dist/web/workspace/terminal/default/__next._head.txt +1 -1
  176. package/dist/web/workspace/terminal/default/__next._index.txt +2 -2
  177. package/dist/web/workspace/terminal/default/__next._tree.txt +2 -2
  178. package/dist/web/workspace/terminal/default/__next.workspace.terminal.$d$sessionId.__PAGE__.txt +1 -1
  179. package/dist/web/workspace/terminal/default/__next.workspace.terminal.$d$sessionId.txt +1 -1
  180. package/dist/web/workspace/terminal/default/__next.workspace.terminal.txt +1 -1
  181. package/dist/web/workspace/terminal/default/__next.workspace.txt +2 -2
  182. package/dist/web/workspace/terminal/default.html +1 -1
  183. package/dist/web/workspace/terminal/default.txt +3 -3
  184. package/dist/web/workspace/workspaces/__next._full.txt +3 -3
  185. package/dist/web/workspace/workspaces/__next._head.txt +1 -1
  186. package/dist/web/workspace/workspaces/__next._index.txt +2 -2
  187. package/dist/web/workspace/workspaces/__next._tree.txt +2 -2
  188. package/dist/web/workspace/workspaces/__next.workspace.txt +2 -2
  189. package/dist/web/workspace/workspaces/__next.workspace.workspaces.__PAGE__.txt +1 -1
  190. package/dist/web/workspace/workspaces/__next.workspace.workspaces.txt +1 -1
  191. package/dist/web/workspace/workspaces.html +1 -1
  192. package/dist/web/workspace/workspaces.txt +3 -3
  193. package/dist/web/workspace.html +1 -1
  194. package/dist/web/workspace.txt +3 -3
  195. package/package.json +1 -1
  196. package/dist/ui/assets/index-BOOiLX1B.js +0 -8
  197. package/dist/web/_next/static/chunks/1750.0aa6aeecbaace8cb.js +0 -1
  198. package/dist/web/_next/static/chunks/5788-2151395b4db264e7.js +0 -1
  199. package/dist/web/_next/static/chunks/6552-26435ba7e21d8241.js +0 -1
  200. package/dist/web/_next/static/chunks/app/_global-error/page-5bd6526483106080.js +0 -1
  201. package/dist/web/_next/static/chunks/app/workspace/browse/page-5bd6526483106080.js +0 -1
  202. package/dist/web/_next/static/chunks/app/workspace/editor/page-5bd6526483106080.js +0 -1
  203. package/dist/web/_next/static/chunks/app/workspace/files/page-5bd6526483106080.js +0 -1
  204. package/dist/web/_next/static/chunks/app/workspace/git/page-5bd6526483106080.js +0 -1
  205. package/dist/web/_next/static/chunks/app/workspace/layout-4b7802a47d5a41d9.js +0 -14
  206. package/dist/web/_next/static/chunks/app/workspace/mobile/page-5bd6526483106080.js +0 -1
  207. package/dist/web/_next/static/chunks/app/workspace/page-5bd6526483106080.js +0 -1
  208. package/dist/web/_next/static/chunks/app/workspace/remote/page-5bd6526483106080.js +0 -1
  209. package/dist/web/_next/static/chunks/app/workspace/terminal/[sessionId]/page-5bd6526483106080.js +0 -1
  210. package/dist/web/_next/static/chunks/app/workspace/workspaces/page-5bd6526483106080.js +0 -1
  211. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/app-error-5bd6526483106080.js +0 -1
  212. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/forbidden-5bd6526483106080.js +0 -1
  213. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/not-found-5bd6526483106080.js +0 -1
  214. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/unauthorized-5bd6526483106080.js +0 -1
  215. package/dist/web/_next/static/chunks/webpack-34aa84f85d3087cb.js +0 -1
  216. package/dist/web/_next/static/css/99ebcb780b6d29f4.css +0 -1
  217. /package/dist/web/_next/static/{doBLJdxjaGN7ToTue-RM0 → ojB5LsquXLz4Tz9PU1iGl}/_buildManifest.js +0 -0
  218. /package/dist/web/_next/static/{doBLJdxjaGN7ToTue-RM0 → ojB5LsquXLz4Tz9PU1iGl}/_ssgManifest.js +0 -0
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1750],{71750:(e,t,n)=>{n.r(t),n.d(t,{default:()=>a});let a={common:{statusIdle:"Idle",statusWorking:"Working",statusBlocked:"Needs input",statusDone:"Your turn",loading:"Đang tải...",cancel:"Hủy",confirm:"X\xe1c nhận",save:"Lưu",delete:"X\xf3a",close:"Đ\xf3ng",back:"Quay lại",edit:"Sửa",rename:"Đổi t\xean",remove:"Gỡ bỏ",open:"Mở",yes:"C\xf3",no:"Kh\xf4ng",ok:"OK",error:"Lỗi",success:"Th\xe0nh c\xf4ng",failed:"Thất bại",retry:"Thử lại",refresh:"Tải lại",clipboard:"Clipboard",clipboardCopy:"Copy",clipboardEmpty:"Clipboard is empty",search:"T\xecm kiếm",create:"Tạo",new:"Mới",add:"Th\xeam",copy:"Sao ch\xe9p",copied:"Đ\xe3 sao ch\xe9p",download:"Tải xuống",upload:"Tải l\xean",enabled:"Đ\xe3 bật",disabled:"Đ\xe3 tắt",on:"bật",off:"tắt",minute:"ph\xfat",hour:"giờ",day:"ng\xe0y",minutesAgo:"{n} ph\xfat trước",hoursAgo:"{n} giờ trước",daysAgo:"{n} ng\xe0y trước",done:"Xong"},agentSwitcher:{title:"Thiết bị của bạn",active:"ACTIVE",unnamed:"Chưa đặt t\xean",connecting:"Đang kết nối…",unreachable:"Kh\xf4ng kết nối được thiết bị n\xe0y. Thiết bị c\xf3 đang bật?"},login:{tagline:"Truy cập terminal của bạn từ mọi nơi",heroLine1:"Any machine.",heroLine2:"One terminal.",heroLine3:"In your pocket.",featureTerminal:"Terminal",featureDesktop:"Desktop",featureFiles:"Files",termConnected:"agent connected",termTunnel:"tunnel established",termReady:"ready",accessKey:"Kh\xf3a truy cập",placeholder:"sk-xxx... hoặc M\xe3 d\xf9ng 1 lần (ABC123)",rememberKey:"Ghi nhớ kh\xf3a n\xe0y",connect:"Kết nối",connecting:"Đang kết nối...",authenticating:"Đang x\xe1c thực bằng token...",invalidKeyTail:"Wrong access key — check the last characters and try again.",scanQr:"Scan QR to login",qrScanTitle:"Scan QR Code",qrHint:"Point the camera at the QR code shown on the machine running 9Remote.",qrDetected:"QR Code detected!",qrAuthenticating:"Authenticating...",qrPleaseWait:"Please wait...",qrLibFail:"Failed to load the QR scanner library.",qrInitFail:"Could not start the scanner.",qrCamDenied:"Camera permission denied. Allow camera access and try again.",qrNoCamera:"No camera found on this device.",qrCamBusy:"Camera is in use by another app.",qrCamError:"Could not open the camera.",legacyKeyUpdateRequired:"Cần cập nhật 9remote",legacyKeyUpdateHint:"Thiết bị n\xe0y d\xf9ng định dạng key cũ. H\xe3y cập nhật 9remote tr\xean m\xe1y đ\xf3 để kết nối:",legacyKeyError:"Access key n\xe0y thuộc phi\xean bản cũ. Vui l\xf2ng cập nhật 9remote l\xean bản mới nhất tr\xean m\xe1y chủ.",updateRequired:"Cần cập nhật",savedKeys:"Kh\xf3a đ\xe3 lưu",login:"Đăng nhập",lastLogin:"Lần đăng nhập gần nhất",namePlaceholder:"Đặt t\xean cho kh\xf3a (t\xf9y chọn)",rename:"Đổi t\xean",deleteKeyTitle:"X\xf3a kh\xf3a",deleteKeyConfirm:'Bạn c\xf3 chắc muốn x\xf3a "{name}"?',justNow:"Vừa xong",minutesAgo:"{n} ph\xfat trước",hoursAgo:"{n} giờ trước",daysAgo:"{n} ng\xe0y trước",tapToScan:"Chạm để qu\xe9t",orEnterManually:"hoặc nhập kh\xf3a thủ c\xf4ng",addKey:"Add Key",secureTitle:"Secure & Encrypted",secureDesc:"All connections are end-to-end encrypted and secure.",featAccessTitle:"Access Anywhere",featAccessDesc:"Connect from any device, anywhere.",featSecureTitle:"Secure Connection",featSecureDesc:"End-to-end encryption keeps you safe.",featFastTitle:"Fast & Reliable",featFastDesc:"Low latency and high performance.",featSessionsTitle:"Multiple Sessions",featSessionsDesc:"Manage and switch between sessions.",home:"Trang chủ",docs:"T\xe0i liệu"},menu:{reloadRestart:"Tải lại & Khởi động lại",restartHost:"Khởi động lại 9remote host",restartConfirmTitle:"Khởi động lại 9remote host?",restartConfirmMessage:"Khởi động lại tiến tr\xecnh agent (kh\xf4ng c\xe0i lại). Phi\xean terminal được giữ. Mất v\xe0i gi\xe2y.",restartStarting:"Đang khởi động lại host…",restartRestarting:"Đang khởi động lại 9remote…",restartDone:"Đ\xe3 khởi động lại! Đang kết nối lại…",restartTimeout:"Khởi động lại qu\xe1 l\xe2u",restartTimeoutHint:"Kết nối lại thủ c\xf4ng nếu kh\xf4ng tự phục hồi.",title:"Menu",language:"Ng\xf4n ngữ",theme:"Giao diện",notifications:"Th\xf4ng b\xe1o",webgl:"GPU Render (Faster)",webglHint:"Tắt nếu chữ hiển thị sai",notificationsHint:"B\xe1o khi Agent xong",files:"File Explorer",downloading:"Downloading",copying:"Copying",conflictTitle:"File already exists",conflictMessage:"{name} already exists. Replace or skip?",skip:"Skip",skipAll:"Skip all",replace:"Replace",replaceAll:"Replace all",sites:"Trang web",commandNotes:"Ghi ch\xfa lệnh",community:"Cộng đồng",installApp:"C\xe0i đặt ứng dụng",codespace:"Codespace",logout:"Đăng xuất",settingsGeneral:"General",settingsAppearance:"Appearance",settingsTerminalTab:"Terminal",settingsMcp:"Plugins",mcpIntro:"Extra abilities you can give your AI coding tools.",mcpTools:"Allow",mcpRestartHint:"Turning it off applies at once. Turning it on needs the AI tool restarted.",mcpUnavailable:"Update this host to use MCP.",artifactFormats:"Formats it can show",mcpClients:"Works with",settingsWorkspace:"Workspace",settingsApplication:"Application",settingsAccount:"Account",themeLight:"Light",themeDark:"Dark",reload:"Tải lại ứng dụng",remoteDesktop:"Điều khiển từ xa",settings:"C\xe0i đặt",enablePush:"Bật th\xf4ng b\xe1o đẩy",disablePush:"Tắt th\xf4ng b\xe1o đẩy",pushHint:"Bật th\xf4ng b\xe1o đẩy để được nhắc khi AI ho\xe0n th\xe0nh t\xe1c vụ",pushActiveHint:"Th\xf4ng b\xe1o đẩy đang bật cho thiết bị n\xe0y. Bạn sẽ được b\xe1o khi AI ho\xe0n th\xe0nh.",versionMismatch:"Agent {version} đ\xe3 lỗi thời",versionMismatchHint:"Một số t\xednh năng c\xf3 thể kh\xf4ng hoạt động. Chạy:",updateNow:"Cập nhật ngay",updating:"Đang cập nhật… kết nối lại",webReloadTitle:"C\xf3 bản giao diện mới",webReloadHint:"Tải lại để cập nhật giao diện mới nhất.",reloadWeb:"Tải lại",updateAvailableTitle:"C\xf3 bản cập nhật 9Remote host",updateStarting:"Đang bắt đầu cập nhật…",updateInstalling:"Đang c\xe0i bản mới…",updateTimeout:"Cập nhật qu\xe1 l\xe2u",updateTimeoutHint:"Tải lại thủ c\xf4ng nếu kh\xf4ng phục hồi.",updateRestarting:"Đang khởi động lại agent…",updateReconnecting:"Đang kết nối lại…",updateDone:"Đ\xe3 cập nhật! Đang tải lại…",version:"Phi\xean bản",orientation:"Xoay m\xe0n h\xecnh",orientationPortrait:"Dọc",orientationLandscape:"Ngang",orientationAuto:"Tự động"},workspace:{loading:"Đang tải...",logoutTitle:"Đăng xuất",logoutMessage:"Bạn c\xf3 chắc muốn đăng xuất?",failedCreateSession:"Kh\xf4ng tạo được session: {error}",failedRenameSession:"Kh\xf4ng đổi t\xean được session: {error}"},sessions:{headerTitle:"9remote.cc",connected:"Đ\xe3 kết nối",disconnected:"Mất kết nối",codespaceStopped:"Codespace đ\xe3 dừng",placeholder:"T\xean terminal (t\xf9y chọn)",newButton:"+ Tạo mới",empty:"Kh\xf4ng c\xf3 session n\xe0o",emptyHint:"Tạo session mới để bắt đầu",created:"Tạo l\xfac {time}",deleteTitle:"X\xf3a Session",deleteMessage:'Bạn c\xf3 chắc muốn x\xf3a "{name}"?',editName:"Sửa t\xean",maximize:"Ph\xf3ng to",restoreSplit:"Chia m\xe0n h\xecnh",openAsUi:"Mở dạng giao diện",openAsTerminal:"Mở dạng terminal",modeSwitchFailed:"Kh\xf4ng chuyển được chế độ",newTerminal:"Terminal mới",options:"Options"},workspaces:{title:"Workspace",newWorkspace:"Th\xeam workspace",newWorkspacePrompt:"T\xean workspace",defaultName:"Workspace mới",ungrouped:"Chưa c\xf3 workspace",addTerminal:"Terminal mới ở đ\xe2y",moveToWorkspace:"Chuyển sang workspace",rename:"Đổi t\xean workspace",delete:"Gỡ workspace",emptyWorkspace:"Chưa c\xf3 terminal",selectFolder:"Chọn thư mục",browse:"Duyệt",recentFolders:"Gần đ\xe2y",searchFolders:"Search folders...",parentFolder:"Up one level",drives:"Drives",homeFolder:"Home",hiddenFolders:"Hidden folders",selectNamed:'Choose "{name}"',enterPath:"Type a path and press Enter",pathNotFolder:"Đường dẫn n\xe0y kh\xf4ng phải thư mục",filterOrPath:"Search, or type a path like /home/me",notADirectory:'"{name}" is not a folder in {dir}',multipleDirMatches:'"{name}" matches several folders in {dir}',invalidPath:"Invalid path",openHere:"Terminal mới ở đ\xe2y",tabFiles:"File",tabGit:"Git",tabTrees:"Worktree",refreshRepos:"Qu\xe9t lại repo",onlyChanged:"Chỉ file đ\xe3 đổi",openFullFiles:"Open full file explorer",emptyTitle:"Chưa mở g\xec",cardWorkspaceTitle:"Workspace",cardWorkspaceDesc:"Mở thư mục v\xe0 chạy terminal trong đ\xf3",cardRemoteTitle:"Remote desktop",cardRemoteDesc:"Điều khiển m\xe0n h\xecnh m\xe1y n\xe0y",worktrees:"Worktree",branches:"Branch",newWorktree:"Worktree mới",worktreeName:"T\xean branch",worktreeRepoLabel:"Repo để tạo worktree",worktreeNameAscii:"T\xean n\xe0y kh\xf4ng tạo được branch — g\xf5 bằng chữ Latin.",addWorktree:"Th\xeam worktree",removeWorktree:"Gỡ worktree",removeWorktreeMessage:'Gỡ worktree ở "{path}"?',removeWorktreeFolder:"Thư mục: {path}",removeWorktreeBranchDelete:"Branch: {branch} (đ\xe3 merge — x\xf3a k\xe8m)",removeWorktreeBranchKeep:"Branch: {branch} (chưa merge — giữ lại)",removeWorktreeSessions:"{count} session b\xean trong: {names}",removeWorktreeBranch:'Branch "{branch}" cũng bị x\xf3a (nếu đ\xe3 merge).',worktreeBranchKept:'Branch "{branch}" được giữ lại: chưa merge.',worktreeBusy:"C\xf2n {count} terminal đang chạy trong worktree n\xe0y: {names}",worktreeDirty:"This worktree has modified or untracked files — forcing the removal deletes them for good. Continue?",checkedOut:"đang checkout",newBranch:"Branch mới",checkout:"Checkout",searchBranch:"T\xecm branch",worktreePath:"Đường dẫn worktree",nestedRepos:"{count} repo",showCleanRepos:"Hiện {count} repo kh\xf4ng đổi",showHiddenRepos:"Bỏ ẩn {count} repo",hideRepo:"Ẩn repo n\xe0y",scanDeeper:"Qu\xe9t s\xe2u hơn",deleteTitle:"Gỡ workspace",deleteMessage:'Gỡ workspace "{name}"? Terminal trong đ\xf3 sẽ đ\xf3ng. File tr\xean đĩa kh\xf4ng bị đụng.'},terminal:{quotaNoData:"No quota data",quotaUsageTitle:"usage",back:"Quay lại",menu:"Menu",newTerminal:"Terminal mới",remoteDesktop:"Điều khiển từ xa",defaultName:"Term"},files:{selectWorkspace:"Chọn Workspace",recentWorkspaces:"Workspace gần đ\xe2y",home:"Thư mục Home",root:"Thư mục gốc",drive:"Ổ đĩa {letter}",codespaces:"Codespaces",removeRecent:"X\xf3a khỏi danh s\xe1ch gần đ\xe2y",removeTitle:"X\xf3a Workspace",removeMessage:'X\xf3a "{name}" khỏi workspace gần đ\xe2y?',setAsWorkspace:"Chọn l\xe0m Workspace",openFolder:"Mở thư mục",newFile:"Tệp mới",newFolder:"Thư mục mới",rename:"Đổi t\xean",delete:"X\xf3a",deleteFile:"X\xf3a tệp",deleteFolder:"X\xf3a thư mục",deleteFileMessage:'X\xf3a "{name}"?',deleteFolderMessage:'X\xf3a thư mục "{name}" v\xe0 to\xe0n bộ nội dung?',emptyFolder:"Thư mục trống",git:"Git",parent:"Thư mục cha",workspace:"Workspace",failedLoad:"Kh\xf4ng tải được: {error}",failedDelete:"Kh\xf4ng x\xf3a được: {error}",failedCreate:"Kh\xf4ng tạo được: {error}",failedRename:"Kh\xf4ng đổi t\xean được: {error}",enterName:"Nhập t\xean",confirmRename:"Đổi t\xean th\xe0nh:",setWorkspace:"Đặt l\xe0m Workspace",setAsWorkspaceTitle:"Đặt l\xe0m workspace",switchWorkspace:"Đổi workspace",searchFiles:"T\xecm tệp",toggleHidden:"Ẩn/hiện tệp ẩn",searchPlaceholder:"T\xecm tệp...",searching:"Đang t\xecm...",noFilesFound:"Kh\xf4ng t\xecm thấy tệp",noGitRepo:"Kh\xf4ng c\xf3 git repository",cannotOpenBinary:"Kh\xf4ng thể mở tệp binary",createNew:"Tạo mới",file:"Tệp",folder:"Thư mục",placeholderFile:"filename.js",placeholderFolder:"ten-thu-muc",pickFile:"Choose files",pickFolder:"Choose folder",copyPath:"Sao ch\xe9p đường dẫn",copyRelPath:"Copy Relative Path",copyName:"Copy Filename",delete:"X\xf3a",rename:"Đổi t\xean",deleteConfirmTitle:"X\xf3a",deleteConfirmMessage:'X\xf3a "{name}"?'},editor:{save:"Lưu",saving:"Đang lưu...",saved:"Đ\xe3 lưu",unsaved:"C\xf3 thay đổi chưa lưu",close:"Đ\xf3ng",discard:"Bỏ thay đổi",discardTitle:"Bỏ thay đổi",discardMessage:"Bạn c\xf3 thay đổi chưa lưu. Bỏ thay đổi?",unsavedTitle:"Lưu thay đổi cho {name}?",unsavedBody:"Kh\xf4ng lưu th\xec c\xe1c thay đổi sẽ mất.",failedLoad:"Kh\xf4ng tải được tệp: {error}",failedSave:"Kh\xf4ng lưu được: {error}",openFull:"Open in full editor",artifact:"Artifact",readOnly:"Chỉ đọc",line:"D\xf2ng",column:"Cột",gitDiff:"Git Diff",typeText:"Nhập chữ v\xe0 ch\xe8n...",insert:"Ch\xe8n",statusModified:"Đ\xe3 sửa",statusAdded:"Đ\xe3 th\xeam",statusUntracked:"Chưa theo d\xf5i"},git:{title:"Git",branch:"Nh\xe1nh",changes:"Thay đổi",staged:"Đ\xe3 staged",unstaged:"Chưa staged",untracked:"Chưa theo d\xf5i",commit:"Commit",commitAndPush:"Commit & Push",commitSuccess:"Commit successful",pushSuccess:"Push successful",stageFailed:"Failed to stage changes",commitFailed:"Commit failed",pushFailed:"Push failed",pullSuccess:"Pull successful",pullFailed:"Pull failed",stageAllConfirmTitle:"Stage All & Commit",stageAllConfirmMessage:"No changes are staged. Stage all changes and commit?",stageAndCommit:"Stage & Commit",gitActions:"Git actions",commitPlaceholder:"Commit message…",stageAllNote:"Stage all \xb7 {count}",upToDate:"Everything up-to-date",commitMessage:"Nội dung commit",push:"Push",pull:"Pull",fetch:"Fetch",stage:"Stage",stageAll:"Stage tất cả",unstage:"Unstage",discard:"Bỏ thay đổi",discardChanges:"Bỏ thay đổi",discardMessage:'Bỏ thay đổi của "{name}"?',noChanges:"Kh\xf4ng c\xf3 thay đổi",diff:"Diff",pushing:"Đang push...",pulling:"Đang pull...",committing:"Đang commit...",failedCommit:"Kh\xf4ng commit được: {error}",failedPush:"Kh\xf4ng push được: {error}",failedPull:"Kh\xf4ng pull được: {error}",status:"Trạng th\xe1i",diffTab:"Diff",modified:"Đ\xe3 sửa",added:"Đ\xe3 th\xeam",deleted:"Đ\xe3 x\xf3a",untrackedTitle:"Chưa theo d\xf5i",openFile:"Mở tệp",discardChangesTitle:"Bỏ thay đổi",discardConfirmTitle:"Bỏ thay đổi",discardConfirmDelete:'Bạn c\xf3 chắc muốn x\xf3a "{name}"? Kh\xf4ng thể ho\xe0n t\xe1c.',discardConfirmDiscard:'Bạn c\xf3 chắc muốn bỏ thay đổi của "{name}"? Kh\xf4ng thể ho\xe0n t\xe1c.'},remote:{title:"Điều khiển từ xa",connecting:"Đang kết nối...",disconnected:"Mất kết nối",fullscreen:"To\xe0n m\xe0n h\xecnh",exitFullscreen:"Tho\xe1t to\xe0n m\xe0n h\xecnh",receivingImage:"Đang nhận h\xecnh…",keyboard:"B\xe0n ph\xedm",mouse:"Chuột",quality:"Chất lượng",fps:"FPS",debug:"Debug",help:"Trợ gi\xfap",close:"Đ\xf3ng",sendKey:"Gửi ph\xedm",helpTitle:"Trợ gi\xfap điều khiển từ xa",notAvailable:"Điều khiển từ xa kh\xf4ng khả dụng",customizeKeys:"T\xf9y chỉnh ph\xedm",back:"Quay lại",resetZoom:"Đặt lại zoom",refresh:"L\xe0m mới",rectangleSelection:"Chọn v\xf9ng chữ nhật",handMode:"Chế độ tay",toggleKeyboard:"Bật/tắt b\xe0n ph\xedm hệ thống",hideControls:"Hide controls",showControls:"Show controls",textBatchInput:"Nhập văn bản h\xe0ng loạt",extraKeys:"Ph\xedm mở rộng",customizeRemoteKeys:"T\xf9y chỉnh ph\xedm Remote",exitRemote:"Tho\xe1t điều khiển từ xa",debugTitle:"Thống k\xea Debug",minimize:"Thu nhỏ",transport:"Giao thức",latency:"Độ trễ",tilesPerSec:"Tiles/gi\xe2y",bandwidth:"Băng th\xf4ng",clearStats:"X\xf3a thống k\xea",lockTitle:"Windows đang kh\xf3a",lockGrantDesc:'Bật "Mở kh\xf3a m\xe1y từ xa" trong 9remote host tr\xean m\xe1y n\xe0y.',lockDesc:"Nhập m\xe3 PIN hoặc mật khẩu Windows của m\xe1y n\xe0y",lockPlaceholder:"M\xe3 PIN hoặc mật khẩu Windows",unlock:"Mở kh\xf3a",unlocking:"Đang mở kh\xf3a…",unlockFailed:"Mở kh\xf3a thất bại — kiểm tra m\xe3 PIN/mật khẩu v\xe0 thử lại."},remoteHelp:{modePc:"PC / Chuột",modeTrackpad:"Cảm ứng \xb7 Trackpad",modeDirect:"Cảm ứng \xb7 Trực tiếp",mouseTitle:"Chuột",keyboardTitle:"B\xe0n ph\xedm",gesturesTrackpadTitle:"Cử chỉ (Trackpad ✋)",gesturesDirectTitle:"Cử chỉ (Trực tiếp)",toolbarTitle:"Thanh c\xf4ng cụ",mouseClickKey:"Click / K\xe9o",mouseClickDesc:"Chuột tr\xe1i, k\xe9o để chọn/di chuyển",mouseRightKey:"Chuột phải",mouseRightDesc:"Mở menu ngữ cảnh tr\xean remote",mouseWheelKey:"Cuộn chuột",mouseWheelDesc:"Cuộn remote (Shift + Cuộn = ngang)",mouseDoubleKey:"Double-click",mouseDoubleDesc:"Nhấp đ\xfap tr\xean remote",keyPhysicalKey:"Ph\xedm vật l\xfd",keyPhysicalDesc:"Gửi trực tiếp (Tab, F-keys... được bắt)",keyModifierKey:"Ctrl / Alt / Shift / ⌘",keyModifierDesc:"Ph\xedm modifier d\xednh — kết hợp với ph\xedm tiếp theo",trackpadSwipeKey:"1 ng\xf3n vuốt",trackpadSwipeDesc:"Di chuyển con trỏ ảo",trackpadTapKey:"1 ng\xf3n chạm",trackpadTapDesc:"Click tr\xe1i tại con trỏ",trackpad2TapKey:"2 ng\xf3n chạm",trackpad2TapDesc:"Click phải tại con trỏ",trackpad2SwipeKey:"2 ng\xf3n vuốt",trackpad2SwipeDesc:"Cuộn tại vị tr\xed con trỏ",trackpadPinchKey:"2 ng\xf3n chụm",trackpadPinchDesc:"Zoom canvas",trackpadScrollLockKey:"Giữ + k\xe9o",trackpadScrollLockDesc:"Giữ để kh\xf3a cuộn, k\xe9o mọi hướng",directTapKey:"1 ng\xf3n chạm",directTapDesc:"Click tại vị tr\xed chạm",directLongKey:"1 ng\xf3n giữ l\xe2u",directLongDesc:"Click phải",directDoubleKey:"1 ng\xf3n chạm đ\xfap",directDoubleDesc:"Nhấp đ\xfap",directScrollKey:"2 ng\xf3n vuốt",directScrollDesc:"Cuộn remote",directPinchKey:"2 ng\xf3n chụm",directPinchDesc:"Zoom canvas",directPanKey:"1 ng\xf3n k\xe9o (zoom>1)",directPanDesc:"Di chuyển canvas",toolbarHandDesc:"Giữ chuột tr\xe1i (chế độ k\xe9o) — chạm lần nữa để thả",toolbarMouseDirectDesc:"Chuyển sang chế độ Trực tiếp",toolbarMouseTrackpadDesc:"Chuyển sang Trackpad (con trỏ ảo)",toolbarKeyboardDesc:"B\xe0n ph\xedm hệ thống / nhập văn bản h\xe0ng loạt",toolbarRectDesc:"Chế độ chọn v\xf9ng chữ nhật"},remoteControls:{enterToSend:"Tab / Ctrl+Số để chuyển tab",typeToSend:"Nhập văn bản để gửi...",send:"Gửi",trackpadMode:"Chế độ trackpad",directMode:"Chế độ direct",bottomRow:"H\xe0ng dưới",extraPanel:"Bảng mở rộng",exitConfirmMessage:"Bạn c\xf3 chắc muốn tho\xe1t phi\xean điều khiển từ xa hiện tại?"},connection:{retrying:"Đang kết nối lại...",waitingApproval:"Đang chờ ph\xea duyệt",approvalDescription:"9Remote host cần ph\xea duyệt thiết bị n\xe0y trước khi bạn c\xf3 thể kết nối.",approvalHint:"Kiểm tra terminal tr\xean m\xe1y của bạn.",rejectedTitle:"Thiết bị bị từ chối",rejectedDescription:"Thiết bị n\xe0y kh\xf4ng được 9Remote host ph\xea duyệt.",backToLogin:"Quay lại Đăng nhập",failed:"Kết nối thất bại",failedDescription:"Kh\xf4ng thể kết nối sau {n} lần thử",attemptOf:"Lần {n} / {total}",exit:"Tho\xe1t",cancel:"Hủy",retry:"Thử lại ngay"},notifications:{claudeCode:"Claude Code",codex:"Codex",geminiCli:"Gemini CLI",openCode:"OpenCode",title:"Th\xf4ng b\xe1o",empty:"Kh\xf4ng c\xf3 th\xf4ng b\xe1o",needsInput:"cần nhập liệu",badgeTitle:"{blocked} needs input, {done} your turn",replied:"đ\xe3 trả lời",agent:"Agent"},sites:{title:"Trang web",localSites:"Site cục bộ",selectSitePreview:"Chọn site để xem trước",browserNewTab:"New tab",browserAddressPlaceholder:"localhost:3000 or /path",browserNotConnected:"Connect to your agent first",portPlaceholder:"cổng",loadingSites:"Đang tải Sites...",notConnected:"Chưa kết nối tới agent",noSitesFound:"Kh\xf4ng t\xecm thấy site",startServerHint:"H\xe3y chạy local dev server để thấy tại đ\xe2y",siteNamePlaceholder:"T\xean site",saveTitle:"Lưu",editNameTitle:"Sửa t\xean",removeTitle:"X\xf3a",removePortTitle:"X\xf3a cổng",removePortMessage:"X\xf3a cổng {port} khỏi danh s\xe1ch đ\xe3 lưu?",popupBlocked:"Popup đ\xe3 bị chặn! H\xe3y cho ph\xe9p popup cho trang n\xe0y.",startProxyFailed:"Kh\xf4ng thể khởi tạo proxy cho {name}",foundCount:"T\xecm thấy {n} site{suffix}",focusOpenedTab:"Focus tab đ\xe3 mở",openInNewTab:"Mở tab mới",goBack:"Quay lại",goForward:"Tiến tới",loadingSite:"Đang tải...",empty:"Kh\xf4ng c\xf3 site n\xe0o đang chạy",emptyHint:"Chạy local server để xem ở đ\xe2y",open:"Mở",refresh:"Tải lại"},commandNotes:{title:"Ghi ch\xfa lệnh",noSavedCommands:"Chưa c\xf3 lệnh đ\xe3 lưu",addFirstBelow:"Th\xeam lệnh đầu ti\xean b\xean dưới",clickToCopy:"Bấm để sao ch\xe9p",copiedBang:"Đ\xe3 sao ch\xe9p!",copy:"Sao ch\xe9p",edit:"Sửa",delete:"X\xf3a",editCommandPlaceholder:"Sửa lệnh...",addCommandPlaceholder:"Th\xeam lệnh...",update:"Cập nhật",add:"Th\xeam",empty:"Chưa c\xf3 ghi ch\xfa",emptyHint:"Lưu lệnh để truy cập nhanh",add:"Th\xeam ghi ch\xfa",edit:"Sửa ghi ch\xfa",delete:"X\xf3a ghi ch\xfa",deleteMessage:"X\xf3a ghi ch\xfa n\xe0y?",name:"T\xean",command:"Lệnh",save:"Lưu",placeholderName:"vd: Khởi động dev server",placeholderCommand:"vd: npm run dev"},mobileKeyboard:{pasteHere:"D\xe1n v\xe0o đ\xe2y (Cmd+V)",enterToSend:"{shortcut} to switch tab",typeCommand:"Nhập lệnh v\xe0 gửi...",send:"Gửi",toggleExtraKeys:"Bật/tắt ph\xedm mở rộng",toggleTextInput:"Bật/tắt \xf4 nhập văn bản",customizeTerminalKeys:"T\xf9y chỉnh ph\xedm Terminal",mainBar:"Thanh ch\xednh",extraPanel:"Bảng mở rộng",fileTooLarge:"File qu\xe1 lớn (tối đa 5MB)",readFileFailed:"Kh\xf4ng thể đọc file",uploadFailed:"Tải file thất bại: {error}"},terminalPane:{scrollToBottom:"Cuộn xuống cuối",changedFiles:"Changed files",pasteOrType:"D\xe1n hoặc nhập tại đ\xe2y",paste:"D\xe1n"},pwaGuide:{copyYourKey:"Sao ch\xe9p Key của bạn",copyKeyHint:"Nhấn v\xe0o key b\xean dưới để sao ch\xe9p — bạn sẽ cần để đăng nhập sau khi c\xe0i",tapToCopyApiKey:"Nhấn để sao ch\xe9p API key",copiedBang:"Đ\xe3 sao ch\xe9p!",copy:"Sao ch\xe9p",tapShareButton:"Nhấn n\xfat Share",tapShareHint:"Nhấn n\xfat share ở dưới c\xf9ng của Safari",addToHome:"Th\xeam v\xe0o M\xe0n h\xecnh ch\xednh",addToHomeHint:'Cuộn xuống v\xe0 nhấn "Add to Home Screen"',openAppPasteKey:"Mở app v\xe0 d\xe1n key",openAppPasteKeyHint:"Mở app đ\xe3 c\xe0i v\xe0 d\xe1n key để đăng nhập",openMenu:"Mở Menu",openMenuHint:"Nhấn n\xfat menu (ba chấm) trong Chrome",installApp:"C\xe0i ứng dụng",installAppHint:'Nhấn "Install app" hoặc "Add to Home screen"',lookInstallIcon:"T\xecm icon c\xe0i đặt",lookInstallIconHint:"T\xecm icon c\xe0i đặt tr\xean thanh địa chỉ",clickInstallPaste:"Nhấn c\xe0i v\xe0 d\xe1n key",installNow:"Install Now",installNowHint:"Install 9Remote as an app for quick access",installing:"Installing...",clickInstallPasteHint:"Nhấn c\xe0i, mở app, v\xe0 d\xe1n key để đăng nhập",alternativeHint:'C\xe1ch kh\xe1c: Mở menu tr\xecnh duyệt → "Install 9Remote" hoặc "Create shortcut"',loadingPlatform:"Đang nhận diện nền tảng...",iosPlatform:"iOS (iPhone/iPad)",androidPlatform:"Android",macosPlatform:"macOS",windowsPlatform:"Windows",desktopPlatform:"Desktop",alreadyInstalled:"Đ\xe3 c\xe0i đặt!",alreadyInstalledHint:"Bạn đang d\xf9ng 9Remote dưới dạng app đ\xe3 c\xe0i",installationGuide:"Hướng dẫn c\xe0i đặt",installationSteps:"C\xe1c bước c\xe0i đặt:"},community:{title:"Cộng đồng",description:"Tham gia cộng đồng 9Remote"},pwa:{title:"C\xe0i đặt như Ứng dụng",description:"C\xe0i 9Remote v\xe0o thiết bị để c\xf3 trải nghiệm tốt nhất",iosTitle:"iOS Safari",androidTitle:"Android Chrome",desktopTitle:"M\xe1y t\xednh"},codespace:{title:"Codespace",name:"T\xean",status:"Trạng th\xe1i",running:"Đang chạy",autoStart:"Tự khởi động 9Remote",autoStartHint:"Khởi động 9Remote khi mở codespace",stop:"Dừng Codespace",stopHint:"Dừng để tiết kiệm t\xe0i nguy\xean",restartHint:"Để khởi động lại, v\xe0o GitHub",unknown:"Kh\xf4ng x\xe1c định"}}}}]);
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[5788],{2163:(e,t,n)=>{"use strict";function r(e){if(!e)return"";if(e.length<=14)return e;let t=e.substring(0,8),n=e.substring(e.length-6),r="•".repeat(12);return`${t}${r}${n}`}n.d(t,{o:()=>r})},2805:(e,t,n)=>{"use strict";n.d(t,{XS:()=>o,_r:()=>s,d8:()=>l,es:()=>c,sP:()=>a});var r=n(90076);let i=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;function s(){let e=window.location.hostname;return"localhost"===e||"::1"===e||"[::1]"===e||e.startsWith("127.")||e.endsWith(".localhost")}function a(){return s()||!!window.__TAURI__}function o(){return!!window.__TAURI__||window.location.port===String(r._8)||!0}function l(){if(s())return!0;let e=i.exec(window.location.hostname);if(!e||e.slice(1).some(e=>Number(e)>255))return!1;let t=Number(e[1]),n=Number(e[2]);return 10===t||192===t&&168===n||172===t&&!!(n>=16)&&!!(n<=31)}function c(e){return s()&&window.location.port!==String(r._8)?e?.loopbackOrigin||r.lE:null}},4018:(e,t,n)=>{"use strict";n.d(t,{N:()=>i.N0,u:()=>l});var r=n(1521),i=n(86129);let s="9remote_api_keys",a=()=>{window.dispatchEvent(new Event(i.N0))};function o(e){try{return btoa(e)}catch{return e}}function l(){let e=(0,r.useCallback)(()=>{try{let e=localStorage.getItem(s);if(!e)return[];return JSON.parse(e).map(e=>({...e,key:function(e){try{return atob(e)}catch{return e}}(e.key)}))}catch(e){return console.error("Failed to load API keys:",e),[]}},[!0]),t=(0,r.useCallback)((t,n="")=>{if(t&&1)try{let r=e(),i=r.findIndex(e=>e.key===t);if(-1!==i){let e=r.map((e,t)=>({...e,key:o(e.key),lastLoginDate:t===i?new Date().toISOString():e.lastLoginDate}));localStorage.setItem(s,JSON.stringify(e));return}let l={id:Date.now().toString(),key:o(t),label:n||`Key ${r.length+1}`,createdAt:new Date().toISOString(),lastLoginDate:new Date().toISOString()},c=[...r.map(e=>({...e,key:o(e.key)})),l];localStorage.setItem(s,JSON.stringify(c)),a()}catch(e){console.error("Failed to save API key:",e)}},[!0,e]),n=(0,r.useCallback)(t=>{try{let n=e().filter(e=>e.id!==t).map(e=>({...e,key:o(e.key)}));localStorage.setItem(s,JSON.stringify(n)),a()}catch(e){console.error("Failed to remove API key:",e)}},[!0,e]),i=(0,r.useCallback)(()=>{try{localStorage.removeItem(s)}catch(e){console.error("Failed to clear API keys:",e)}},[!0]),l=(0,r.useCallback)(()=>{try{let e=localStorage.getItem(s);if(!e)return!1;return JSON.parse(e).length>0}catch{return!1}},[!0]),c=(0,r.useCallback)((t,n)=>{try{let r=e().map(e=>({...e,key:o(e.key),label:e.id===t?n:e.label||""}));localStorage.setItem(s,JSON.stringify(r)),a()}catch(e){console.error("Failed to rename API key:",e)}},[!0,e]),d=(0,r.useCallback)(t=>{if(t&&1)try{let n=e().map(e=>({...e,key:o(e.key),lastLoginDate:e.key===t?new Date().toISOString():e.lastLoginDate}));localStorage.setItem(s,JSON.stringify(n))}catch(e){console.error("Failed to update last login date:",e)}},[!0,e]);return{saveKey:t,loadKeys:e,removeKey:n,renameKey:c,clearKeys:i,hasStoredKeys:l,updateLastLogin:d}}},7938:(e,t,n)=>{"use strict";n.d(t,{D5:()=>a,FO:()=>c,I9:()=>l,Ic:()=>o,eR:()=>r,ij:()=>s,tC:()=>i});let r={namespace:"/remote",enableWebRTC:!0,enableTurn:!1,debug:{transport:!1,remote:!1,panel:!1,showButton:!1},dcChunkSize:8,dcReliable:!1,dcOrdered:!1,hashRequestInterval:1500,lastDataThreshold:500,restreamDelay:200,mouseThrottle:8,keyThrottle:25,scrollInterval:100,tileLoadTimeout:600,batchSize:16,batchDelay:3,decodeQueueCap:48,resizeDebounceMs:100,resizeStableFrames:3,resizeMaxFrames:30,focusDebounce:50,longPressDelay:1e3,doubleClickDelay:300,moveThreshold:10,edgeScrollThreshold:15,edgeScrollMultiplier:1.5,momentumFriction:.94,momentumMinVelocity:.3,pointerMode:"trackpad",trackpadSensitivity:1.3,trackpadAcceleration:1.5,trackpadTapMaxMove:8,trackpadTapMaxDuration:220,trackpadCursorSize:20,trackpadEdgeMarginRatio:.25,clipboardBadgeTimeout:1e4,gestureLockDelay:80,gestureDistanceThreshold:15,gestureCentroidThreshold:10,gestureDominanceRatio:2,wheelScrollMultiplier:2.5,wheelLineHeight:40,wheelPageHeight:400,wheelZoomStep:.1,wheelBoostInterval:250,mouseButtonMap:{0:"left",1:"middle",2:"right"},pcModeControls:{rectangleSelect:!1,pointerModeToggle:!1,handMode:!1,keyboardToggle:!1,textPanel:!0,modifierRow:!0,help:!0}},i={ctrl:"control",cmd:"command",alt:"alt",shift:"shift"},s=[{id:"ctrl",label:"Ctrl",modifier:"ctrl",type:"modifier"},{id:"alt",label:"Alt",modifier:"alt",type:"modifier"},{id:"shift",label:"Shift",modifier:"shift",type:"modifier"},{id:"cmd",label:"⌘",modifier:"cmd",type:"modifier"},{id:"esc",label:"Esc",key:"escape",type:"key"},{id:"tab",label:"Tab",key:"tab",type:"key"},{id:"enter",label:"↵",key:"enter",type:"key",primary:!0},{id:"backspace",label:"⌫",key:"backspace",type:"key"},{id:"undo",label:"Undo",key:"z",modifiers:["control"],type:"combo",osAdaptive:!0},{id:"redo",label:"Redo",key:"z",modifiers:["control","shift"],type:"combo",osAdaptive:!0},{id:"up",label:"↑",key:"up",type:"arrow"},{id:"down",label:"↓",key:"down",type:"arrow"},{id:"left",label:"←",key:"left",type:"arrow"},{id:"right",label:"→",key:"right",type:"arrow"},{id:"home",label:"Home",key:"home",type:"key"},{id:"end",label:"End",key:"end",type:"key"},{id:"pgup",label:"PgUp",key:"pageup",type:"key"},{id:"pgdn",label:"PgDn",key:"pagedown",type:"key"},{id:"del",label:"Del",key:"delete",type:"key"},{id:"ins",label:"Ins",key:"insert",type:"key"},{id:"f1",label:"F1",key:"f1",type:"key"},{id:"f2",label:"F2",key:"f2",type:"key"},{id:"f3",label:"F3",key:"f3",type:"key"},{id:"f4",label:"F4",key:"f4",type:"key"},{id:"f5",label:"F5",key:"f5",type:"key"},{id:"f6",label:"F6",key:"f6",type:"key"},{id:"f7",label:"F7",key:"f7",type:"key"},{id:"f8",label:"F8",key:"f8",type:"key"},{id:"f9",label:"F9",key:"f9",type:"key"},{id:"f10",label:"F10",key:"f10",type:"key"},{id:"f11",label:"F11",key:"f11",type:"key"},{id:"f12",label:"F12",key:"f12",type:"key"},{id:"ctrlAltDel",label:"Ctl+Alt+Del",key:"delete",modifiers:["control","alt"],type:"combo"},{id:"ctrlShiftEsc",label:"Task Mgr",key:"escape",modifiers:["control","shift"],type:"combo"},{id:"altTab",label:"Alt+Tab",key:"tab",modifiers:["alt"],type:"combo"},{id:"altF4",label:"Alt+F4",key:"f4",modifiers:["alt"],type:"combo"},{id:"winKey",label:"Win",key:"command",type:"key"},{id:"printScreen",label:"PrtSc",key:"printscreen",type:"key"},{id:"paste",label:"Paste",key:"v",modifiers:["control"],type:"combo",osAdaptive:!0},{id:"cut",label:"Cut",key:"x",modifiers:["control"],type:"combo",osAdaptive:!0},{id:"selectAll",label:"All",key:"a",modifiers:["control"],type:"combo",osAdaptive:!0},{id:"desktopPrev",label:"◀ Desk",type:"desktop",direction:"prev"},{id:"desktopNext",label:"Desk ▶",type:"desktop",direction:"next"},{id:"desktopNew",label:"+ Desk",type:"desktop",direction:"new"}],a=["esc","undo","up","down","tab","ctrl","alt","shift","cmd","backspace"],o="enter",l=[["left","right","home","end","pgup","pgdn","del"],["f1","f2","f3","f4","f5","f6","f7","altTab"],["f9","f10","f11","f12","ctrlAltDel",,"desktopPrev","desktopNext","desktopNew"]],c={enter:"enter",return:"enter",space:" ",backspace:"backspace",tab:"tab",escape:"escape",Enter:"enter"," ":"space",Backspace:"backspace",Tab:"tab",Escape:"escape",ArrowUp:"up",ArrowDown:"down",ArrowLeft:"left",ArrowRight:"right",Home:"home",End:"end",PageUp:"pageup",PageDown:"pagedown",Delete:"delete",Insert:"insert",F1:"f1",F2:"f2",F3:"f3",F4:"f4",F5:"f5",F6:"f6",F7:"f7",F8:"f8",F9:"f9",F10:"f10",F11:"f11",F12:"f12",CapsLock:"capslock",NumLock:"numlock",ScrollLock:"scrolllock",PrintScreen:"printscreen",ContextMenu:"menu"}},11155:(e,t,n)=>{"use strict";function r(e){return"string"==typeof e&&!!e&&/^sk-[a-z0-9]{8}-[a-z0-9]{4}-[0-9a-f]{6}$/.test(e.trim().toLowerCase())}function i(e){if("string"!=typeof e||!/^sk-[a-z0-9]{8}-[a-np-z1-9]{8}-[a-np-z1-9]{8}$/.test(e))return e||null;let t=e.split("-");return`${t[0]}-${t[1]}-${t[2]}`}function s(e){return"string"==typeof e&&/^sk-[a-z0-9]{8}-[a-np-z1-9]{8}-[a-np-z1-9]{8}$/.test(e)?e.split("-")[3]:null}n.d(t,{Cj:()=>s,PF:()=>r,Uo:()=>i})},11865:(e,t,n)=>{"use strict";n.d(t,{A:()=>l});var r=n(73365),i=n(1521),s=n(64683),a=n(80186),o=n(78762);function l({isOpen:e,onClose:t,onScan:c}){let{t:d}=(0,o.s)(),u=(0,i.useRef)(null),p=(0,i.useRef)(null),h=(0,i.useRef)(null),m=(0,i.useRef)(null),g=(0,i.useRef)(null),[f,y]=(0,i.useState)(""),[b,_]=(0,i.useState)(""),w=(0,i.useCallback)(async e=>{if(p.current)try{await p.current.stop()}catch(e){}_("detected"),await new Promise(e=>setTimeout(e,300)),_("authenticating"),await c(e)||(_(""),g.current?.())},[c]),k=(0,i.useCallback)(async()=>{if(!h.current){let e=await Promise.all([n.e(3446),n.e(6075)]).then(n.bind(n,16075)).catch(()=>null);if(!e)return void y(d("login.qrLibFail"));h.current=e.Html5Qrcode}let e=document.getElementById("qr-reader");if(!e)return void y(d("login.qrInitFail"));try{e.innerHTML="";let t=new h.current("qr-reader");p.current=t,await t.start({facingMode:"environment"},{fps:10,qrbox:{width:250,height:250}},e=>{m.current?.(e)},()=>{})}catch(t){let e=t.toString();e.includes("NotAllowedError")?y(d("login.qrCamDenied")):e.includes("NotFoundError")?y(d("login.qrNoCamera")):e.includes("NotReadableError")?y(d("login.qrCamBusy")):y(d("login.qrCamError"))}},[d]),v=(0,i.useCallback)(async()=>{if(p.current){try{await p.current.stop()}catch(e){}p.current=null}y(""),_(""),t()},[t]);return((0,i.useEffect)(()=>{m.current=w},[w]),(0,i.useEffect)(()=>{if(!e)return;let t=!1;g.current=async()=>{p.current=null,await new Promise(e=>setTimeout(e,400)),t||k()};let n=setTimeout(()=>{t||k()},200);return()=>{if(t=!0,clearTimeout(n),g.current=null,p.current){try{p.current.stop()}catch(e){}p.current=null}}},[e,k]),e)?(0,r.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm",children:(0,r.jsxs)("div",{className:"relative card-elev max-w-md w-full mx-4 overflow-hidden",children:[(0,r.jsxs)("div",{className:"flex items-center justify-between p-4 border-b border-border",children:[(0,r.jsx)("h2",{className:"text-xl font-bold text-text",children:d("login.qrScanTitle")}),(0,r.jsx)("button",{onClick:v,className:"text-text-muted hover:text-text transition-colors p-1",children:(0,r.jsx)(s.X,{size:24})})]}),(0,r.jsx)("div",{className:"relative bg-black",children:(0,r.jsx)("div",{id:"qr-reader",ref:u,className:"w-full",style:{minHeight:"300px"}})}),(0,r.jsxs)("div",{className:"p-4",children:[f?(0,r.jsxs)("div",{className:"flex items-start gap-2 p-3 bg-red-500/10 rounded-brand text-red-400",children:[(0,r.jsx)(s.RI,{size:20,className:"flex-shrink-0 mt-0.5"}),(0,r.jsx)("p",{className:"text-sm",children:f})]}):"detected"===b?(0,r.jsxs)("div",{className:"flex items-center justify-center gap-2 p-3 bg-green-500/10 rounded-brand text-green-400",children:[(0,r.jsx)(s.vW,{size:22}),(0,r.jsx)("p",{className:"text-sm font-medium",children:d("login.qrDetected")})]}):"authenticating"===b?(0,r.jsx)("div",{className:"flex items-center justify-center gap-2 p-3 bg-brand-500/10 rounded-brand text-brand-400",children:(0,r.jsx)("p",{className:"text-sm font-medium",children:d("login.qrAuthenticating")})}):(0,r.jsx)("p",{className:"text-sm text-text-muted text-center",children:d("login.qrHint")}),(0,r.jsx)(a.A,{variant:"secondary",onClick:v,disabled:"authenticating"===b,className:"w-full mt-4",children:"authenticating"===b?d("login.qrPleaseWait"):d("common.cancel")})]})]})}):null}},18057:(e,t,n)=>{"use strict";n.d(t,{A:()=>c});var r=n(73365),i=n(1521),s=n(64683),a=n(8910),o=n(78762),l=n(52345);function c({isOpen:e,onClose:t}){let{t:n,locale:d,setLocale:u}=(0,o.s)();return((0,i.useEffect)(()=>{if(!e)return;let n=e=>{"Escape"===e.key&&t()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[e,t]),e)?(0,r.jsxs)("div",{className:"fixed inset-0 z-[60] flex items-center justify-center p-4",children:[(0,r.jsx)("div",{className:"absolute inset-0 bg-black/60 backdrop-blur-[2px] animate-in fade-in duration-200",onClick:t}),(0,r.jsxs)("div",{className:"relative card-elev max-w-lg w-full max-h-[90dvh] flex flex-col animate-in zoom-in-95 duration-200",children:[(0,r.jsxs)("div",{className:"px-5 py-4 flex items-center justify-between flex-shrink-0",children:[(0,r.jsx)("h3",{className:"text-lg font-semibold text-text",children:n("menu.language")}),(0,r.jsx)("button",{onClick:t,className:"p-2 text-text-muted hover:text-text hover:bg-surface-2 rounded-brand transition-all duration-150 ease-out","aria-label":n("common.close"),children:(0,r.jsx)(s.X,{size:20})})]}),(0,r.jsx)("div",{className:"flex-1 overflow-y-auto modal-scrollable p-3",children:(0,r.jsx)("div",{className:"grid grid-cols-2 sm:grid-cols-3 gap-2",children:l.dI.map(e=>{let n=e.code===d;return(0,r.jsxs)("button",{onClick:()=>{var n;return n=e.code,void((0,a.e)(),u(n),t())},className:`px-2 py-2 rounded-brand flex items-center gap-2 transition-all duration-150 ease-out active:scale-[0.97] min-w-0 ${n?"bg-brand-500 text-white":"text-text hover:bg-surface-2"}`,children:[(0,r.jsx)("img",{src:`https://flagcdn.com/w80/${e.country}.png`,alt:e.label,className:"w-5 h-[14px] object-cover rounded-[2px] flex-shrink-0",loading:"lazy"}),(0,r.jsx)("span",{className:"flex-1 text-sm font-medium truncate text-left",children:e.label}),n&&(0,r.jsx)(s.aJ,{size:14,className:"flex-shrink-0"})]},e.code)})})})]})]}):null}},20464:(e,t,n)=>{"use strict";n.d(t,{As:()=>g,zg:()=>u});var r=n(1521),i=n(29717),s=n(90076),a=n(11155),o=n(90084),l=n(2805),c=n(97711);let d="wrong-key-tail";async function u(e,t,n=s.qn){try{let t=new AbortController,r=setTimeout(()=>t.abort(),n),i=await fetch(`${e}/api/health`,{signal:t.signal});return clearTimeout(r),i.ok}catch{return!1}}async function p(e,{tail:t,tempKey:n},r=s.qn){try{let i=new AbortController,s=setTimeout(()=>i.abort(),r),a=await fetch(`${e}/api/verify-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tail:t||null,tempKey:n||null}),signal:i.signal});if(clearTimeout(s),!a.ok)return null;return(await a.json())?.ok===!0}catch{return null}}async function h(){return(0,l._r)()?(0,l.es)(await m()):(0,l.d8)()?window.location.origin:null}async function m(){try{let e=await fetch(s.Go);return e.ok?await e.json():null}catch{return null}}function g(){let[e,t]=(0,r.useState)(!1),[n,l]=(0,r.useState)(""),u=(0,i.useRouter)(),{setAuth:g}=(0,c.Fo)(),f=(0,r.useCallback)(async(e,{persistSession:n=!0}={})=>{t(!0),l("");try{let t,r=await h();if(r){let t=e.tail||(0,a.Cj)(e.apiKey||""),i=e.tempKey||(e.token?.length<=8?e.token:null),s=await m(),c=(0,a.Uo)(s?.permanentKey||""),u=(0,a.Uo)(e.apiKey||e.token||""),h=String(s?.oneTimeKey||"").slice(0,6).toUpperCase(),f=i?!!h&&h===i.toUpperCase():!!c&&!!u&&(0,a.Uo)(c)===u;try{let s=f?await p(r,{tail:t,tempKey:i}):null;if(!0===s){let s=e.apiKey||i||"",l=(0,a.Uo)(s)||"direct";return t&&(0,o.LG)(l,{tail:t}),n&&g({apiKey:l,tunnelUrl:r,mode:"local",tempKey:i?i.toUpperCase():null,localIp:null}),{success:!0,shouldAskToSave:!0,apiKey:l}}if(!1===s)return l(d),{success:!1,wrongTail:!0}}catch{}}let i=new AbortController,c=setTimeout(()=>i.abort(),s.cC);try{t=await fetch(s.Sn.connect,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...e,apiKey:(0,a.Uo)(e.apiKey)}),signal:i.signal})}catch(e){throw Error(e?.name==="AbortError"?"Connection timed out. Please try again.":"Network error. Please try again.")}finally{clearTimeout(c)}if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.error||"Authentication failed")}let u=await t.json(),f=(0,a.Uo)(e.apiKey||u.apiKey);u.hostKeys?.x&&(0,o.LG)(f,{hostSealKey:u.hostKeys.x,hostPubKey:u.hostKeys.ed||null});let y=e.tail||(0,a.Cj)(e.apiKey||"");if(u.tunnelUrl&&(y||e.tempKey)){let t=await p(u.tunnelUrl,{tail:y,tempKey:e.tempKey||null});if(!1===t)return l(d),{success:!1,wrongTail:!0}}return n&&g({apiKey:f,tunnelUrl:u.tunnelUrl||null,mode:"remote",tempKey:e.tempKey?e.tempKey.toUpperCase():null,localIp:u.localIp||null}),{success:!0,shouldAskToSave:!0,apiKey:f}}catch(e){return l(e.message),{success:!1,error:e.message}}finally{t(!1)}},[u,g]);return{loading:e,error:n,setError:l,authenticateWithToken:(0,r.useCallback)(async(e,t=!1,n=null,r)=>t?f({token:e,tempKey:e,tail:n},r):f({token:e},r),[f]),authenticateWithApiKey:(0,r.useCallback)((e,t)=>f({apiKey:e},t),[f])}}},27520:(e,t,n)=>{"use strict";n.d(t,{FQ:()=>l,Lq:()=>m,UX:()=>o,k_:()=>d,yO:()=>c});var r=n(2805);let i=[],s=new Set,a=location.hostname.startsWith("dev.")||"localhost"===location.hostname&&!(0,r.XS)()||"1"===localStorage.getItem("9remote:termLog");function o(){return a}function l(){return i}function c(e){return s.add(e),()=>s.delete(e)}function d(){for(let e of(i.length=0,s))try{e(null)}catch(e){}}function u(e){if(null==e)return"";if(e instanceof Uint8Array||ArrayBuffer.isView(e)||e instanceof ArrayBuffer)return`<${e.byteLength}b>`;if("string"==typeof e)return e.length>120?`${e.slice(0,60)}…${e.length}b`:e;if("object"==typeof e)try{return JSON.stringify(e)}catch(e){}return String(e)}let p=new Set(["recv"]),h=null;function m(e,...t){if(!a)return;let n=Date.now(),r=t.map(u).join(" ");if(h&&h.category===e&&h.baseMsg===r&&n-h.ts<3e3||p.has(e)&&h&&h.category===e&&n-h.ts<300){h.count=(h.count||1)+1,h.ts=n,h.msg=`${r} \xd7${h.count}`,queueMicrotask(()=>{for(let e of s)try{e(h)}catch(e){}});return}let o={ts:n,category:e,msg:r,baseMsg:r,count:1};h=o,i.push(o),i.length>800&&i.shift();try{console.log(`[termLog ${e}] ${r}`)}catch{}queueMicrotask(()=>{for(let e of s)try{e(o)}catch(e){}})}},29091:(e,t,n)=>{"use strict";n.d(t,{B:()=>h});var r=n(2074),i=n(11472),s=n(34277),a=n(61826),o=n(33897);let l=(e,{min:t,max:n})=>Math.max(t,Math.min(n,Math.round(e)));var c=n(79253);let d={name:null,value:null},u=null,p=()=>{if(u&&(clearTimeout(u),u=null),null===d.name)return;let{name:e,value:t}=d;d.name=null,d.value=null;try{localStorage.setItem(e,JSON.stringify(t))}catch{}};window.addEventListener("pagehide",p),document.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&p()});let h=(0,r.v)((0,i.Zr)((e,t,n)=>({...{viewStack:[{type:"list"}],openedSessions:[],activeWorkspaceId:null,setActiveWorkspaceId:t=>e(e=>({activeWorkspaceId:t,fullMode:!!e.fullModes?.[t??o.AD]})),livePanes:[],touchLivePane:t=>e(e=>{let n=Array.isArray(t)?t:[t];return{livePanes:[...e.livePanes.filter(e=>!n.includes(e)),...n].slice(-s.kn)}}),mountedWorkspaces:{},markWorkspaceMounted:t=>e(e=>{let n=t??o.AD;return e.mountedWorkspaces[n]?e:{mountedWorkspaces:{...e.mountedWorkspaces,[n]:!0}}}),isWorkspaceMounted:e=>{let n=e??o.AD;return!!t().mountedWorkspaces[n]},drafts:{},setDraft:(t,n)=>e(e=>({drafts:{...e.drafts,[t]:n}})),collapsedWorkspaces:{},toggleWorkspace:t=>e(e=>({collapsedWorkspaces:{...e.collapsedWorkspaces,[t]:!e.collapsedWorkspaces[t]}})),cwdBySession:{},setCwd:(t,n)=>{if(!t||!n)return;let r=(0,c.kb)(n);e(e=>e.cwdBySession[t]===r?e:{cwdBySession:{...e.cwdBySession,[t]:r}})},pushView:t=>e(e=>{let n=Array.isArray(e.viewStack)?e.viewStack:[];return{viewStack:[...a.yP.includes(t?.type)?n:n.filter((e,t)=>!(a.yP.includes(e?.type)&&t===n.length-1)),t]}}),popView:()=>e(e=>{let t=Array.isArray(e.viewStack)?e.viewStack:[];return{viewStack:t.length>1?t.slice(0,-1):[{type:"list"}]}}),setViewStack:t=>e({viewStack:t}),addOpenedSession:t=>e(e=>({openedSessions:e.openedSessions.includes(t)?e.openedSessions:[...e.openedSessions,t]})),removeOpenedSession:t=>e(e=>{let{[t]:n,...r}=e.drafts,{[t]:i,...s}=e.pendingStartup,{[t]:a,...o}=e.artifactsBySession;return{artifactsBySession:o,openedSessions:e.openedSessions.filter(e=>e!==t),livePanes:e.livePanes.filter(e=>e!==t),hiddenPaneSessionIds:e.hiddenPaneSessionIds?e.hiddenPaneSessionIds.filter(e=>e!==t):[],drafts:r,pendingStartup:s}}),replaceOpenedSession:(t,n)=>e(e=>{if(!n||t===n)return e;let r=e=>e===t?n:e;return{openedSessions:!t||e.openedSessions.includes(t)?e.openedSessions.map(r):e.openedSessions.includes(n)?e.openedSessions:[...e.openedSessions,n],livePanes:e.livePanes.map(r)}}),clearOpenedSessions:()=>e({openedSessions:[],livePanes:[]}),reorderOpenedSessions:t=>e(e=>{let n=new Set(t),r=t.filter(t=>e.openedSessions.includes(t));if(r.length<2)return{};let i=0;return{openedSessions:e.openedSessions.map(e=>n.has(e)?r[i++]:e)}}),closeSession:t=>e(e=>{let{[t]:n,...r}=e.drafts,{[t]:i,...s}=e.pendingStartup,{[t]:a,...o}=e.agentBySession,l=((e,t)=>{let n={};for(let[r,i]of Object.entries(e))n[r]={at:0,sessions:t?i.sessions.map(t):i.sessions};return n})(e.agentHistory,e=>e.openSessionId===t?{...e,openSessionId:null}:e);return{openedSessions:e.openedSessions.filter(e=>e!==t),livePanes:e.livePanes.filter(e=>e!==t),drafts:r,pendingStartup:s,agentBySession:o,agentHistory:l}}),getCurrentView:()=>{let{viewStack:e}=t();return e[e.length-1]},getSelectedSession:()=>{let{viewStack:e}=t();for(let t=e.length-1;t>=0;t--)if("terminal"===e[t].type)return e[t].sessionId;return null},reset:()=>e({viewStack:[{type:"list"}],openedSessions:[],livePanes:[],activeWorkspaceId:null})},...{sidebarCollapsed:!1,toggleSidebar:()=>e(e=>({sidebarCollapsed:!e.sidebarCollapsed})),setSidebarCollapsed:t=>e({sidebarCollapsed:!!t}),sidebarWidth:s.gH.default,setSidebarWidth:t=>e({sidebarWidth:l(t,s.gH)}),fullModes:{},fullMode:!1,toggleFullMode:t=>e(e=>{let n=t??e.activeWorkspaceId??o.AD,r=!e.fullModes[n];return{fullModes:{...e.fullModes,[n]:r},fullMode:n===(e.activeWorkspaceId??o.AD)?r:e.fullMode}}),setFullMode:(t,n)=>e(e=>{let r="boolean"==typeof t?e.activeWorkspaceId??o.AD:t??e.activeWorkspaceId??o.AD,i="boolean"==typeof t?t:!!n;return{fullModes:{...e.fullModes,[r]:i},fullMode:r===(e.activeWorkspaceId??o.AD)?i:e.fullMode}}),hiddenPaneSessionIds:[],toggleHidePane:t=>e(e=>({hiddenPaneSessionIds:e.hiddenPaneSessionIds.includes(t)?e.hiddenPaneSessionIds.filter(e=>e!==t):[...e.hiddenPaneSessionIds,t]})),unhidePane:t=>e(e=>({hiddenPaneSessionIds:e.hiddenPaneSessionIds.filter(e=>e!==t)})),paneWidths:{},setPaneWidth:(t,n)=>e(e=>({paneWidths:{...e.paneWidths,[t]:null==n?null:l(n,s.k9)}})),rightPanelOpen:window.innerWidth>=s.jK,rightPanelTabs:{},rightPanelWidth:s.Ds.default,toggleRightPanel:()=>e(e=>({rightPanelOpen:!e.rightPanelOpen,rightPanelWasOpen:null})),closeRightPanel:()=>e({rightPanelOpen:!1,rightPanelWasOpen:null}),openRightPanel:()=>e({rightPanelOpen:!0,rightPanelWasOpen:null}),setRightPanelTab:(t,n)=>e(e=>({rightPanelOpen:!0,rightPanelWasOpen:null,...null!=n?{rightPanelTabs:{...e.rightPanelTabs,[n]:t}}:{}})),rightPanelRoots:{},setRightPanelRoot:(t,n)=>e(e=>{if(null==t)return e;let r=e.rightPanelRoots[t],i=n&&n!==t?n:void 0;if(r===i)return e;let s={...e.rightPanelRoots};return i?s[t]=i:delete s[t],{rightPanelRoots:s}}),setRightPanelWidth:t=>e({rightPanelWidth:l(t,s.Ds)}),editorFilePath:null,editorPanelWidth:s.Ao.default,setEditorPanelWidth:t=>e({editorPanelWidth:l(t,s.Ao)}),editorPreviewSeq:0,artifactTitle:null,rightPanelWasOpen:null,artifactSessionId:null,openEditorFile:(t,n={})=>e(e=>({editorFilePath:t,editorPreviewSeq:n.preview?e.editorPreviewSeq+1:0,artifactTitle:n.artifactTitle||null,artifactSessionId:n.artifactSessionId||null,...n.artifactTitle?{rightPanelWasOpen:e.rightPanelWasOpen??e.rightPanelOpen,rightPanelOpen:!1}:{}})),closeEditorFile:()=>e(e=>({editorFilePath:null,editorPreviewSeq:0,artifactTitle:null,artifactSessionId:null,rightPanelWasOpen:null,...e.rightPanelWasOpen?{rightPanelOpen:!0}:{},...e.artifactSessionId&&e.editorFilePath?{artifactsBySession:((e,t,n)=>{let r=e[t];if(!r)return e;let i=r.filter(e=>e.path!==n);if(i.length===r.length)return e;let{[t]:s,...a}=e;return i.length?{...a,[t]:i}:a})(e.artifactsBySession,e.artifactSessionId,e.editorFilePath)}:{}})),hiddenHeaderButtons:["mobile"],hiddenHeaderButtonsMigrated:!1,toggleHeaderButton:t=>e(e=>({hiddenHeaderButtons:e.hiddenHeaderButtons.includes(t)?e.hiddenHeaderButtons.filter(e=>e!==t):[...e.hiddenHeaderButtons,t]})),mobileLowPower:!1,setMobileLowPower:t=>e({mobileLowPower:!!t}),mobileOpen:!1,mobileMode:"float",mobilePanelWidth:s.b5.default,mobileFloatRect:null,setMobileOpen:t=>e({mobileOpen:!!t}),setMobileMode:t=>e({mobileMode:t,mobileOpen:!0}),setMobilePanelWidth:t=>e({mobilePanelWidth:l(t,s.b5)}),setMobileFloatRect:t=>e({mobileFloatRect:t}),mobileSession:null,setMobileSession:t=>e(e=>({mobileSession:"function"==typeof t?t(e.mobileSession):t}))},...{webglEnabled:!0,setWebglEnabled:t=>e({webglEnabled:!!t}),fontSize:null,setFontSize:t=>e({fontSize:t?Math.max(10,Math.min(18,Math.round(t))):null}),terminalTheme:"default",setTerminalTheme:t=>e({terminalTheme:t||"default"}),terminalBackgrounds:["art8"],setTerminalBackgrounds:t=>e({terminalBackgrounds:Array.isArray(t)?t.filter(Boolean):[]}),terminalBackgroundOpacity:null,setTerminalBackgroundOpacity:t=>e({terminalBackgroundOpacity:null==t?s._z:Number(Math.max(s.DW.min,Math.min(s.DW.max,Math.round(t/s.DW.step)*s.DW.step)).toFixed(2))}),customBackgrounds:[],setCustomBackgrounds:t=>e({customBackgrounds:Array.isArray(t)?t.filter(e=>e?.id&&e?.dataUrl):[]}),backgroundBySession:{},setSessionBackground:(t,n)=>e(e=>{let r={...e.backgroundBySession};return n?r[t]=n:delete r[t],{backgroundBySession:r}}),showFolderButton:!0,showNoteButton:!1,setShowFolderButton:t=>e({showFolderButton:!!t}),setShowNoteButton:t=>e({showNoteButton:!!t}),noteChips:[],addNoteChip:t=>e(e=>({noteChips:[...e.noteChips,t]})),removeNoteChip:t=>e(e=>({noteChips:e.noteChips.filter(e=>e!==t)})),pinnedNotes:{},setNotePinned:(t,n)=>e(e=>{let r={...e.pinnedNotes};return n?r[t]=!0:delete r[t],{pinnedNotes:r}})},...{agentCaps:{},setAgentCaps:t=>e({agentCaps:t||{}}),artifactEnabled:!1,setArtifactEnabled:t=>e({artifactEnabled:!!t}),mcpClients:[],setMcpClients:t=>e({mcpClients:Array.isArray(t)?t:[]}),agentClisBy:{},setAgentClis:(t,n)=>e(e=>({agentClisBy:{...e.agentClisBy,[t]:{list:Array.isArray(n)?n:[],at:Date.now()}}})),agentHistory:{},setAgentHistory:(t,n)=>e(e=>({agentHistory:{...e.agentHistory,[t]:{at:Date.now(),sessions:Array.isArray(n)?n:[]}}})),invalidateAgentHistory:()=>e(e=>({agentHistory:(e=>{let t={};for(let[n,r]of Object.entries(e))t[n]={at:0,sessions:r.sessions};return t})(e.agentHistory)})),agentBySession:{},setSessionAgent:(t,n)=>e(e=>e.agentBySession[t]===n?e:{agentBySession:{...e.agentBySession,[t]:n}}),pendingStartup:{},queueStartup:(t,n)=>e(e=>({pendingStartup:{...e.pendingStartup,[t]:n}})),consumeStartup:n=>{let r=t().pendingStartup[n];return void 0===r?null:(e(e=>{let{[n]:t,...r}=e.pendingStartup;return{pendingStartup:r}}),r)},artifactsBySession:{},pushArtifact:(t,n)=>e(e=>{if(!t||!n?.path)return{};let r=(e.artifactsBySession[t]||[]).filter(e=>e.path!==n.path);return{artifactsBySession:{...e.artifactsBySession,[t]:[n,...r].slice(0,s.zv)}}}),removeArtifact:(t,n)=>e(e=>({artifactsBySession:((e,t,n)=>{let r=e[t];if(!r)return e;let i=r.filter(e=>e.path!==n);if(i.length===r.length)return e;let{[t]:s,...a}=e;return i.length?{...a,[t]:i}:a})(e.artifactsBySession,t,n)}))}}),{name:"terminal-ui-state",partialize:e=>({viewStack:e.viewStack,openedSessions:e.openedSessions,agentBySession:e.agentBySession,activeWorkspaceId:e.activeWorkspaceId,collapsedWorkspaces:e.collapsedWorkspaces,webglEnabled:e.webglEnabled,fontSize:e.fontSize,terminalTheme:e.terminalTheme,terminalBackgrounds:e.terminalBackgrounds,terminalBackgroundOpacity:e.terminalBackgroundOpacity,backgroundBySession:e.backgroundBySession,showFolderButton:e.showFolderButton,showNoteButton:e.showNoteButton,noteChips:e.noteChips,pinnedNotes:e.pinnedNotes,sidebarCollapsed:e.sidebarCollapsed,sidebarWidth:e.sidebarWidth,fullModes:e.fullModes||{},fullMode:e.fullMode,hiddenPaneSessionIds:e.hiddenPaneSessionIds||[],paneWidths:e.paneWidths,rightPanelOpen:e.rightPanelOpen,rightPanelTabs:e.rightPanelTabs,rightPanelWidth:e.rightPanelWidth,editorPanelWidth:e.editorPanelWidth,hiddenHeaderButtons:e.hiddenHeaderButtons,hiddenHeaderButtonsMigrated:e.hiddenHeaderButtonsMigrated,mobileLowPower:e.mobileLowPower,mobileMode:e.mobileMode,mobilePanelWidth:e.mobilePanelWidth,mobileFloatRect:e.mobileFloatRect,artifactsBySession:e.artifactsBySession}),storage:{getItem:e=>{try{let t=localStorage.getItem(e);if(!t)return null;let n=JSON.parse(t);return n&&!Array.isArray(n.viewStack)&&(n.viewStack=[{type:"list"}]),n}catch{return null}},setItem:(e,t)=>{d.name=e,d.value=t,u||(u=setTimeout(p,s.eu))},removeItem:e=>{d.name===e&&(d.name=null,d.value=null),localStorage.removeItem(e)}},onRehydrateStorage:()=>e=>{e&&(Array.isArray(e.viewStack)&&0!==e.viewStack.length||(e.viewStack=[{type:"list"}]),e.viewStack=e.viewStack.filter(e=>!a.yP.includes(e?.type)),0===e.viewStack.length&&(e.viewStack=[{type:"list"}]),Array.isArray(e.terminalBackgrounds)||(e.terminalBackgrounds=[]),e.terminalBackground&&"none"!==e.terminalBackground&&0===e.terminalBackgrounds.length&&(e.terminalBackgrounds=[e.terminalBackground]),e.agentBySession&&"object"==typeof e.agentBySession||(e.agentBySession={}),window.innerWidth<s.jK&&(e.rightPanelOpen=!1),!e.hiddenHeaderButtonsMigrated&&(e.hiddenHeaderButtonsMigrated=!0,Array.isArray(e.hiddenHeaderButtons)?e.hiddenHeaderButtons.includes("mobile")||(e.hiddenHeaderButtons=[...e.hiddenHeaderButtons,"mobile"]):e.hiddenHeaderButtons=["mobile"]))}}))},31408:(e,t,n)=>{"use strict";function r(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;let n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;for(let r of n)if(!(r in t)||e[r]!==t[r])return!1;return!0}function i(e,t){if(e===t)return!0;if(!Array.isArray(e)||!Array.isArray(t)||e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!r(e[n],t[n]))return!1;return!0}function s(e,t){if(e===t)return!0;if(!e||!t)return!1;let n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;for(let i of n)if(!(i in t)||!r(e[i],t[i]))return!1;return!0}n.d(t,{dI:()=>r,h3:()=>s,nk:()=>i})},31735:(e,t,n)=>{"use strict";n.d(t,{H$:()=>a,d6:()=>s});var r=n(1521),i=n(29717);let s=(e,t)=>{if(e&&t)try{localStorage.setItem("9remote_nav:"+e,t)}catch{}};function a(e){let t=(0,i.usePathname)(),n=(0,i.useSearchParams)();(0,r.useEffect)(()=>{if(!e||!t?.startsWith("/workspace"))return;let r=function(e,t){if(!e)return"";let n=t?.toString();return n?`${e}?${n}`:e}(t,n);r&&s(e,r)},[e,t,n])}},33897:(e,t,n)=>{"use strict";n.d(t,{AD:()=>r,Jc:()=>l,Mt:()=>a,g4:()=>o,gk:()=>s,xs:()=>i});let r="__ungrouped__",i=e=>e?.workspaceId??e?.groupId??null;function s({sessions:e,openedSessions:t,livePanes:n,mountedWorkspaces:a,activeWorkspaceId:o,isDesktop:l}){let c=new Set(e.filter(e=>i(e)===(o??null)).map(e=>e.id)),d=t.filter(e=>c.has(e)),u=new Set([...d,...n.filter(e=>t.includes(e))]),p=t.filter(e=>u.has(e)),h=new Map(e.map(e=>[e.id,i(e)])),m=new Set(t.filter(e=>!!c.has(e)||!!l&&!!a[h.get(e)??r])),g=new Map(d.map((e,t)=>[e,t]));return{workspaceSessionIds:c,workspaceOpenedSessions:d,renderedSessions:p,mountedSet:m,workspaceIndex:g}}let a=(e,t,n)=>!t&&n.has(e)?120*n.get(e):0;function o({container:e,pane:t}){if(!e||!t||t.offsetWidth<=0)return null;let n=t.getBoundingClientRect().left-e.getBoundingClientRect().left;return Math.max(0,Math.min(e.scrollLeft+n-(e.clientWidth-t.offsetWidth)/2,e.scrollWidth-e.clientWidth))}function l({rowWidth:e,paneCount:t,sidebarWidth:n,sidePx:r,gapPx:i,paddingPx:s,minWidth:a}){return!(e>0)||t<=0?null:Math.max(a,Math.floor((e-n-s-r-(t-1)*i)/t))}},34277:(e,t,n)=>{"use strict";n.d(t,{$Z:()=>ee,A_:()=>c,Ao:()=>h,B$:()=>H,BM:()=>es,DW:()=>q,Ds:()=>p,EE:()=>P,FC:()=>ef,Fz:()=>m,GL:()=>g,Gp:()=>et,IJ:()=>Y,Il:()=>eg,Jv:()=>o,KA:()=>_,KN:()=>I,Lo:()=>X,M8:()=>en,Mg:()=>eT,Nz:()=>ew,OM:()=>eu,Pj:()=>E,Pz:()=>Z,Qe:()=>d,RF:()=>ey,RS:()=>V,TM:()=>N,Tb:()=>v,Tk:()=>w,Uc:()=>ea,VE:()=>ec,W$:()=>$,YA:()=>em,YS:()=>C,ZU:()=>O,_C:()=>eA,_O:()=>Q,_z:()=>B,aD:()=>F,am:()=>A,ar:()=>U,b5:()=>f,b9:()=>e_,bl:()=>eb,bs:()=>R,c:()=>W,cK:()=>ev,dU:()=>ei,de:()=>ex,dt:()=>r,eE:()=>ed,eu:()=>D,fw:()=>ep,g$:()=>eS,gH:()=>u,hp:()=>x,i5:()=>eh,iW:()=>k,j4:()=>er,jK:()=>i,k9:()=>s,kn:()=>l,ll:()=>T,ok:()=>eR,pS:()=>a,pZ:()=>K,pt:()=>G,qQ:()=>S,qj:()=>y,qw:()=>eo,t:()=>j,vP:()=>M,vk:()=>z,wu:()=>L,y:()=>ek,zm:()=>el,zv:()=>b});let r=["git status","git add .",'git commit -m ""',"git push","git pull","git fetch","git diff","git log --oneline","git branch","git checkout","git checkout -b","git switch","git stash","git stash pop","git merge","git rebase","git clone","git remote -v","git restore","npm install","npm ci","npm run dev","npm run build","npm run test","npm run lint","npm outdated","pnpm install","pnpm dev","yarn dev","bun install","cd ..","cd ~","cd -","ls -la","ll","mkdir -p","cp -r","find . -name","du -sh","chmod +x","ln -s","grep -rn","grep -i","wc -l","tail -f","ps aux","df -h","free -h","lsof -i","netstat -tlnp","docker ps","docker ps -a","docker images","docker logs -f","docker exec -it","docker compose up -d","docker compose down","docker build -t","code .","claude","claude --continue","claude --resume","claude --dangerously-skip-permissions","claude mcp","codex","codex --full-auto"],i=760,s={min:400,max:1/0},a=2,o=0,l=12,c=250,d=8,u={default:190,min:180,max:1/0},p={default:190,min:190,max:1/0},h={default:420,min:280,max:1/0},m=[{id:"remote",labelKey:"menu.remoteDesktop",group:"header"},{id:"mobile",labelKey:"mobile.androidDevice",group:"header"},{id:"sites",labelKey:"menu.sites",group:"header"},{id:"notifications",labelKey:"menu.notificationsButton",group:"header"},{id:"folder",labelKey:"menu.showFolder",group:"pane",storeKey:"showFolderButton",setterKey:"setShowFolderButton"},{id:"note",labelKey:"menu.showNote",group:"pane",storeKey:"showNoteButton",setterKey:"setShowNoteButton"}],g=[{group:"header",titleKey:"menu.headerButtons"},{group:"pane",titleKey:"menu.showButtons"}],f={default:300,min:240,max:1/0},y={width:{default:300,min:240,max:900},height:{default:620,min:320},margin:12,defaultOffset:24},b=20,_=1e4,w={maxDepth:1,deepMaxDepth:3,cacheTtlMs:3e4},k={topThresholdLines:5,guardMs:600,minFetchBytes:256,chainMax:3,chainDebounceMs:300,disabled:!1},v=5242880,S=5,T=3e3,A=150,C=100,R=101,x=200,P={Escape:{data:"\x1b"},c:{ctrl:!0,data:"\x03",requireNoSelection:!0},d:{ctrl:!0,data:"\x04"},z:{ctrl:!0,data:"\x1a"},l:{ctrl:!0,data:"\f"}},D=250,I=999,N=["check again","continue","summarize"],F="terminal:noteSync",M="terminal:openSession",L=5e3,O=250,$=90,E={cursorBlink:!0,fontSize:12,fontSizeMobile:12,fontFamily:'ui-monospace, "SF Mono", "Cascadia Code", "Roboto Mono", "Noto Sans Mono", Menlo, Monaco, "Courier New", monospace',scrollback:15e3,convertEol:!0,allowProposedApi:!0,scrollOnUserInput:!0,fastScrollModifier:"none",smoothScrollDuration:0,rescaleOverlappingGlyphs:!0,minimumContrastRatio:4.5,macOptionIsMeta:!0};function U(e){return null!=e?e:window.innerWidth<768?E.fontSizeMobile:E.fontSize}let B=.8,j=.25,W="16,16,20",K="116,120,136",H=.28,q={min:.3,max:.95,step:.01},z={none:{label:"None"},art1:{label:"Anime 1",src:"/backgrounds/bg9.jpg"},art2:{label:"Anime 2",src:"/backgrounds/bg2.jpg"},art3:{label:"Anime 3",src:"/backgrounds/bg3.jpg"},art4:{label:"Anime 4",src:"/backgrounds/bg4.jpg"},art5:{label:"Anime 5",src:"/backgrounds/bg5.jpg"},art7:{label:"Anime 7",src:"/backgrounds/bg7.jpg"},art8:{label:"Anime 8",src:"/backgrounds/bg8.jpg"},art9:{label:"Anime 9",src:"/backgrounds/bg10.jpg"},art10:{label:"Anime 10",src:"/backgrounds/bg11.jpg"},art11:{label:"Anime 11",src:"/backgrounds/bg12.jpg"},art12:{label:"Anime 12",src:"/backgrounds/bg13.jpg"}};function G(e,t){return e&&t&&"none"!==t&&(z[t]||String(t).startsWith("custom"))?{...e,background:"#10101400"}:e}function J(e){return"custom"===e?"custom":"string"==typeof e&&e.startsWith("custom:")?e.slice(7):null}function V(e,t=[]){let n=J(e);return n?t.find(e=>e?.id===n)?.dataUrl||null:z[e]?.src||null}function Z(e){return z[e]?.label||(J(e)?"Custom":z.none.label)}let Q=4e3,X=2e4;function Y(e,t=[]){return Array.isArray(e)?e.filter(e=>{let n=J(e);return n?t.some(e=>e?.id===n):"none"===e||!!z[e]}):[]}function ee(e,t,n=[],r=0){var i;return Y([e],n)[0]||(i=Y(t,n),Array.isArray(i)&&0!==i.length&&i[r%i.length]||"none")}let et={gpuAcceleration:"auto",smoothScrollDuration:125},en={clipboard:!0,search:!0,image:!0},er=30,ei=2,es=100,ea=600,eo=150,el=4e3,ec=3e3,ed=8e3,eu=6e4,ep=3e4,eh="28%",em=400,eg={lineHeight:18,sensitivity:1,friction:.95,minVelocity:.3,maxVelocity:55,wheelStepLines:1,tuiThrottleMs:50,momentumRenderCadenceMs:33,tuiBackpressureTimeoutMs:120,sgrUp:(e,t)=>`\x1b[<64;${e};${t}M`,sgrDown:(e,t)=>`\x1b[<65;${e};${t}M`},ef={longPressMs:450,moveTolerance:10,wordChars:/[A-Za-z0-9._\-/~:@]/},ey={verbs:["cd","ls","ll","cat","less","more","head","tail","vim","nvim","nano","bat","code","code-insiders","rm","cp","mv","mkdir","touch","chmod","open","grep"],ttlMs:3e5,debounceMs:120,maxDirs:20,maxResults:8},eb={minDistance:60,ratio:1.5,maxDuration:500},e_=e=>!!e&&27!==e.charCodeAt(0),ew=e=>"string"==typeof e&&(/^\x1b\[[?>=][0-9;]*c$/.test(e)||/^\x1b\[[0-9]+;[0-9]+R$/.test(e)||/^\x1b\[0n$/.test(e)||/^\x1b\]\d+;/.test(e)),ek=[{id:"ctrl",label:"Ctrl",key:"Ctrl",type:"modifier"},{id:"opt",label:"Opt",key:"Alt",type:"modifier"},{id:"shift",label:"Shift",key:"Shift",type:"modifier"},{id:"meta",label:"⌘",key:"Meta",type:"modifier"},{id:"esc",label:"Esc",key:"Escape",type:"key"},{id:"tab",label:"Tab",key:"Tab",type:"key"},{id:"enter",label:"↵",key:"Enter",type:"key"},{id:"backspace",label:"⌫",key:"Backspace",type:"key"},{id:"up",label:"↑",key:"ArrowUp",type:"arrow"},{id:"down",label:"↓",key:"ArrowDown",type:"arrow"},{id:"left",label:"←",key:"ArrowLeft",type:"arrow"},{id:"right",label:"→",key:"ArrowRight",type:"arrow"},{id:"home",label:"Home",key:"Home",type:"key"},{id:"end",label:"End",key:"End",type:"key"},{id:"pgup",label:"PgUp",key:"PageUp",type:"key"},{id:"pgdn",label:"PgDn",key:"PageDown",type:"key"},{id:"del",label:"Del",key:"Delete",type:"key"},{id:"ins",label:"Ins",key:"Insert",type:"key"},{id:"ctrlA",label:"^A",key:"a",type:"ctrl"},{id:"ctrlC",label:"^C",key:"c",type:"ctrl"},{id:"ctrlD",label:"^D",key:"d",type:"ctrl"},{id:"ctrlE",label:"^E",key:"e",type:"ctrl"},{id:"ctrlK",label:"^K",key:"k",type:"ctrl"},{id:"ctrlL",label:"^L",key:"l",type:"ctrl"},{id:"ctrlN",label:"^N",key:"n",type:"ctrl"},{id:"ctrlP",label:"^P",key:"p",type:"ctrl"},{id:"ctrlR",label:"^R",key:"r",type:"ctrl"},{id:"ctrlT",label:"^T",key:"t",type:"ctrl"},{id:"ctrlU",label:"^U",key:"u",type:"ctrl"},{id:"ctrlW",label:"^W",key:"w",type:"ctrl"},{id:"ctrlX",label:"^X",key:"x",type:"ctrl"},{id:"ctrlY",label:"^Y",key:"y",type:"ctrl"},{id:"ctrlZ",label:"^Z",key:"z",type:"ctrl"},{id:"f1",label:"F1",key:"F1",type:"key"},{id:"f2",label:"F2",key:"F2",type:"key"},{id:"f3",label:"F3",key:"F3",type:"key"},{id:"f4",label:"F4",key:"F4",type:"key"},{id:"f5",label:"F5",key:"F5",type:"key"},{id:"f6",label:"F6",key:"F6",type:"key"},{id:"f7",label:"F7",key:"F7",type:"key"},{id:"f8",label:"F8",key:"F8",type:"key"},{id:"f9",label:"F9",key:"F9",type:"key"},{id:"f10",label:"F10",key:"F10",type:"key"},{id:"f11",label:"F11",key:"F11",type:"key"},{id:"f12",label:"F12",key:"F12",type:"key"},{id:"pipe",label:"|",key:"|",type:"key"},{id:"tilde",label:"~",key:"~",type:"key"},{id:"slash",label:"/",key:"/",type:"key"},{id:"backslash",label:"\\",key:"\\",type:"key"},{id:"dash",label:"-",key:"-",type:"key"},{id:"underscore",label:"_",key:"_",type:"key"}],ev=["esc","up","down","ctrlC","ctrl","opt","shift","tab","slash"],eS="enter",eT=[["left","right","home","end","pgup","pgdn","del"],["ctrlZ","ctrlR","ctrlL","ctrlA","ctrlE","ctrlW","ctrlD"],["f1","f2","f3","f4","f5","f10","f11"]],eA={base:"flex items-center justify-center rounded-brand font-semibold transition-all duration-150 ease-out active:scale-[0.94]",textNormal:"text-xs",textSmall:"text-[11px]",normal:"bg-surface-2 hover:bg-surface-3 text-text",arrow:"bg-surface-2 hover:bg-surface-3 text-text text-sm",modifierActive:"bg-brand-500 text-white shadow-sm",pinned:"bg-brand-500/15 hover:bg-brand-500/25 text-brand-400",size:{minWidth:"34px",height:"32px",paddingLeft:"6px",paddingRight:"6px"},sizeLarge:{minWidth:"38px",height:"32px",paddingLeft:"8px",paddingRight:"8px"},sizeSmall:{width:"28px",height:"28px"}},eC=["main","master"],eR=e=>eC.includes(e),ex={DELAY_MS:400,GAP_PX:6,EDGE_PX:8,MAX_WIDTH_PX:320,EST_HEIGHT_PX:48,SLACK_PX:.5}},38415:(e,t,n)=>{"use strict";n.d(t,{Gf:()=>l,Gi:()=>p,Hu:()=>o,Nn:()=>d,O8:()=>s,cu:()=>c,ij:()=>u,l7:()=>a,no:()=>h,pe:()=>r,rl:()=>i,xO:()=>m});let r="https://api.github.com",i="https://github.com/decolua/9remote",s=`${r}/repos/decolua/9remote`,a=!1,o=".devcontainer/devcontainer.json",l="NREMOTE_API_KEY",c={name:"9Remote",image:"mcr.microsoft.com/devcontainers/universal:latest",postCreateCommand:"npm install -g 9remote@latest",postAttachCommand:"nohup 9remote start > /tmp/9remote.log 2>&1 &",forwardPorts:[2208],portsAttributes:{2208:{label:"9Remote Server",onAutoForward:"silent",visibility:"public"}}},d=3e3,u=60,p={available:"Available",starting:"Starting",shutdown:"Shutdown",unknown:"Unknown"},h={user:"/user",codespaces:"/user/codespaces",codespaceByName:e=>`/user/codespaces/${e}`,startCodespace:e=>`/user/codespaces/${e}/start`,userReposList:"/user/repos?per_page=100&sort=updated&affiliation=owner,collaborator",repoContents:(e,t,n)=>`/repos/${e}/${t}/contents/${n}`,createCodespaceForRepo:(e,t)=>`/repos/${e}/${t}/codespaces`,codespaceSecretsPublicKey:"/user/codespaces/secrets/public-key",codespaceSecret:e=>`/user/codespaces/secrets/${e}`,codespaceSecretRepos:(e,t)=>`/user/codespaces/secrets/${e}/repositories/${t}`};function m(e){return`https://${e}-2208.app.github.dev`}},42174:(e,t,n)=>{"use strict";n.d(t,{A:()=>c});var r=n(73365),i=n(1521),s=n(98196),a=n(8910),o=n(78762),l=n(64683);function c({isOpen:e,onClose:t,onConfirm:n,title:d,message:u,confirmText:p,cancelText:h}){let{t:m}=(0,o.s)(),g=(0,i.useRef)(null),f=(0,i.useRef)(null),y=p??m("common.confirm"),b=h??m("common.cancel");return((0,i.useEffect)(()=>{if(!e)return;let t=requestAnimationFrame(()=>{f.current?.focus()});return()=>cancelAnimationFrame(t)},[e]),(0,i.useEffect)(()=>{if(!e)return;let r=e=>{if("Escape"===e.key)e.preventDefault(),e.stopPropagation(),t();else if("Enter"===e.key){if(g.current&&document.activeElement===g.current){e.preventDefault(),e.stopPropagation(),t();return}e.preventDefault(),e.stopPropagation(),(0,a.e)(),n?.(),t()}};return window.addEventListener("keydown",r,!0),()=>window.removeEventListener("keydown",r,!0)},[e,t,n]),!e||"u"<typeof document)?null:(0,s.createPortal)((0,r.jsxs)("div",{className:"fixed inset-0 z-[100] flex items-center justify-center px-4",style:{paddingTop:"max(1rem, env(safe-area-inset-top))",paddingBottom:"max(1rem, env(safe-area-inset-bottom))"},children:[(0,r.jsx)("div",{className:"absolute inset-0 bg-black/50 backdrop-blur-[4px] animate-in fade-in duration-150",onClick:t}),(0,r.jsxs)("div",{role:"dialog","aria-modal":"true",className:"relative card-elev max-w-md w-full my-auto max-h-[min(85%,calc(var(--app-height,85vh)-2rem))] overflow-y-auto animate-in zoom-in-95 duration-200",onClick:e=>e.stopPropagation(),onKeyDown:e=>e.stopPropagation(),children:[(0,r.jsx)("div",{className:"px-6 py-4",children:(0,r.jsx)("h3",{className:"text-lg font-semibold text-text",children:d})}),(0,r.jsx)("div",{className:"px-6 pb-4",children:(0,r.jsx)("p",{className:"text-text whitespace-pre-line",children:u})}),(0,r.jsxs)("div",{className:"px-6 py-4 flex justify-end gap-3",children:[(0,r.jsxs)("button",{ref:g,onClick:()=>{(0,a.e)(),t()},className:"px-4 py-2 bg-surface-2 hover:bg-surface-3 text-text rounded-brand transition-all duration-150 ease-out active:scale-[0.98] font-medium flex items-center gap-1.5",children:[(0,r.jsx)("span",{children:b}),(0,r.jsx)("kbd",{className:"hidden sm:inline-flex items-center text-[10px] font-mono px-1 py-0.5 rounded bg-surface-3 text-text-muted leading-none",children:"Esc"})]}),(0,r.jsxs)("button",{ref:f,onClick:()=>{(0,a.e)(),n?.(),t()},className:"px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-brand transition-all duration-150 ease-out active:scale-[0.98] font-medium flex items-center gap-1.5 focus:outline-none focus:ring-2 focus:ring-red-500/50",children:[(0,r.jsx)("span",{children:y}),(0,r.jsx)("kbd",{className:"hidden sm:inline-flex items-center justify-center w-4 h-4 rounded bg-white/20 text-white",children:(0,r.jsx)(l.Lt,{size:10,strokeWidth:2.5})})]})]})]})]}),document.body)}},45111:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});var r=n(73365);function i({size:e="md",text:t,className:n=""}){return(0,r.jsxs)("div",{className:`flex flex-col items-center justify-center gap-3 ${n}`,children:[(0,r.jsx)("div",{className:`animate-spin rounded-full border-brand-500 border-t-transparent ${{sm:"h-4 w-4 border-2",md:"h-8 w-8 border-2",lg:"h-12 w-12 border-b-2"}[e]}`}),t&&(0,r.jsx)("p",{className:"text-brand-500 text-sm font-medium",children:t})]})}},49262:(e,t,n)=>{var r={"./ar.js":[22180,2180],"./de.js":[81228,1228],"./en.js":[58628],"./es.js":[9259,9259],"./fa.js":[68638,8638],"./fr.js":[87507,7507],"./he.js":[27960,7960],"./hi.js":[20132,132],"./id.js":[41222,1222],"./it.js":[46742,6742],"./ja.js":[40674,674],"./ko.js":[50213,213],"./ms.js":[98467,8467],"./nl.js":[30925,925],"./pl.js":[91243,1243],"./pt.js":[24643,4643],"./ru.js":[82038,2038],"./sv.js":[83514,3514],"./th.js":[96419,6419],"./tr.js":[2849,2849],"./uk.js":[29299,9299],"./vi.js":[71750,1750],"./zh.js":[43429,3429]};function i(e){if(!n.o(r,e))return Promise.resolve().then(()=>{var t=Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t});var t=r[e],i=t[0];return Promise.all(t.slice(1).map(n.e)).then(()=>n(i))}i.keys=()=>Object.keys(r),i.id=49262,e.exports=i},51627:(e,t,n)=>{"use strict";function r(e,t){if(!e||!t)return!1;let n=String(e).split(".").map(Number),r=String(t).split(".").map(Number);for(let e=0;e<3;e++){let t=n[e]||0,i=r[e]||0;if(t!==i)return t>i}return!1}n.d(t,{U:()=>r})},52159:(e,t,n)=>{"use strict";n.d(t,{c:()=>i});var r=n(7938);function i(e,...t){r.eR.debug?.[e]&&console.log(...t)}},52345:(e,t,n)=>{"use strict";n.d(t,{Xn:()=>i,dI:()=>r,zl:()=>s});let r=[{code:"en",label:"English",flag:"\uD83C\uDDFA\uD83C\uDDF8",country:"us"},{code:"vi",label:"Tiếng Việt",flag:"\uD83C\uDDFB\uD83C\uDDF3",country:"vn"},{code:"zh",label:"中文",flag:"\uD83C\uDDE8\uD83C\uDDF3",country:"cn"},{code:"es",label:"Espa\xf1ol",flag:"\uD83C\uDDEA\uD83C\uDDF8",country:"es"},{code:"hi",label:"हिन्दी",flag:"\uD83C\uDDEE\uD83C\uDDF3",country:"in"},{code:"ar",label:"العربية",flag:"\uD83C\uDDF8\uD83C\uDDE6",country:"sa"},{code:"pt",label:"Portugu\xeas",flag:"\uD83C\uDDE7\uD83C\uDDF7",country:"br"},{code:"ru",label:"Русский",flag:"\uD83C\uDDF7\uD83C\uDDFA",country:"ru"},{code:"ja",label:"日本語",flag:"\uD83C\uDDEF\uD83C\uDDF5",country:"jp"},{code:"de",label:"Deutsch",flag:"\uD83C\uDDE9\uD83C\uDDEA",country:"de"},{code:"fr",label:"Fran\xe7ais",flag:"\uD83C\uDDEB\uD83C\uDDF7",country:"fr"},{code:"ko",label:"한국어",flag:"\uD83C\uDDF0\uD83C\uDDF7",country:"kr"},{code:"it",label:"Italiano",flag:"\uD83C\uDDEE\uD83C\uDDF9",country:"it"},{code:"tr",label:"T\xfcrk\xe7e",flag:"\uD83C\uDDF9\uD83C\uDDF7",country:"tr"},{code:"id",label:"Bahasa Indonesia",flag:"\uD83C\uDDEE\uD83C\uDDE9",country:"id"},{code:"th",label:"ไทย",flag:"\uD83C\uDDF9\uD83C\uDDED",country:"th"},{code:"pl",label:"Polski",flag:"\uD83C\uDDF5\uD83C\uDDF1",country:"pl"},{code:"nl",label:"Nederlands",flag:"\uD83C\uDDF3\uD83C\uDDF1",country:"nl"},{code:"uk",label:"Українська",flag:"\uD83C\uDDFA\uD83C\uDDE6",country:"ua"},{code:"fa",label:"فارسی",flag:"\uD83C\uDDEE\uD83C\uDDF7",country:"ir"},{code:"ms",label:"Bahasa Melayu",flag:"\uD83C\uDDF2\uD83C\uDDFE",country:"my"},{code:"sv",label:"Svenska",flag:"\uD83C\uDDF8\uD83C\uDDEA",country:"se"},{code:"el",label:"Ελληνικά",flag:"\uD83C\uDDEC\uD83C\uDDF7",country:"gr"},{code:"he",label:"עברית",flag:"\uD83C\uDDEE\uD83C\uDDF1",country:"il"}],i="en",s="9remote_locale"},58628:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});let r={common:{statusIdle:"Idle",statusWorking:"Working",statusBlocked:"Needs input",statusDone:"Your turn",connect:"Connect",disconnect:"Disconnect",loading:"Loading...",cancel:"Cancel",confirm:"Confirm",save:"Save",delete:"Delete",close:"Close",back:"Back",next:"Next",edit:"Edit",rename:"Rename",remove:"Remove",open:"Open",yes:"Yes",no:"No",ok:"OK",error:"Error",success:"Success",failed:"Failed",retry:"Retry",refresh:"Refresh",clipboard:"Clipboard",clipboardCopy:"Copy",clipboardEmpty:"Clipboard is empty",search:"Search",create:"Create",new:"New",add:"Add",copy:"Copy",copied:"Copied",download:"Download",upload:"Upload",enabled:"Enabled",disabled:"Disabled",on:"on",off:"off",minute:"min",hour:"h",day:"d",minutesAgo:"{n} min ago",hoursAgo:"{n} hours ago",daysAgo:"{n} days ago",done:"Done"},agentSwitcher:{title:"Your devices",active:"ACTIVE",unnamed:"Untitled",connecting:"Connecting…",unreachable:"Can't reach this device. Is it online?"},hosts:{title:"Hosts",openHost:"Open host",connecting:"Connecting…",lastSeen:"Last seen",online:"Online",offline:"Offline",sessions:"sessions",working:"working",attention:"need you",noSessions:"No sessions",addHost:"Add host",removeHost:"Remove host",removeHostMessage:'Remove "{name}" from your saved hosts? The machine itself is not affected.',disconnectMessage:'Disconnect from "{name}"? Its terminals keep running; the key stays saved.'},login:{tagline:"Access your terminal from anywhere",heroLine1:"Any machine.",heroLine2:"One terminal.",heroLine3:"In your pocket.",featureTerminal:"Terminal",featureDesktop:"Desktop",featureFiles:"Files",termConnected:"agent connected",termTunnel:"tunnel established",termReady:"ready",accessKey:"Access Key",placeholder:"sk-xxx... or One-Time Key (ABC123)",rememberKey:"Remember this key",connect:"Connect",connecting:"Connecting...",authenticating:"Authenticating with token...",invalidKeyTail:"Wrong access key — check the last characters and try again.",scanQr:"Scan QR to login",qrScanTitle:"Scan QR Code",qrHint:"Point the camera at the QR code shown on the machine running 9Remote.",qrDetected:"QR Code detected!",qrAuthenticating:"Authenticating...",qrPleaseWait:"Please wait...",qrLibFail:"Failed to load the QR scanner library.",qrInitFail:"Could not start the scanner.",qrCamDenied:"Camera permission denied. Allow camera access and try again.",qrNoCamera:"No camera found on this device.",qrCamBusy:"Camera is in use by another app.",qrCamError:"Could not open the camera.",agentOffline:"This machine isn't running 9remote. Start the agent, then try again.",legacyKeyUpdateRequired:"Agent update required",legacyKeyUpdateHint:"This device uses an older key format. Update 9remote on that machine to connect:",legacyKeyError:"This access key uses an older format. Please update 9remote to the latest version on your host machine.",updateRequired:"Update required",savedKeys:"Saved Keys",login:"Login",lastLogin:"Last login",namePlaceholder:"Name this key (optional)",rename:"Rename",deleteKeyTitle:"Delete key",deleteKeyConfirm:'Are you sure you want to delete "{name}"?',justNow:"Just now",minutesAgo:"{n}m ago",hoursAgo:"{n}h ago",daysAgo:"{n}d ago",tapToScan:"Tap to scan",orEnterManually:"or enter key manually",addKey:"Add Key",secureTitle:"Secure & Encrypted",secureDesc:"All connections are end-to-end encrypted and secure.",featAccessTitle:"Access Anywhere",featAccessDesc:"Connect from any device, anywhere.",featSecureTitle:"Secure Connection",featSecureDesc:"End-to-end encryption keeps you safe.",featFastTitle:"Fast & Reliable",featFastDesc:"Low latency and high performance.",featSessionsTitle:"Multiple Sessions",featSessionsDesc:"Manage and switch between sessions.",home:"Home",docs:"Docs"},menu:{reloadRestart:"Reload & Restart",restartHost:"Restart 9remote host",restartConfirmTitle:"Restart 9remote host?",restartConfirmMessage:"This restarts the agent process (no reinstall). Terminal sessions are preserved. It takes a few seconds.",restartStarting:"Restarting host…",restartRestarting:"Restarting 9remote…",restartDone:"Restarted! Reconnecting…",restartTimeout:"Restart is taking too long",restartTimeoutHint:"Reconnect manually if it doesn't recover.",title:"Menu",language:"Language",theme:"Theme",notifications:"Notifications",webgl:"GPU Render (Faster)",webglHint:"Turn off if text looks wrong",notificationsHint:"Notify when agent finishes",files:"File Explorer",downloading:"Downloading",copying:"Copying",conflictTitle:"File already exists",conflictMessage:"{name} already exists. Replace or skip?",skip:"Skip",skipAll:"Skip all",replace:"Replace",replaceAll:"Replace all",sites:"Local Sites",terminalSettings:"Terminal Settings",fontSize:"Font Size",terminalTheme:"Terminal Theme",terminalBackground:"Background",bgDim:"Background dim",bgApplyAll:"Apply to all",bgUrlPlaceholder:"Image URL (https://…)",bgSave:"Save",bgSaveFailed:"Could not save background",bgFromDevice:"Choose from device",bgFromUrl:"Paste image URL",bgChange:"Change image",bgAdd:"Add",bgCustomLabel:"Custom",bgDeleteFailed:"Could not delete background",bgCustomTitle:"Custom background",commandNotes:"Command Notes",showButtons:"Quick Buttons",showFolder:"Folder & Git Button",showNote:"Checklist Button",artifactHint:"The AI can preview html, docx, pdf, images and more instantly, beside your terminal.",artifactPanel:"Artifact preview",settingsJarvis:"Jarvis",jarvisToggle:"Jarvis coordinator",jarvisToggleHint:"Show the Jarvis button in the header. Its tools need the MCP switch in Plugins.",jarvisMcpOff:"The MCP switch in Plugins is off - Jarvis will start without its coordinator tools.",community:"Community",installApp:"Install App",upgrade:"Upgrade",upgradeExpires:"Expires",upgradeRestore:"Restore Purchases",codespace:"Codespace",logout:"Logout",settingsGeneral:"General",settingsAppearance:"Appearance",settingsTerminalTab:"Terminal",settingsMcp:"Plugins",mcpIntro:"Extra abilities you can give your AI coding tools.",mcpTools:"Allow",mcpRestartHint:"Turning it off applies at once. Turning it on needs the AI tool restarted.",mcpUnavailable:"Update this host to use MCP.",artifactFormats:"Formats it can show",mcpClients:"Works with",settingsWorkspace:"Workspace",settingsApplication:"Application",settingsAccount:"Account",themeLight:"Light",themeDark:"Dark",reload:"Reload App",remoteDesktop:"Remote Desktop",headerButtons:"Header buttons",settingsButtons:"Buttons",notificationsButton:"Notifications",settings:"Settings",enablePush:"Enable Push Notifications",disablePush:"Disable Push Notifications",pushHint:"Enable push notifications to get alerted when AI completes tasks",pushActiveHint:"Push notifications are on for this device. You'll be alerted when AI completes tasks.",versionMismatch:"9remote {version} is outdated",versionMismatchHint:"Some features may not work. Run:",updateNow:"Update now",updating:"Updating… reconnecting",webReloadTitle:"New web version available",webReloadHint:"Reload to get the latest interface.",reloadWeb:"Reload",updateAvailableTitle:"9Remote host update available",updateConfirmTitle:"Update 9remote?",updateConfirmMessage:"This installs the latest version and restarts the connection. It takes about a minute.",updateStarting:"Starting update…",updateInstalling:"Installing new version…",updateTimeout:"Update is taking too long",updateTimeoutHint:"Reload manually if it doesn't recover.",updateRestarting:"Updating 9remote…",updateReconnecting:"Reconnecting…",updateDone:"Updated! Reloading…",version:"Version",orientation:"Screen Orientation",orientationPortrait:"Portrait",orientationLandscape:"Landscape",orientationAuto:"Auto"},workspace:{loading:"Loading...",logoutTitle:"Logout",logoutMessage:"Are you sure you want to logout?",failedCreateSession:"Failed to create session: {error}",failedRenameSession:"Failed to rename session: {error}"},sessions:{headerTitle:"9remote.cc",connected:"Connected",disconnected:"Disconnected",codespaceStopped:"Codespace stopped",placeholder:"Terminal name (optional)",newButton:"+ New",empty:"No active sessions",emptyHint:"Create a new session to get started",created:"Created {time}",deleteTitle:"Delete Session",deleteMessage:'Are you sure you want to delete "{name}"?',editName:"Edit name",sessionActions:"Session actions",maximize:"Maximize",restoreSplit:"Restore split",split:"Split",hidePanel:"Hide panel",showPanel:"Show panel",resumeSession:"Resume session",restartAi:"Restart AI",markRead:"Mark as read",openAsUi:"Open as chat UI",openAsTerminal:"Open as terminal",modeSwitchFailed:"Could not switch this terminal",newTerminal:"New terminal",options:"Options"},agentHistory:{title:"History",empty:"No past conversations here yet",untitled:"Untitled",openNow:"Open in a terminal",minutesAgo:"{n}m",hoursAgo:"{n}h",daysAgo:"{n}d",showAll:"View all history",searchPlaceholder:"Search conversations…",allAgents:"All agents",delete:"Delete session",deleteTitle:"Delete conversation",deleteMessage:'Delete "{title}"? This permanently deletes the conversation transcript.',noResults:"No matching conversations"},workspaces:{title:"Workspaces",newWorkspace:"Add workspace",newWorkspacePrompt:"Workspace name",defaultName:"New workspace",ungrouped:"No workspace",addTerminal:"New terminal here",moveToWorkspace:"Move to workspace",rename:"Rename workspace",delete:"Remove workspace",emptyWorkspace:"No terminals here",selectFolder:"Choose folder",browse:"Browse",recentFolders:"Recent",searchFolders:"Search folders...",parentFolder:"Up one level",drives:"Drives",homeFolder:"Home",hiddenFolders:"Hidden folders",selectNamed:'Choose "{name}"',enterPath:"Type a path and press Enter",pathNotFolder:"That path is not a folder",filterOrPath:"Search, or type a path like /home/me",notADirectory:'"{name}" is not a folder in {dir}',multipleDirMatches:'"{name}" matches several folders in {dir}',invalidPath:"Invalid path",openHere:"New terminal here",tabFiles:"Files",tabGit:"Git",tabTrees:"Trees",refreshRepos:"Rescan repos",onlyChanged:"Only changed files",openFullFiles:"Open full file explorer",emptyTitle:"Nothing open yet",cardWorkspaceTitle:"Workspace",cardWorkspaceDesc:"Open a folder and run terminals in it",cardRemoteTitle:"Remote desktop",cardRemoteDesc:"Control this machine's screen",emptyWordTerminal:"Remote Terminal",emptyWordRemote:"Remote Desktop",emptyTagWorkspace:"workspace \xb7 pty",emptyTagRemote:"remote \xb7 webrtc",emptyMetaWorkspace:"open a folder \xb7 <b>sessions persist</b>",emptyMetaRemote:"control this machine \xb7 <b>low latency</b>",worktrees:"Worktrees",branches:"Branches",newWorktree:"New worktree",worktreeName:"Branch name",worktreeRepoLabel:"Repo to add the worktree in",worktreeNameAscii:"This name can't become a branch — type it in Latin letters.",addWorktree:"Add worktree",removeWorktree:"Remove worktree",removeWorktreeMessage:'Remove worktree at "{path}"?',removeWorktreeFolder:"Folder: {path}",removeWorktreeBranchDelete:"Branch: {branch} (fully merged — deleted too)",removeWorktreeBranchKeep:"Branch: {branch} (not fully merged — kept)",removeWorktreeSessions:"{count} session(s) inside: {names}",removeWorktreeBranch:'Branch "{branch}" is deleted too (when fully merged).',worktreeBranchKept:'Branch "{branch}" kept: not fully merged.',worktreeBusy:"{count} terminal(s) still run in this worktree: {names}",worktreeDirty:"This worktree has modified or untracked files — forcing the removal deletes them for good. Continue?",checkedOut:"checked out",newBranch:"New branch",checkout:"Checkout",searchBranch:"Search branches",worktreePath:"Worktree path",nestedRepos:"{count} repos",showCleanRepos:"Show {count} unchanged repo(s)",showHiddenRepos:"Unhide {count} repo(s)",hideRepo:"Hide this repo",scanDeeper:"Scan subfolders deeper",deleteTitle:"Remove workspace",deleteMessage:'Remove workspace "{name}"? Its terminals are closed. Files on disk are untouched.'},terminal:{quotaNoData:"No quota data",quotaUsageTitle:"usage",back:"Back",menu:"Menu",newTerminal:"New terminal",remoteDesktop:"Remote Desktop",defaultName:"Term",searchAgents:"Search terminal or agent",noAgentsFound:"No match",skipPermissions:"Skip permission prompts",plainShell:"Terminal",nameLabel:"Name (optional)",workspaceRoot:"Workspace root",detachedHead:"detached",browseFolders:"Browse folders…",shell:"Shell"},files:{selectWorkspace:"Select Workspace",recentWorkspaces:"Recent Workspaces",home:"Home",root:"Root",drive:"Drive {letter}",codespaces:"Codespaces",removeRecent:"Remove from recent",removeTitle:"Remove Workspace",removeMessage:'Remove "{name}" from recent workspaces?',setAsWorkspace:"Set as Workspace",openFolder:"Open Folder",newFile:"New File",newFolder:"New Folder",rename:"Rename",delete:"Delete",deleteFile:"Delete File",deleteFolder:"Delete Folder",deleteFileMessage:'Delete "{name}"?',deleteFolderMessage:'Delete folder "{name}" and all its contents?',emptyFolder:"Empty folder",git:"Git",parent:"Parent folder",workspace:"Workspace",failedLoad:"Failed to load: {error}",failedDelete:"Failed to delete: {error}",failedCreate:"Failed to create: {error}",failedRename:"Failed to rename: {error}",enterName:"Enter name",confirmRename:"Rename to:",setWorkspace:"Set Workspace",setAsWorkspaceTitle:"Set as workspace",switchWorkspace:"Switch workspace",searchFiles:"Search files",toggleHidden:"Toggle hidden files",searchPlaceholder:"Search files...",searching:"Searching...",noFilesFound:"No files found",noGitRepo:"No git repository",cannotOpenBinary:"Cannot open binary file",createNew:"Create New",file:"File",folder:"Folder",placeholderFile:"filename.js",placeholderFolder:"folder-name",pickFile:"Choose files",pickFolder:"Choose folder",copyPath:"Copy path",copyRelPath:"Copy Relative Path",copyName:"Copy Filename",delete:"Delete",rename:"Rename",deleteConfirmTitle:"Delete",deleteConfirmMessage:'Delete "{name}"?'},fileKind:{web:"Web pages",document:"Documents",sheet:"Spreadsheets",image:"Images",media:"Audio & video",diagram:"Diagrams",code:"Code & text"},editor:{save:"Save",saving:"Saving...",saved:"Saved",unsaved:"Unsaved changes",close:"Close",discard:"Discard",discardTitle:"Discard Changes",discardMessage:"You have unsaved changes. Discard them?",unsavedTitle:"Save changes to {name}?",unsavedBody:"Your changes will be lost if you don't save them.",failedLoad:"Failed to load file: {error}",failedSave:"Failed to save: {error}",openFull:"Open in full editor",artifact:"Artifact",preview:"Preview",editCode:"Edit code",reload:"Reload",previewFailed:"Preview failed",previewNoRoute:"No LAN or tunnel route to the agent",previewBack:"Back",previewForward:"Forward",previewOpenTab:"Open in a new tab",changedOnDisk:"Changed on disk",reloadFromDisk:"Reload",mermaidEmpty:"Nothing to draw",readOnly:"Read only",line:"Line",column:"Column",gitDiff:"Git Diff",typeText:"Type text and insert...",insert:"Insert",statusModified:"Modified",statusAdded:"Added",statusUntracked:"Untracked"},git:{title:"Git",branch:"Branch",changes:"Changes",staged:"Staged",unstaged:"Unstaged",untracked:"Untracked",commit:"Commit",commitAndPush:"Commit & Push",commitSuccess:"Commit successful",pushSuccess:"Push successful",stageFailed:"Failed to stage changes",commitFailed:"Commit failed",pushFailed:"Push failed",pullSuccess:"Pull successful",pullFailed:"Pull failed",stageAllConfirmTitle:"Stage All & Commit",stageAllConfirmMessage:"No changes are staged. Stage all changes and commit?",stageAndCommit:"Stage & Commit",gitActions:"Git actions",commitPlaceholder:"Commit message…",stageAllNote:"Stage all \xb7 {count}",upToDate:"Everything up-to-date",commitMessage:"Commit message",push:"Push",pull:"Pull",fetch:"Fetch",stage:"Stage",stageAll:"Stage All",unstage:"Unstage",discard:"Discard",discardChanges:"Discard Changes",discardMessage:'Discard changes to "{name}"?',noChanges:"No changes",diff:"Diff",pushing:"Pushing...",pulling:"Pulling...",committing:"Committing...",failedCommit:"Failed to commit: {error}",failedPush:"Failed to push: {error}",failedPull:"Failed to pull: {error}",status:"Status",diffTab:"Diff",modified:"Modified",added:"Added",deleted:"Deleted",untrackedTitle:"Untracked",openFile:"Open file",discardChangesTitle:"Discard changes",discardConfirmTitle:"Discard Changes",discardConfirmDelete:'Are you sure you want to delete "{name}"? This cannot be undone.',discardConfirmDiscard:'Are you sure you want to discard changes in "{name}"? This cannot be undone.',addToGitignore:"Add to .gitignore"},fileExplorer:{explorer:"Explorer",search:"Search",sourceControl:"Source Control",settings:"Settings",outline:"Outline",noFolderOpen:"No folder open",uploadingCount:"Uploading {{n}}/{{total}}…",uploadFailedCount:"{{n}} of {{total}} files failed to upload",openFolder:"Open Folder",recentWorkspaces:"Recent Workspaces",openedEditors:"Open Editors",closeEditor:"Close",closeOthers:"Close Others",closeAll:"Close All",closeAllSaved:"Close All Saved",saveAll:"Save All",newFile:"New File",newFolder:"New Folder",refreshExplorer:"Refresh Explorer",collapseAll:"Collapse All",searchInFiles:"Search in files",replaceInFiles:"Replace in files",searchPlaceholder:"Search",replacePlaceholder:"Replace",caseSensitive:"Match Case",wholeWord:"Match Whole Word",useRegex:"Use Regular Expression",filesToInclude:"files to include",filesToExclude:"files to exclude",noResults:"No results found",resultCount:"{count} results in {fileCount} files",replaceAll:"Replace All",replaceConfirmTitle:"Replace in Files",replaceConfirmMessage:"Replace {count} occurrences in {fileCount} files?",commandPalette:"Command Palette",quickOpen:"Quick Open File",typeCommand:"Type a command",typeFileName:"Type a file name",noCommandsFound:"No commands found",workspaceSwitcher:"Switch Workspace",pinWorkspace:"Pin",unpinWorkspace:"Unpin",renameWorkspace:"Rename Workspace",workspaceNamePlaceholder:"Workspace display name",pinned:"Pinned",recent:"Recent",searchWorkspaces:"Search workspaces",welcomeTitle:"Welcome",welcomeSubtitle:"Open a folder to start working",welcomeOpenFolder:"Open Folder",welcomeRecent:"Recent",toggleSidebar:"Toggle Sidebar",togglePanel:"Toggle Panel",togglePanelBottom:"Toggle Bottom Panel",toggleWordWrap:"Toggle Word Wrap",zoomIn:"Zoom In",zoomOut:"Zoom Out",resetZoom:"Reset Zoom",formatDocument:"Format Document",findInFile:"Find",replaceInFile:"Replace",goToLine:"Go to Line",goToFile:"Go to File",revealInOS:"Reveal in Finder/Explorer",openInTerminal:"Open in Terminal",copyPath:"Copy Path",copyRelativePath:"Copy Relative Path",duplicate:"Duplicate",cut:"Cut",paste:"Paste",autoSave:"Auto Save",autoSaveOff:"Off",autoSaveAfterDelay:"After Delay",autoSaveOnFocusChange:"On Focus Change",fontSize:"Font Size",wordWrap:"Word Wrap",language:"Language",encoding:"Encoding",spaces:"Spaces",branch:"Branch",noBranch:"No branch",commitMessage:"Commit Message",commitMessagePlaceholder:"Message (Cmd+Enter to commit)",stage:"Stage",stageAll:"Stage All",unstage:"Unstage",push:"Push",pull:"Pull",sync:"Sync",staged:"Staged Changes",changes:"Changes",untracked:"Untracked",bottomPanelTerminal:"Terminal",bottomPanelOutput:"Output",bottomPanelProblems:"Problems",expandAll:"Expand All",recentFiles:"Recent Files",closedTabReopen:"Reopen Closed Tab",unsavedDot:"●",loadingTree:"Loading...",fileWatcherActive:"Watching for changes"},mobile:{title:"Android Device",refreshDevices:"Refresh devices",pickDevice:"Pick a device to mirror",noDevices:"No Android device found. Start an emulator or attach a device with USB debugging on.",starting:"Starting stream…",unsupportedBrowser:"This browser cannot decode the video stream. Use Chrome, Edge, or Safari 16.4+.",back:"Back",home:"Home",recents:"Recents",power:"Lock screen",shutdownDevice:"Shut down the emulator",shutdownTitle:"Shut down emulator?",shutdownMessage:"{name} will stop, losing anything running on it. Starting it again takes around 20 seconds.",shutdownConfirm:"Shut down",androidDevice:"Android Device",deviceRunning:"Android Device — {count} running",rotate:"Rotate",stopped:"Stopped",startDevice:"Start device",stopDevice:"Stop device",switchDevice:"Switch device",lowPower:"Low power mode",lowPowerHint:"No emulator window — much less CPU, fewer frames",noDevicesWithSdk:"No device running. Start an emulator below, or attach a phone with USB debugging on.",phaseLaunching:"Starting emulator…",phaseBooting:"Booting Android…",phaseReady:"Almost ready…",backToScreen:"Back to the device screen",tabApps:"Apps",tabLogs:"Logs",dropApk:"Install an APK",dropApkHint:"Drop a file here, or tap to choose",installing:"Installing…",installedApps:"Installed apps",noApps:"No user apps installed",launch:"Launch",forceStop:"Force stop",clearData:"Clear data",uninstall:"Uninstall",deepLinkPlaceholder:"myapp://path or https://…",filterByApp:"Filter by app",allApps:"All apps",minLevel:"Level",clearLog:"Clear log",pauseLog:"Pause",resumeLog:"Resume",logPaused:"Paused — new lines are not shown",noLogs:"Waiting for log output…",hideNoise:"Hide driver noise",showNoise:"Show driver noise (hidden by default)",modeFloat:"Unpin (float over the page)",modePin:"Pin to the right",resize:"Resize",setupTitle:"Android tooling",setupInstall:"Install",setupExtracting:"Extracting…",setupInstallTo:"Installs to",setupLowDisk:"Not enough disk space at the install location",setupRequires:"Needs {deps} first",setupDepsCmdline:"command line tools",setupDepsJdk:"Java 17",setupDepsEmulator:"emulator",setupBannerHint:"Some Android tools are missing — tap to install",addDevice:"Add device",noDevicesHint:"No device yet — tap + to create one, or plug in a phone with USB debugging on.",presetReady:"Ready — nothing to download",presetDownload:"Android 16 \xb7 ~1.5 GB download","provisionStep_platform-tools":"Downloading adb…",provisionStep_jdk:"Downloading Java…","provisionStep_cmdline-tools":"Downloading SDK tools…",provisionStep_emulator:"Downloading the emulator…",provisionStep_image:"Downloading Android…",provisionStep_create:"Creating the device…",imagesTitle:"System images",imagesSearch:"Search system images…",imagesNone:"No system images match",imageInstall:"Install image",imageRemove:"Remove image",imageRemoveTitle:"Remove system image?",imageRemoveMessage:"{path} will be deleted from the host. AVDs using it will no longer start.",avdCreateTitle:"Create Virtual Device",avdStep1:"Hardware",avdStep2:"System Image",avdStep3:"Name",avdNoProfiles:"No device profiles available",avdNamePlaceholder:"AVD name",avdInstalledBelow:"Installed images are marked",avdMenu:"AVD options",avdWipe:"Wipe data",avdWipeTitle:"Wipe AVD data?",avdWipeMessage:"{name} will lose all apps, accounts and files — back to a fresh device.",avdDelete:"Delete",avdDeleteTitle:"Delete AVD?",avdDeleteMessage:"{name} and its storage on the host will be removed permanently."},remote:{title:"Remote Desktop",connecting:"Connecting...",disconnected:"Disconnected",fullscreen:"Fullscreen",exitFullscreen:"Exit Fullscreen",receivingImage:"Receiving screen…",keyboard:"Keyboard",mouse:"Mouse",fps:"FPS",debug:"Debug",help:"Help",close:"Close",sendKey:"Send Key",helpTitle:"Remote Desktop Help",notAvailable:"Remote desktop is not available",customizeKeys:"Customize keys",back:"Back",resetZoom:"Reset zoom",refresh:"Refresh",rectangleSelection:"Rectangle selection",handMode:"Hand mode",toggleKeyboard:"Toggle native keyboard",hideControls:"Hide controls",showControls:"Show controls",textBatchInput:"Text batch input",extraKeys:"Extra keys",customizeRemoteKeys:"Customize Remote Keys",exitRemote:"Exit remote desktop",debugTitle:"Debug Stats",minimize:"Minimize",transport:"Transport",latency:"Latency",tilesPerSec:"Tiles/sec",bandwidth:"Bandwidth",clearStats:"Clear Stats",lockTitle:"Windows is locked",lockGrantDesc:'Turn on "Unlock PC remotely" in 9remote host on this PC.',lockDesc:"Enter the Windows PIN or password for this computer",lockPlaceholder:"Windows PIN or password",unlock:"Unlock",unlocking:"Unlocking…",unlockFailed:"Unlock failed — check your PIN/password and try again."},remoteHelp:{modePc:"PC / Mouse",modeTrackpad:"Touch \xb7 Trackpad",modeDirect:"Touch \xb7 Direct",mouseTitle:"Mouse",keyboardTitle:"Keyboard",gesturesTrackpadTitle:"Gestures (Trackpad ✋)",gesturesDirectTitle:"Gestures (Direct)",toolbarTitle:"Toolbar",mouseClickKey:"Click / Drag",mouseClickDesc:"Left-click, drag to select/move",mouseRightKey:"Right-click",mouseRightDesc:"Context menu on remote",mouseWheelKey:"Wheel",mouseWheelDesc:"Scroll remote (Shift + Wheel = horizontal)",mouseDoubleKey:"Double-click",mouseDoubleDesc:"Double-click on remote",keyPhysicalKey:"Physical keys",keyPhysicalDesc:"Sent directly (Tab, F-keys, etc. captured)",keyModifierKey:"Ctrl / Alt / Shift / ⌘",keyModifierDesc:"Sticky modifier — combine with next key",trackpadSwipeKey:"1 finger swipe",trackpadSwipeDesc:"Move virtual cursor",trackpadTapKey:"1 finger tap",trackpadTapDesc:"Left-click at cursor",trackpad2TapKey:"2 fingers tap",trackpad2TapDesc:"Right-click at cursor",trackpad2SwipeKey:"2 fingers swipe",trackpad2SwipeDesc:"Scroll at cursor position",trackpadPinchKey:"2 fingers pinch",trackpadPinchDesc:"Zoom canvas",trackpadScrollLockKey:"Hold + drag",trackpadScrollLockDesc:"Hold to lock scroll, drag any direction",directTapKey:"1 finger tap",directTapDesc:"Click at tap position",directLongKey:"1 finger long-press",directLongDesc:"Right-click",directDoubleKey:"1 finger double-tap",directDoubleDesc:"Double-click",directScrollKey:"2 fingers swipe",directScrollDesc:"Scroll remote",directPinchKey:"2 fingers pinch",directPinchDesc:"Zoom canvas",directPanKey:"1 finger drag (zoom>1)",directPanDesc:"Pan canvas",toolbarHandDesc:"Hold left-click (drag mode) — tap again to release",toolbarMouseDirectDesc:"Switch to Direct mode",toolbarMouseTrackpadDesc:"Switch to Trackpad (virtual cursor)",toolbarKeyboardDesc:"Native keyboard / text batch input",toolbarRectDesc:"Rectangle selection mode"},remoteControls:{enterToSend:"Tab or Ctrl+Num to switch tab",typeToSend:"Type text to send...",send:"Send",trackpadMode:"Trackpad mode",directMode:"Direct mode",bottomRow:"Bottom Row",extraPanel:"Extra Panel",exitConfirmMessage:"Are you sure you want to exit the current remote desktop session?"},connection:{retrying:"Reconnecting...",waitingApproval:"Waiting for Approval",approvalDescription:"The 9Remote host needs to approve this device before you can connect.",approvalHint:"Check the terminal on your machine.",rejectedTitle:"Device Rejected",rejectedDescription:"This device was not approved by the 9Remote host.",backToLogin:"Back to Login",failed:"Connection Failed",failedDescription:"Unable to connect after {n} attempts",attemptOf:"Attempt {n} of {total}",exit:"Exit",cancel:"Cancel",retry:"Retry now"},notifications:{claudeCode:"Claude Code",codex:"Codex",geminiCli:"Gemini CLI",openCode:"OpenCode",title:"Notifications",empty:"No notifications",needsInput:"needs input",badgeTitle:"{blocked} needs input, {done} your turn",replied:"replied",agent:"Agent"},sites:{title:"Sites",localSites:"Local Sites",selectSitePreview:"Select a site to preview",browserNewTab:"New tab",browserAddressPlaceholder:"localhost:3000 or /path",browserNotConnected:"Connect to your agent first",portPlaceholder:"port",loadingSites:"Loading Sites...",notConnected:"Not connected to the agent",noSitesFound:"No sites found",startServerHint:"Start a local dev server to see it here",siteNamePlaceholder:"Site name",saveTitle:"Save",editNameTitle:"Edit name",removeTitle:"Remove",removePortTitle:"Remove Port",removePortMessage:"Remove port {port} from saved list?",popupBlocked:"Popup blocked! Please allow popups for this site.",startProxyFailed:"Failed to start proxy session for {name}",foundCount:"{n} site{suffix} found",focusOpenedTab:"Focus opened tab",openInNewTab:"Open in new tab",goBack:"Go back",goForward:"Go forward",loadingSite:"Loading...",empty:"No active sites",emptyHint:"Run a local server to see it here",open:"Open",refresh:"Refresh",newTabTitle:"Open local site",errorSwBlocked:"This browser blocked the service worker the site view needs",errorNoBridge:"Connect to your agent first",errorNoSession:"Port {port} is no longer open — reopen the site",errorTimeout:"The site did not answer in time",errorNoReply:"No reply from the agent",errorGeneric:"The site could not be loaded"},commandNotes:{title:"Command Notes",noSavedCommands:"No saved commands",addFirstBelow:"Add your first command below",clickToCopy:"Click to copy",copiedBang:"Copied!",copy:"Copy",edit:"Edit",delete:"Delete",editCommandPlaceholder:"Edit command...",addCommandPlaceholder:"Add command...",update:"Update",add:"Add",empty:"No notes yet",emptyHint:"Save commands for quick access",add:"Add Note",edit:"Edit Note",delete:"Delete Note",deleteMessage:"Delete this note?",name:"Name",command:"Command",save:"Save",placeholderName:"e.g. Start dev server",placeholderCommand:"e.g. npm run dev"},mobileKeyboard:{pasteHere:"Paste here (Cmd+V)",enterToSend:"{shortcut} to switch tab",typeCommand:"Type command and send...",send:"Send",toggleExtraKeys:"Toggle extra keys",toggleTextInput:"Toggle text input",customizeTerminalKeys:"Customize Terminal Keys",mainBar:"Main Bar",extraPanel:"Extra Panel",fileTooLarge:"File too large (max 5MB)",readFileFailed:"Failed to read file",uploadFailed:"Failed to upload file: {error}"},terminalPane:{scrollToBottom:"Scroll to bottom",refresh:"Refresh terminal",openFolder:"Open folder",openFolderHere:"Open files here",changedFiles:"Changed files",pasteOrType:"Paste or type here",paste:"Paste",note:"Checklist",addToNote:"Add to checklist"},note:{title:"Checklist",placeholder:"No tasks yet",copy:"Copy",clear:"Clear",saved:"Saved",addSuccess:"Added to checklist",copyTodo:"Copy to-do items",multilinePlaceholder:"One task per line…",addLines:"Add each line as an item",copyItem:"Copy — taps stack rows in list order",edit:"Edit",drag:"Drag to reorder",pin:"Pin above the terminal",unpin:"Unpin",expand:"Open the full checklist",allDone:"All done",clearDone:"Clear done",sendHint:"Send to terminal with checklist",addChip:"Add chip",removeChip:"Remove chip",chipPlaceholder:"Chip text…"},pwaGuide:{copyYourKey:"Copy Your Key",copyKeyHint:"Tap the key below to copy — you'll need it to login after installing",tapToCopyApiKey:"Tap to copy API key",copiedBang:"Copied!",copy:"Copy",tapShareButton:"Tap Share Button",tapShareHint:"Tap the share button at the bottom of Safari",addToHome:"Add to Home Screen",addToHomeHint:'Scroll down and tap "Add to Home Screen"',openAppPasteKey:"Open App & Paste Key",openAppPasteKeyHint:"Open the installed app and paste your key to login",openMenu:"Open Menu",openMenuHint:"Tap the menu button (three dots) in Chrome",installApp:"Install App",installAppHint:'Tap "Install app" or "Add to Home screen"',lookInstallIcon:"Look for Install Icon",lookInstallIconHint:"Look for the install icon in the address bar",clickInstallPaste:"Click Install & Paste Key",installNow:"Install Now",installNowHint:"Install 9Remote as an app for quick access",installing:"Installing...",clickInstallPasteHint:"Click install, open the app, and paste your key to login",alternativeHint:'Alternative: Open browser menu → "Install 9Remote" or "Create shortcut"',loadingPlatform:"Loading platform detection...",iosPlatform:"iOS (iPhone/iPad)",androidPlatform:"Android",macosPlatform:"macOS",windowsPlatform:"Windows",desktopPlatform:"Desktop",alreadyInstalled:"Already Installed!",alreadyInstalledHint:"You're already using 9Remote as an installed app",installationGuide:"Installation Guide",installationSteps:"Installation Steps:"},community:{title:"Community",description:"Join the 9Remote community"},pwa:{title:"Install as App",description:"Install 9Remote on your device for the best experience",iosTitle:"iOS Safari",androidTitle:"Android Chrome",desktopTitle:"Desktop"},codespace:{title:"Codespace",name:"Name",status:"Status",running:"Running",autoStart:"Auto Start 9Remote",autoStartHint:"Start 9Remote when codespace opens",stop:"Stop Codespace",stopHint:"Stop to save usage",restartHint:"To restart, go to GitHub",unknown:"Unknown"},history:{title:"Command history",empty:"No commands yet",clearAll:"Clear all",snippets:"Snippets",history:"History",pin:"Pin as snippet",unpin:"Unpin",editSnippet:"Edit snippet",aliasLabel:"Alias",aliasHint:"Type this shortcut then send to run the command",commandLabel:"Command",aliasPlaceholder:"e.g. nrd"},voice:{dictate:"Voice input",language:"Voice language",clear:"Clear",denied:"Microphone blocked — allow mic access in your browser settings"},shortcuts:{title:"Keyboard shortcuts",menuLabel:"Keyboard shortcuts",switchTerminal:"Switch terminal",switchWorkspace:"Switch workspace",terminalActions:"New / Close terminal",togglePanels:"Toggle side panels",palette:"Search files",help:"Keyboard shortcuts",sessionPrev:"Previous terminal",sessionNext:"Next terminal",workspacePrev:"Previous workspace",workspaceNext:"Next workspace",sessionIndex:"Go to terminal 1-9",closeTerminal:"Close terminal",fitPanes:"Auto-fit panes",toggleFocus:"Toggle terminal / input focus",newTerminal:"New terminal",toggleSidebar:"Toggle sidebar",toggleRightPanel:"Toggle side panel"}}},61826:(e,t,n)=>{"use strict";n.d(t,{O5:()=>c,dX:()=>d,mn:()=>l,yP:()=>s});let r="/workspace",i={list:()=>r,terminal:e=>`${r}/terminal/${encodeURIComponent(e.sessionId||"")}`,files:e=>o(`${r}/files`,{ws:e.workspace,p:e.currentPath}),editor:e=>o(`${r}/editor`,{path:e.path,line:e.line,col:e.column}),git:e=>o(`${r}/git`,{ws:e.workspace}),remote:()=>`${r}/remote`,mobile:()=>`${r}/mobile`,workspaces:()=>`${r}/workspaces`,browse:e=>o(`${r}/browse`,{path:e.path})},s=["site"],a={"":"list",terminal:"terminal",files:"files",editor:"editor",git:"git",remote:"remote",mobile:"mobile",workspaces:"workspaces",browse:"browse"};function o(e,t){let n=Object.entries(t).filter(([,e])=>null!=e&&""!==e).map(([e,t])=>`${e}=${encodeURIComponent(t)}`).join("&");return n?`${e}?${n}`:e}function l(e,t){if(!e?.startsWith(r))return null;let[n,i]=e.slice(r.length).replace(/^\//,"").split("/"),s=a[n||""];if(!s)return null;let o=e=>t?.get(e)||void 0;switch(s){case"terminal":return{type:s,sessionId:i?decodeURIComponent(i):void 0};case"files":return{type:s,workspace:o("ws"),currentPath:o("p")};case"editor":return{type:s,path:o("path"),line:u(o("line")),column:u(o("col"))};case"git":return{type:s,workspace:o("ws")};case"browse":return{type:s,path:o("path")};default:return{type:s}}}function c(e){return(i[e?.type]||i.list)(e)}function d(e,t){let n=c(t),r=e.findIndex(e=>c(e)===n);if(-1!==r)return e.slice(0,r+1);if("terminal"===t.type&&e[e.length-1]?.type==="terminal"){let n=[...e];return n[n.length-1]=t,n}return null}function u(e){let t=Number(e);return Number.isFinite(t)?t:void 0}},63977:(e,t,n)=>{"use strict";n.d(t,{freshAuth:()=>s});var r=n(90084),i=n(86251);async function s(e={},t){let n={...e,connectionMode:t},a=(0,r.lz)(e.apiKey),o=e.tempKey?(0,r.lz)(e.tempKey):null,l=o?.tail?o:a?.tail?a:a||o,c=l?.tail;if(delete n.keyTail,delete n.keyTailSealed,!c)return n;if(l?.hostSealKey){let e=await (0,i.Y)(c,l.hostSealKey);if(e)return n.keyTailSealed=e,n}return n.keyTail=c,n}},73426:(e,t,n)=>{"use strict";n.d(t,{U:()=>h,x$:()=>p,zm:()=>m});var r=n(90076),i=n(20464),s=n(31735),a=n(97711),o=n(11155),l=n(98988),c=n(90084),d=n(86129);let u=0;async function p(e,{currentKey:t}={}){let n=++u,c=l.rh.getState(),d=t||c.hosts[c.currentKey]?.full||c.currentKey;d&&((0,s.d6)(d,window.location.pathname+window.location.search),l.rh.getState().setAutoConnect((0,o.Uo)(d),!0));let h=await fetch(r.Sn.connect,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e})});if(!h.ok)throw Error("connect failed");let m=await h.json(),g=!1;for(let t=0;t<r.jP&&!g;t++)(g=await (0,i.zg)(m.tunnelUrl,e))||!(t<r.jP-1)||await new Promise(e=>setTimeout(e,r.dM));if(!g)throw Error("unreachable");n===u&&(0,a.vd)({apiKey:e,tunnelUrl:m.tunnelUrl,mode:"remote",localIp:m.localIp||null})}function h(e){try{e?sessionStorage.setItem(d.aS,"1"):sessionStorage.removeItem(d.aS)}catch{}}function m(e,{remember:t=!0,leavingHead:n=null,navigate:r=!0}={}){e?.tail&&e.tempKey&&(0,c.LG)(e.tempKey,{tail:e.tail}),h(t),n&&((0,s.d6)(n,window.location.pathname+window.location.search),l.rh.getState().setAutoConnect((0,o.Uo)(n),!0)),r&&(window.location.href="/workspace/")}},75687:(e,t,n)=>{"use strict";function r(e){let t=String(e||"").trim(),n=e=>({tempKey:e.slice(0,6).toUpperCase(),tail:e.slice(6,8).toUpperCase()}),r=/#([A-NP-Z1-9]{6}-?[a-np-z1-9]{2})$/i.exec(t);if(r)return n(r[1].replace(/-/g,""));let i=/^([A-NP-Z1-9]{6}-?[a-np-z1-9]{2})$/i.exec(t);if(i)return n(i[1].replace(/-/g,""));let s=/[?&]k=([A-NP-Z1-9]{6})(?:[^A-NP-Z1-9]|$)/i.exec(t);return s?{tempKey:s[1].toUpperCase()}:/^[A-NP-Z1-9]{6}$/i.test(t)?{tempKey:t.toUpperCase()}:null}n.d(t,{k:()=>r})},78762:(e,t,n)=>{"use strict";n.d(t,{s:()=>p});var r=n(1521),i=n(2074),s=n(52345),a=n(58628);let o=s.dI.map(e=>e.code),l=new Map,c=(e,t)=>{if(!o.includes(e)||e===s.Xn||d.getState().dicts[e]||l.has(e))return;let r=n(49262)(`./${e}.js`).then(n=>{l.delete(e);let r=n.default;return t(t=>({dicts:{...t.dicts,[e]:r}})),r}).catch(()=>{l.delete(e)});l.set(e,r)},d=(0,i.v)(e=>({locale:s.Xn,dicts:{[s.Xn]:a.default},hydrated:!1,hydrate:()=>{let t=function(){try{let e=window.localStorage.getItem(s.zl);if(e&&o.includes(e))return e}catch{}return s.Xn}();c(t,e),e({locale:t,hydrated:!0})},setLocale:t=>{if(o.includes(t)){try{window.localStorage.setItem(s.zl,t)}catch{}c(t,e),e({locale:t})}}}));function u(e,t){if(e)return t.split(".").reduce((e,t)=>null==e?e:e[t],e)}function p(){let{locale:e,dicts:t,hydrated:n,hydrate:i,setLocale:a}=d();(0,r.useEffect)(()=>{n||i()},[n,i]);let o=t[e]||t[s.Xn],l=t[s.Xn];return{t:(0,r.useMemo)(()=>(e,t)=>{var n;return n=u(o,e)??u(l,e)??e,"string"==typeof n&&t?n.replace(/\{(\w+)\}/g,(e,n)=>null!=t[n]?t[n]:`{${n}}`):n},[o,l]),locale:e,setLocale:a,hydrated:n}}},79253:(e,t,n)=>{"use strict";n.d(t,{$b:()=>_,A0:()=>z,AE:()=>f,Ax:()=>I,Dk:()=>P,GW:()=>K,Jl:()=>W,Kr:()=>q,L0:()=>Q,L8:()=>y,LN:()=>E,Qw:()=>M,RV:()=>function e(t){let n;if(!t||"object"!=typeof t)return t;if(Array.isArray(t)){let n=!1,r=t.map(t=>{let r=e(t);return r!==t&&(n=!0),r});return n?r:t}for(let s of Object.keys(t)){let a=t[s];if(i.has(s)&&"string"==typeof a&&a.includes("\\"))(n||={...t})[s]=r(a);else if(a&&"object"==typeof a){let r=e(a);r!==a&&((n||={...t})[s]=r)}}return n||t},W5:()=>X,YO:()=>k,ZH:()=>b,_C:()=>B,bd:()=>Z,cv:()=>j,d5:()=>H,fQ:()=>v,gh:()=>R,hh:()=>L,iB:()=>w,kS:()=>U,kb:()=>r,mv:()=>C,n2:()=>N,pA:()=>D,qu:()=>F,rL:()=>J,so:()=>S,u:()=>g,vd:()=>O,vs:()=>T,xW:()=>A,xl:()=>G,xr:()=>V,zT:()=>$});let r=e=>"string"==typeof e?e.replace(/\\/g,"/"):e,i=new Set(["path","currentPath","parentPath","dirPath","filePath","repoPath","oldPath","newPath","fullPath","relativePath"]),s=[".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".svg",".avif",".apng",".tif",".tiff",".heic",".heif"],a=[".mp4",".m4v",".webm",".ogv",".mov",".mkv",".avi",".3gp"],o=[".mp3",".wav",".ogg",".oga",".flac",".m4a",".aac",".opus"],l=[".pdf"],c=[".docx"],d=[".xlsx",".xls",".csv",".tsv"],u=[".html",".htm",".xhtml"],p=[".mmd",".mermaid"],h=[".md",".markdown",".mdx"];function m(e,t){if(!e)return!1;let n=e.toLowerCase();return t.some(e=>n.endsWith(e))}let g=e=>m(e,s),f=e=>m(e,a),y=e=>m(e,o),b=e=>m(e,l),_=e=>m(e,c),w=e=>m(e,d);function k(e){return e?m(e,u)?"html":m(e,h)?"markdown":m(e,p)?"mermaid":null:null}let v="9remote-preview",S={".js":"javascript",".jsx":"javascript",".ts":"javascript",".tsx":"javascript",".mjs":"javascript",".cjs":"javascript",".html":"html",".htm":"html",".xhtml":"html",".css":"css",".scss":"css",".sass":"css",".less":"css",".styl":"css",".json":"json",".json5":"json",".jsonc":"json",".md":"markdown",".markdown":"markdown",".mdx":"markdown",".py":"python",".pyw":"python",".rb":"ruby",".php":"php",".go":"go",".rs":"rust",".java":"java",".kt":"kotlin",".kts":"kotlin",".swift":"swift",".scala":"scala",".clj":"clojure",".cljs":"clojure",".ex":"elixir",".exs":"elixir",".erl":"erlang",".hs":"haskell",".ml":"ocaml",".mli":"ocaml",".jl":"julia",".pl":"perl",".pm":"perl",".tcl":"tcl",".lua":"lua",".r":"r",".dart":"dart",".groovy":"groovy",".gradle":"groovy",".c":"c",".h":"c",".cpp":"cpp",".cc":"cpp",".cxx":"cpp",".hpp":"cpp",".hh":"cpp",".cs":"csharp",".m":"objectivec",".sh":"shell",".bash":"shell",".zsh":"shell",".fish":"shell",".ps1":"powershell",".bat":"batch",".cmd":"batch",".yml":"yaml",".yaml":"yaml",".toml":"toml",".ini":"ini",".cfg":"ini",".conf":"ini",".properties":"ini",".xml":"xml",".sql":"sql",".graphql":"graphql",".gql":"graphql",".proto":"protobuf",".vue":"vue",".svelte":"svelte",".csv":"csv",".tsv":"csv",".log":"log",".diff":"diff",".patch":"diff",".dockerfile":"dockerfile",".makefile":"makefile",".mk":"makefile",".env":"env",".gitignore":"gitignore"},T={M:"text-git-modified",A:"text-git-added",D:"text-git-deleted","?":"text-git-untracked",U:"text-git-modified"},A={normal:{indentBase:12,indentStep:12,icon:16,chevron:14,text:"text-[15px] sm:text-sm",padY:"py-1 sm:py-0.5"},compact:{indentBase:8,indentStep:8,icon:14,chevron:12,text:"text-[13px] sm:text-[12px]",padY:"py-0.5 sm:py-[1px]"}},C=e=>e?"folder-changed"===e?22:32:4,R=768,x="git-diff:",P=(e,t)=>`${x}${e}:${t}`,D=e=>"string"==typeof e&&e.startsWith(x),I=e=>{let t=e.slice(x.length),n=t.indexOf(":");return{status:t.slice(0,n),absPath:t.slice(n+1)}},N=(e,t,n)=>`${x}${e}:${t}\u0000${n}`,F=e=>{let{status:t,absPath:n}=I(e),r=n.indexOf("\0");return -1===r?{status:t,repoPath:null,filePath:n}:{status:t,repoPath:n.slice(0,r),filePath:n.slice(r+1)}},M=18,L=12,O=40,$=48,E=30,U=10,B=70,j=20,W={MAX_DIRS:40,DEBOUNCE_MS:300,PREVIEW_DEBOUNCE_MS:1e3,IDLE_UNWATCH_MS:6e4},K="fileExplorer:gitRefresh",H={sidebarWidth:"fileExplorer.sidebarWidth",sidebarVisible:"fileExplorer.sidebarVisible",bottomPanelVisible:"fileExplorer.bottomPanelVisible",bottomPanelHeight:"fileExplorer.bottomPanelHeight",activityPanel:"fileExplorer.activityPanel",recentFiles:"fileExplorer.recentFiles",openTabs:"fileExplorer.openTabs",editorFontSize:"fileExplorer.editorFontSize",wordWrap:"fileExplorer.wordWrap",expandedFolders:"fileExplorer.expandedFolders",showHidden:"fileExplorer.showHidden"},q={explorer:"explorer",search:"search",scm:"scm",settings:"settings"},z=14,G=4,J=9,V=10,Z=28,Q=5,X=4194304},79453:(e,t,n)=>{"use strict";n.d(t,{g:()=>z});var r=n(86129);class i{static{this.id="base"}static{this.capabilities={control:!1,binary:!1,signaling:"none"}}static{this.priority={control:0,binary:0}}constructor(){this._listeners=new Map,this._state=r.Of.idle}get state(){return this._state}get ready(){return this._state===r.Of.open}supports(e){return!!this.constructor.capabilities[e]}getPriority(e){return this.constructor.priority[e]??0}on(e,t){this._listeners.has(e)||this._listeners.set(e,new Set),this._listeners.get(e).add(t)}off(e,t){this._listeners.get(e)?.delete(t)}_emit(e,...t){let n=this._listeners.get(e);if(n)for(let e of n)e(...t)}_setState(e){this._state!==e&&(this._state=e,this._emit("stateChange",e))}connect(e){throw Error("Not implemented: connect")}disconnect(){throw Error("Not implemented: disconnect")}send(e,t){throw Error("Not implemented: send")}}var s=n(48193),a=n(63977);let o={transports:["websocket"],reconnection:!1,reconnectionDelay:1e3,reconnectionDelayMax:5e3};class l{constructor({tunnelUrl:e,namespace:t="",socketOptions:n={}}){this._tunnelUrl=e,this._namespace=t,this._socketOptions=n}connect({onSocket:e,onFail:t}){let n=this._namespace?`${this._tunnelUrl}${this._namespace}`:this._tunnelUrl,r=this._tunnelUrl===window.location.origin?"local":"tunnel",i=(0,s.io)(n,{...o,...this._socketOptions,path:"/socket.io",auth:e=>{(0,a.freshAuth)(this._socketOptions.auth,r).then(e)}}),l=!1;i.once("connect",()=>{l||(l=!0,e(i,r))}),i.once("connect_error",()=>{l||(l=!0,t?.())})}}let c={transports:["websocket"],reconnection:!1};class d{constructor({tunnelUrl:e,localIp:t,namespace:n="",socketOptions:r={}}){this._tunnelUrl=e,this._localIp=t,this._namespace=n,this._socketOptions=r}connect({onSocket:e,onFail:t}){let n=!1,r=(t,r)=>{if(n){try{t.disconnect()}catch{}return}n=!0,e(t,r)},i=e=>this._namespace?`${e}${this._namespace}`:e,o=e=>({...c,...this._socketOptions,path:"/socket.io",auth:t=>{(0,a.freshAuth)(this._socketOptions.auth,e).then(t)}}),l=()=>{let e=this._tunnelUrl===window.location.origin?"local":"tunnel",a=(0,s.io)(i(this._tunnelUrl),o(e));a.once("connect",()=>r(a,e)),a.once("connect_error",()=>void(!n&&(n=!0,t?.())))};if(!this._localIp||"https:"===window.location.protocol)return void l();let d=(0,s.io)(i(`http://${this._localIp}`),o("local"));d.once("connect",()=>r(d,"local")),d.once("connect_error",()=>{n||(d.disconnect(),l())})}}var u=n(90076);let p=3;var h=n(52159),m=n(27520);let g=2e3,f=15,y=15,b=15,_=45;class w extends i{static{this.id="ws"}static{this.capabilities={control:!0,binary:!0,file:!0,signaling:"ws"}}static{this.priority={control:100,binary:10,file:10}}constructor(){super(),this._socket=null,this._connectionMode="local",this._retryTimer=null,this._retryAttempt=0,this._retryScheduled=!1,this._retryNowTimer=null,this._destroyed=!1,this._blocked=!1,this._updating=!1,this._connecting=!1,this._visibilityHandler=null,this._lastInboundAt=Date.now(),this._lastMsgAt=0,this._retrySeq=0}get lastInboundAt(){return this._lastInboundAt}get lastMsgAt(){return this._lastMsgAt}get socket(){return this._socket}get connectionMode(){return this._connectionMode}get blocked(){return this._blocked}setUpdating(e){this._updating=e,e&&(this._maxAttempts=_,this._retryAttempt=0,(0,h.c)("transport",`[ws] updating=true maxAttempts=${this._maxAttempts}`))}forceReconnect(){this._destroyed||this._forceReconnect()}retryNow(e="?"){if(this._blocked)return void(0,m.Lq)("switch",`ws retryNow SKIP by=${e} (blocked)`);let t=Date.now(),n=t-(this._lastRetryNowAt||0);if(n<3e3){this._retryNowTimer||(this._retryNowTimer=setTimeout(()=>{this._retryNowTimer=null,this.retryNow(`${e}-deferred`)},3e3-n)),(0,h.c)("transport","[ws] retryNow throttled → deferred"),(0,m.Lq)("switch",`ws retryNow DEFER by=${e} (${3e3-n}ms left)`);return}(0,m.Lq)("switch",`ws retryNow GO by=${e} (drops attempt ${this._retryAttempt})`),this._retrySeq++,this._lastRetryNowAt=t,clearTimeout(this._retryNowTimer),this._retryNowTimer=null,clearTimeout(this._retryTimer),clearTimeout(this._connectingTimer),this._retryTimer=null,this._retryScheduled=!1,this._retryAttempt=0,this._connecting=!1,this._destroyed=!0,this._detachSocketEvents(),this._socket?.disconnect(),this._socket=null,this._destroyed=!1,this._ctx?.onRetryStatus?.({isRetrying:!0,attempt:1,maxAttempts:this._maxAttempts,failed:!1}),this._setState(r.Of.connecting),this._connectInternal()}setBlocked(e){this._blocked=e,(0,h.c)("transport",`[ws] blocked=${e}`),e?(this._cancelRetry(),this._socket?.disconnect()):this._socket?.connected||this._destroyed||this._connectInternal()}connect(e){this._ctx=e,this._auth=e.auth,this._maxAttempts=this._auth.tempKey?f:y,this._reconnectMaxAttempts=b,this._destroyed=!1,this._attachNetworkListeners(),this._setState(r.Of.connecting),this._connectInternal()}disconnect(){this._destroyed=!0,this._retrySeq++,this._cancelRetry(),this._removeNetworkListeners(),this._detachSocketEvents(),this._socket?.disconnect(),this._socket=null,this._setState(r.Of.closed)}send(e,t){if(!this._socket?.connected)return!1;if(e===r.l_.control){let{event:e,args:n=[],cb:r}=t;return r?this._socket.emit(e,...n,r):this._socket.emit(e,...n),!0}return e===r.l_.binary?(this._socket.emit("tiles-bin-v2",t),!0):e===r.l_.file&&(this._socket.emit("file-bin",t),!0)}_connectInternal(){if(this._connecting||this._socket?.connected||this._destroyed)return;if(!this._auth.tunnelUrl&&!this._auth.localIp){(0,h.c)("transport","[ws] connect HOLD (no tunnelUrl/localIp yet) → retry"),(0,m.Lq)("switch","ws connect HOLD (no url yet) → fetch on retry"),this._setState(r.Of.degraded),this._scheduleRetry();return}this._connecting=!0,clearTimeout(this._connectingTimer),this._connectingTimer=setTimeout(()=>{this._connecting=!1},g);let e={tunnelUrl:this._auth.tunnelUrl,namespace:this._auth.namespace||"",socketOptions:this._auth.socketOptions||{}};(0,h.c)("transport",`[ws] connect: tunnelUrl=${this._auth.tunnelUrl} localIp=${this._auth.localIp||"none"}`),new l(e).connect({onSocket:(e,t)=>{if(this._connecting=!1,clearTimeout(this._connectingTimer),this._socket?.connected&&this._socket!==e){try{e.disconnect()}catch{}return}this._connectionMode=t,this._socket=e,this._retryAttempt=0,this._updating=!1,this._maxAttempts=this._reconnectMaxAttempts,this._cancelRetry(),this._attachSocketEvents(e),(0,h.c)("transport",`[ws] connect mode=${t}`),(0,m.Lq)("switch",`ws open mode=${t}`),this._setState(r.Of.open)},onFail:()=>{this._connecting=!1,clearTimeout(this._connectingTimer),(0,h.c)("transport","[ws] connect FAIL → schedule retry"),this._scheduleRetry()}})}_attachSocketEvents(e){e.on("disconnect",e=>{(0,h.c)("transport",`[ws] disconnect reason=${e}`),(0,m.Lq)("switch",`ws disconnect reason=${e}`),this._setState(r.Of.degraded),this._destroyed||this._forceReconnect()}),e.on("connect_error",e=>{(0,h.c)("transport",`[ws] connect_error ${e?.message||e}`),this._setState(r.Of.degraded),this._forceReconnect()}),e.io?.on?.("pong",()=>{this._lastInboundAt=Date.now()}),e.on("connect",()=>{this._lastInboundAt=Date.now()}),e.onAny((e,t)=>{this._lastMsgAt=Date.now(),this._emit("message",{event:e,data:t,source:"ws"})})}_attachNetworkListeners(){this._visibilityHandler||(this._visibilityHandler=()=>{"visible"!==document.visibilityState||this._socket?.connected||this._connecting||this.retryNow("visible")},this._offlineHandler=()=>{(0,m.Lq)("switch","ws offline event → drop socket, degraded"),this._socket?.disconnect(),this._socket=null,this._setState(r.Of.degraded)},this._onlineHandler=()=>{this._socket?.connected||this._connecting?(0,m.Lq)("switch",`ws online event → skip (${this._connecting?"handshaking":"already up"})`):this.retryNow("online")},this._pagehideHandler=()=>{try{this._socket?.disconnect()}catch{}},window.addEventListener("pagehide",this._pagehideHandler),document.addEventListener("visibilitychange",this._visibilityHandler),window.addEventListener("offline",this._offlineHandler),window.addEventListener("online",this._onlineHandler))}_detachSocketEvents(){if(this._socket)try{this._socket.offAny()}catch{}}_removeNetworkListeners(){this._pagehideHandler&&(window.removeEventListener("pagehide",this._pagehideHandler),this._pagehideHandler=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null),this._offlineHandler&&(window.removeEventListener("offline",this._offlineHandler),this._offlineHandler=null),this._onlineHandler&&(window.removeEventListener("online",this._onlineHandler),this._onlineHandler=null)}_forceReconnect(){if(!this._destroyed&&!this._blocked&&!this._retryScheduled&&!this._connecting){if(this._retrySeq++,this._retryAttempt++,this._retryAttempt>p){this._retryAttempt=0,this._scheduleRetry();return}this._socket?.disconnect(),this._socket=null,this._connectInternal()}}_scheduleRetry(){this._retryScheduled||this._destroyed||this._blocked||(this._retryScheduled=!0,this._retryTimer=setTimeout(()=>this._doRetry(),g))}async _doRetry(){if(this._destroyed)return;if("u">typeof document&&"hidden"===document.visibilityState){(0,m.Lq)("switch",`ws retry HOLD (hidden, still at ${this._retryAttempt}/${this._maxAttempts})`),this._retryScheduled=!1,this._scheduleRetry();return}this._retryAttempt++;let e=this._retryAttempt,t=this._retrySeq;if(e>this._maxAttempts){this._retryScheduled=!1,(0,m.Lq)("switch",`ws GAVE UP after ${this._maxAttempts} attempts → closed`),this._ctx?.onRetryStatus?.({isRetrying:!1,attempt:e,maxAttempts:this._maxAttempts,failed:!0}),this._setState(r.Of.closed);return}(0,h.c)("transport",`[ws] retry attempt=${e}/${this._maxAttempts}`),(0,m.Lq)("switch",`ws retry ${e}/${this._maxAttempts}`),this._ctx?.onRetryStatus?.({isRetrying:!0,attempt:e,maxAttempts:this._maxAttempts,failed:!1});try{let e=await fetch(u.Sn.connect,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:this._auth.apiKey})});if(!e.ok)throw Error("Failed");let{tunnelUrl:n,localIp:r}=await e.json();if(t!==this._retrySeq)return void(0,m.Lq)("switch","ws retry ABORT (superseded mid-fetch)");this._auth.tunnelUrl=n,this._auth.localIp=r||null,this._connectionMode="local",this._ctx?.onUrlUpdate?.({tunnelUrl:n,localIp:r}),this._socket?.disconnect(),this._retryScheduled=!1,this._connectInternal()}catch{if(t!==this._retrySeq)return;this._retryScheduled=!1,this._scheduleRetry()}}_cancelRetry(){clearTimeout(this._retryTimer),this._retryTimer=null,clearTimeout(this._retryNowTimer),this._retryNowTimer=null,this._retrySeq++,this._retryAttempt=0,this._retryScheduled=!1,this._ctx?.onRetryStatus?.({isRetrying:!1,attempt:0,maxAttempts:this._maxAttempts,failed:!1})}}function k(e,t){if(t instanceof Uint8Array){let e="";for(let n=0;n<t.length;n++)e+=String.fromCharCode(t[n]);return{__b:btoa(e)}}return t}function v(e,t){if(t&&"object"==typeof t&&"string"==typeof t.__b){let e=atob(t.__b),n=new Uint8Array(e.length);for(let t=0;t<e.length;t++)n[t]=e.charCodeAt(t);return n}return t}function S(e){return JSON.stringify(e,k)}function T(e,t=null){let n=[],r={event:e.event,args:function e(t,n){if(t instanceof ArrayBuffer)return n.push(new Uint8Array(t)),{__B:n.length-1};if(ArrayBuffer.isView(t))return n.push(new Uint8Array(t.buffer,t.byteOffset,t.byteLength)),{__B:n.length-1};if(Array.isArray(t))return t.map(t=>e(t,n));if(t&&"object"==typeof t){let r={};for(let i of Object.keys(t))r[i]=e(t[i],n);return r}return t}(e.args||[],n),ackId:e.ackId??null,lens:n.map(e=>e.length)};t&&(r.frag=t.id,r.part=t.part,r.parts=t.parts);let i=new TextEncoder().encode(JSON.stringify(r)),s=new Uint8Array(4+i.length+n.reduce((e,t)=>e+t.length,0));new DataView(s.buffer).setUint32(0,i.length,!0),s.set(i,4);let a=4+i.length;for(let e of n)s.set(e,a),a+=e.length;return s}function A(e){let t=e instanceof Uint8Array?e:new Uint8Array(e);if(t.length<4)throw Error("frame too short");let n=4+new DataView(t.buffer,t.byteOffset,t.byteLength).getUint32(0,!0);if(n>t.length)throw Error("frame header truncated");let r=JSON.parse(new TextDecoder().decode(t.subarray(4,n))),i=[],s=n;for(let e of r.lens||[]){if(s+e>t.length)throw Error("frame part truncated");i.push(t.subarray(s,s+e)),s+=e}return{event:r.event,args:function e(t,n){if(Array.isArray(t))return t.map(t=>e(t,n));if(t&&"object"==typeof t){if("number"==typeof t.__B)return n[t.__B]??null;let r={};for(let i of Object.keys(t))r[i]=e(t[i],n);return r}return t}(r.args||[],i),ackId:r.ackId??null,frag:r.frag,part:r.part,parts:r.parts}}function C(){let e=new Map;return{push(t){let{frag:n,part:r,parts:i}=t;if(null==n)return t;if(!Number.isInteger(r)||!Number.isInteger(i)||r<0||i<1||r>=i||i>4096)return null;let s=e.get(n);s||(e.size>=4&&e.delete(e.keys().next().value),s={slices:Array(i),got:0},e.set(n,s));let a=t.args?.[0];if(null==a||(!s.slices[r]&&(s.slices[r]=a,s.got++),s.got<i))return null;e.delete(n);let o=new Uint8Array(s.slices.reduce((e,t)=>e+t.byteLength,0)),l=0;for(let e of s.slices)o.set(e,l),l+=e.byteLength;return A(o)}}}var R=n(90084),x=n(7938);let P=null,D=0,I=new Map,N=0;async function F(e,t){let n=`9remote_turn_cache_${t?.slice(0,12)||"anon"}`;try{let e="u">typeof localStorage?localStorage.getItem(n):null;if(e){let t=JSON.parse(e);if(t?.expiresAt>Date.now()&&Array.isArray(t.iceServers)&&t.iceServers.length)return t.iceServers}}catch{}try{let r=await fetch(e,{headers:{"X-API-Key":t},signal:AbortSignal.timeout(4e3)});if(r.ok){let e=await r.json();if(e?.iceServers?.length){try{"u">typeof localStorage&&localStorage.setItem(n,JSON.stringify({iceServers:e.iceServers,expiresAt:Date.now()+828e5}))}catch{}return e.iceServers}}}catch(e){console.warn("[WebRtcProtocol] TURN fetch failed:",e.message)}return null}class M extends i{static{this.id="rtc"}static{this.capabilities={control:!0,binary:!0,file:!0,signaling:"external"}}static{this.priority={control:50,binary:100,file:100}}constructor(){super(),this._pc=null,this._dcControl=null,this._dcBinary=null,this._dcFile=null,this._typeDetail="dc-stun",this._localCandidateTypes=new Set,this._answerApplied=!1,this._pendingCandidates=[],this._iceReachedChecking=!1,this._everOpened=!1,this._isLoopback=!1,this._pendingEmit=null,this._flushTimer=null,this._latestTileTs=new Map,this._hbTimer=null,this._hbLastPing=0,this._peerEnv2=!1,this._peerFragCtl=!1,this._v2Announced=!1,this._v2RxSeen=!1,this._fragSeq=0,this._reassemble=C(),this._lastInboundAt=0,this._signalingHandlers={},this._signaling=null,this._useTurn=!1}get lastInboundAt(){return this._lastInboundAt}getPriority(e){return"dc-turn"===this._typeDetail?5:150}async connect(e){this._ctx=e,this._cleanupPeer(),this._peerEpoch=(this._peerEpoch??0)+1,this._localCandidateTypes=new Set,this._answerApplied=!1,this._pendingCandidates=[],this._iceReachedChecking=!1,this._everOpened=!1,this._isLoopback=!1,this._typeDetail="dc-stun",this._lastMid=null,this._remoteGatheringDone=!1,this._setState(r.Of.connecting),this.connectingSince=Date.now(),this.connectDeadline=this.connectingSince+r.AC,clearTimeout(this._connectTimer),this._connectTimer=setTimeout(()=>{this._state!==r.Of.open&&((0,h.c)("transport",`[rtc] connect timeout (${r.AC}ms, state=${this._state}) → close + retry`),this._closePeer(`connect-timeout (state=${this._state})`))},r.AC);let t=[{urls:["stun:stun.l.google.com:19302","stun:stun1.l.google.com:19302","stun:stun2.l.google.com:19302","stun:stun3.l.google.com:19302","stun:stun4.l.google.com:19302"]},{urls:"stun:global.stun.twilio.com:3478"},{urls:"stun:stun.cloudflare.com:3478"}];if(this._useTurn=!!(e.useTurn||e.profile?.rtc?.enableTurn),e.iceServers?.length)t=e.iceServers;else if(this._useTurn){let n=await F(u.Sn.turnCredentials,e.auth?.apiKey);n?.length&&(t=n)}let n=new RTCPeerConnection({iceServers:t,iceCandidatePoolSize:4,bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"});this._pc=n;let i=e.profile?.rtc?.dcControl?.ordered??!0,s=n.createDataChannel("control",{ordered:i}),a=n.createDataChannel("binary",{ordered:!1,maxPacketLifeTime:500}),o=n.createDataChannel("file",{ordered:!0});a.binaryType="arraybuffer",s.binaryType="arraybuffer",o.binaryType="arraybuffer",this._dcControl=s,this._dcBinary=a,this._dcFile=o;let l=async()=>{if("open"!==s.readyState||"open"!==a.readyState)return;let e="";try{let t=await n.getStats();t.forEach(n=>{if("candidate-pair"===n.type&&"succeeded"===n.state){let r=[...t.values()].find(e=>e.id===n.localCandidateId),i=[...t.values()].find(e=>e.id===n.remoteCandidateId);(r?.candidateType==="relay"||i?.candidateType==="relay")&&(this._typeDetail="dc-turn");let s=r?.address||r?.ip||"",a=i?.address||i?.ip||"";("127.0.0.1"===s||"::1"===s||"127.0.0.1"===a||"::1"===a)&&(this._isLoopback=!0),e=`local=${r?.candidateType}/${r?.protocol} remote=${i?.candidateType}/${i?.protocol}`}})}catch{}this.send(r.l_.control,{event:"rtc:linkType",args:[this._typeDetail]}),(0,h.c)("transport",`[rtc] dc OPEN type=${this._typeDetail} ${e}`),(0,m.Lq)("switch",`rtc dc OPEN (${this._typeDetail} ${e})`),clearTimeout(this._connectTimer),this._connectTimer=null,this._everOpened=!0,this._lastInboundAt=Date.now(),this._setState(r.Of.open)};s.onopen=l,a.onopen=l;let c=()=>{let e=!this._dcControl||"closed"===this._dcControl.readyState,t=!this._dcBinary||"closed"===this._dcBinary.readyState;(0,m.Lq)("switch",`rtc dc-close (ctrl=${this._dcControl?.readyState} bin=${this._dcBinary?.readyState})`),e&&t?this._setState(r.Of.closed):this._setState(r.Of.degraded)};s.onclose=c,a.onclose=c,o.onclose=()=>{this._dcFile=null},s.onerror=e=>{let t=e.error?.message??"unknown";t.includes("User-Initiated")||console.error("[rtc] dcControl ERROR:",t)},a.onerror=e=>{let t=e.error?.message??"unknown";t.includes("User-Initiated")||console.error("[rtc] dcBinary ERROR:",t)},o.onerror=e=>{let t=e.error?.message??"unknown";t.includes("User-Initiated")||console.error("[rtc] dcFile ERROR:",t)},s.onmessage=({data:e})=>{let t;this._lastInboundAt=Date.now();try{let n;if("string"==typeof e)n=JSON.parse("string"==typeof e?e:new TextDecoder().decode(e),v);else n=A(e),this._v2RxSeen||(this._v2RxSeen=!0,(0,m.Lq)("switch","env2: first v2 binary frame DECODED from agent (mutual upgrade confirmed)"));t=this._reassemble.push(n)}catch(e){console.error("[rtc] control parse error:",e.message);return}if(t){if("__ping"===t.event){this._hbTimer||this._startHeartbeatWatch(),this._hbLastPing=Date.now();try{s.send(S({event:"__pong",args:t.args||[]}))}catch{}return}this._emit("message",{event:t.event,data:t,source:"rtc"})}},a.onmessage=({data:e})=>{this._lastInboundAt=Date.now(),e instanceof ArrayBuffer&&this._receiveTile(e)},o.onmessage=({data:e})=>{this._lastInboundAt=Date.now(),e instanceof ArrayBuffer&&this._emit("binary",{channel:"file",buffer:e,source:"rtc"})},n.onicecandidate=({candidate:e})=>{var t;if(!e)return void this._sendSignaling({type:"ice",candidate:"",mid:this._lastMid||"0"});this._lastMid=e.sdpMid;let n=/typ (host|srflx|relay|prflx)/.exec(e.candidate||"");n&&this._localCandidateTypes.add(n[1]);let r=(t=e.candidate)&&t.includes("typ srflx")&&t.split(" ")[4]||null;r&&this._emit("netFingerprint",r),this._sendSignaling({type:"ice",candidate:e.candidate,mid:e.sdpMid})},n.oniceconnectionstatechange=()=>{(0,h.c)("transport",`[rtc] iceState=${n.iceConnectionState}`),(0,m.Lq)("switch",`rtc ice=${n.iceConnectionState} types=[${[...this._localCandidateTypes].join(",")}]`),"checking"===n.iceConnectionState&&(this._iceReachedChecking=!0),"disconnected"===n.iceConnectionState?this._setState(r.Of.degraded):"failed"===n.iceConnectionState?this._closePeer("ice-failed"):"connected"===n.iceConnectionState&&this._dcControl?.readyState==="open"&&this._dcBinary?.readyState==="open"&&this._setState(r.Of.open)},this._signaling=e.signaling,this._signaling?.on?.(e=>this._handleSignal(e));try{let e=await n.createOffer();await n.setLocalDescription(e),(0,h.c)("transport","[rtc] offer sent"),(0,m.Lq)("switch","rtc offer sent"),this._sendSignaling({type:"offer",sdp:e.sdp,useTurn:this._useTurn})}catch(e){console.error("[rtc] createOffer error:",e.message),this._closePeer(`create-offer:${e.message}`)}}disconnect(e="?"){this._closePeer(`manual-disconnect by=${e} state=${this._state}`),this._signaling?.off?.(),this._signaling=null}send(e,t){if(e===r.l_.control){if(this._dcControl?.readyState!=="open")return!1;let e={event:t.event,args:t.args||[],ackId:t.ackId||null};if(this._peerEnv2)return!!this._sendFramed(e)&&(this._v2Announced||(this._v2Announced=!0,(0,m.Lq)("switch","env2: client→agent control now SENT as v2 binary frames")),!0);try{return this._dcControl.send(S(e)),!0}catch(e){return!1}}if(e===r.l_.binary){if(this._dcBinary?.readyState!=="open")return!1;try{return this._dcBinary.send(t),!0}catch(e){return console.error("[rtc] send binary error:",e.message),!1}}if(e===r.l_.file){if(this._dcFile?.readyState!=="open")return!1;try{if(this._dcFile.bufferedAmount>r.HE.dcBufferThreshold)return!1;return this._dcFile.send(t),!0}catch(e){console.error("[rtc] send file error:",e.message)}}return!1}get typeDetail(){return this._typeDetail}get isLoopback(){return this._isLoopback}_closePeer(e){(0,m.Lq)("switch",`rtc→closed reason=${e}`),this._cleanupPeer(),this._setState(r.Of.closed)}setPeerCaps(e){this._peerEnv2=!!e?.env2,this._peerFragCtl=!!e?.fragCtl}get maxControlBytes(){return this._pc?.sctp?.maxMessageSize||r.dT}_sendFramed(e){var t;let n,r,i=this._peerFragCtl?this.maxControlBytes:1/0,s=(t=++this._fragSeq,(r=function(e,t){if(e.byteLength<=t)return[e];let n=t-192;if(n<=0)return null;let r=Math.ceil(e.byteLength/n);if(r>4096)return null;let i=[];for(let t=0;t<r;t++)i.push(e.subarray(t*n,Math.min((t+1)*n,e.byteLength)));return i}(n=T(e),i))?1===r.length?[n]:r.map((n,i)=>T({event:e.event,args:[n]},{id:t,part:i,parts:r.length})):null);if(!s)return!1;try{for(let e of s)this._dcControl.send(e);return!0}catch(e){return(0,h.c)("transport",`[rtc] control send refused: ${e.message}`),!1}}_startHeartbeatWatch(){this._hbTimer&&(clearInterval(this._hbTimer),this._hbTimer=null),this._hbLastPing=Date.now(),this._hbTimer=setInterval(()=>{if(this._state!==r.Of.open){clearInterval(this._hbTimer),this._hbTimer=null;return}let e=Date.now()-this._hbLastPing;e>r.An&&((0,h.c)("transport",`[rtc] heartbeat: no ping for ${e}ms → closing stalled peer`),this._closePeer(`heartbeat-stale (${e}ms)`))},r.KF)}async _addRemoteCandidate({candidate:e,mid:t}){e||(this._remoteGatheringDone=!0),await this._pc.addIceCandidate(new RTCIceCandidate(e?{candidate:e,sdpMid:t}:{candidate:"",sdpMid:t||"0"})).catch(()=>{})}_startDeadPathWatch(){clearInterval(this._deadPathTimer),this._deadPathTimer=setInterval(async()=>{if(this._state===r.Of.open||!this._pc)return this._stopDeadPathWatch();if(!this._remoteGatheringDone||"complete"!==this._pc.iceGatheringState)return;let e=0,t=0;try{(await this._pc.getStats()).forEach(n=>{"candidate-pair"===n.type&&(e++,"failed"===n.state&&t++)})}catch{return}e&&!(t<e)&&(this._stopDeadPathWatch(),this._closePeer(`dead-path (${t} pair(s) failed)`))},r.QS)}_stopDeadPathWatch(){clearInterval(this._deadPathTimer),this._deadPathTimer=null}_sendSignaling(e){this._signaling?.send?.(e)}async _handleSignal(e){if((0,h.c)("transport",`[rtc] signal: ${e.type}`),(0,m.Lq)("switch",`rtc signal recv=${e.type}`),this._pc)try{if("answer"===e.type){if(this._answerApplied||"stable"===this._pc.signalingState){(0,h.c)("transport","[rtc] duplicate answer ignored"),(0,m.Lq)("switch","rtc duplicate answer ignored");return}if(e.pub&&e.sig&&!await this._verifyHostAnswer(e)){console.error("[rtc] host key verification FAILED — relayed answer rejected"),this._closePeer("host-key-rejected");return}await this._pc.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:e.sdp})),this._answerApplied=!0,(0,h.c)("transport","[rtc] answer set"),(0,m.Lq)("switch","rtc answer applied");let t=this._pendingCandidates;for(let e of(this._pendingCandidates=[],t))await this._addRemoteCandidate(e);clearTimeout(this._connectTimer),this.connectDeadline=Date.now()+r.HJ,this._startDeadPathWatch(),this._connectTimer=setTimeout(async()=>{if(this._state!==r.Of.open){try{let e=await this._pc.getStats();e.forEach(t=>{if("candidate-pair"!==t.type)return;let n=e.get(t.localCandidateId),r=e.get(t.remoteCandidateId),i=(n?.address||n?.ip||"?").split(":")[0].slice(-12),s=r?.address||r?.ip||"?";(0,m.Lq)("switch",`pair ${t.state} ${n?.candidateType}:${i}→${r?.candidateType}:${s}`)})}catch{}this._closePeer(`ice-timeout (state=${this._state})`)}},r.HJ)}else if("ice"===e.type){if(!this._answerApplied)return void this._pendingCandidates.push(e);await this._addRemoteCandidate(e)}else"error"===e.type&&((0,h.c)("transport",`[rtc] server error: ${e.message}`),this._closePeer(`server-error:${e.message}`))}catch(e){console.error("[rtc] signal handle error:",e.message)}}async _verifyHostAnswer(e){let t=this._ctx?.auth?.apiKey;if(!t)return!0;let n=(0,R.lz)(t),r=n?.hostPubKey?n:null,i=!!n?.hostSealKey;if((0,h.c)("auth","[seal] verify answer:",{agentSentXpub:!!e.xpub,pinned:!!r,stalePin:!!(n?.hostPubKey&&!i),pendingFp2:(0,R.e1)()}),r){if(r.hostPubKey!==e.pub){let n=(0,R.e1)();return n&&await (0,R.t8)(e.pub,e.xpub)===n?((0,R.LG)(t,{hostPubKey:e.pub,hostSealKey:e.xpub,fp2:n}),(0,h.c)("transport","[rtc] host key re-pinned via fresh pairing fp2"),!0):((0,h.c)("auth","[seal] REJECT answer — pinned pub differs (host key rotated?) and no fresh fp2 to re-pin"),!1)}let n=await (0,R.D5)(e.pub,e.sdp,e.sig);if(!1===n)return(0,h.c)("auth","[seal] REJECT answer — signature invalid (relay tampering?)"),!1;if(null===n){if(!i)return(0,h.c)("auth","[seal] REJECT answer — no Ed25519 in browser and pinned fp2 predates sealing"),!1;let t=await (0,R.t8)(e.pub,e.xpub)===r.fp2;return t||(0,h.c)("auth","[seal] REJECT answer — fp2 fallback mismatch vs pinned",r.fp2),t}return!0}let s=(0,R.e1)();if(s){let n=await (0,R.t8)(e.pub,e.xpub);if(n!==s)return(0,h.c)("auth","[seal] REJECTED — fp2",n,"!= code",s,e.xpub?"":"(agent sent no sealing key — needs the source build)"),(0,R.HY)(),!1;(0,R.LG)(t,{hostPubKey:e.pub,hostSealKey:e.xpub,fp2:n}),(0,h.c)("auth","[seal] pinned via RTC — fp2",n,"sealing key stored"),(0,h.c)("transport","[rtc] host key pinned via pairing fp2")}return!0}natVerdict(){let e=this._localCandidateTypes;return this._everOpened||e.has("relay")?"ok":0===e.size||e.has("srflx")&&(!this._answerApplied||this._iceReachedChecking)?"unknown":"hard"}_cleanupPeer(){for(let e of(clearTimeout(this._connectTimer),this._connectTimer=null,this._stopDeadPathWatch(),this._hbTimer&&(clearInterval(this._hbTimer),this._hbTimer=null),[this._dcControl,this._dcBinary,this._dcFile]))if(e){e.onopen=null,e.onclose=null,e.onerror=null,e.onmessage=null;try{e.close()}catch{}}if(this._dcControl=null,this._dcBinary=null,this._dcFile=null,this._isLoopback=!1,this._typeDetail="dc-stun",this._pc){this._pc.onicecandidate=null,this._pc.oniceconnectionstatechange=null;try{this._pc.close()}catch{}this._pc=null}this._pendingEmit=null,this._flushTimer&&(clearTimeout(this._flushTimer),this._flushTimer=null),this._latestTileTs.clear(),this._reassemble=C()}_receiveTile(e){let t=++D,r=e.byteLength;new Promise(r=>{let i=setTimeout(()=>{I.has(t)&&(I.delete(t),r(null))},8e3),s=x.eR.decodeQueueCap;for(;I.size>=s;){let e=I.keys().next().value,t=I.get(e);if(!t)break;clearTimeout(t.timer),I.delete(e),t.resolve(null)}let a=function(){if(!1===P)return null;if(P)return P;try{P=new Worker(n.tu(new URL(n.p+n.u(3692),n.b)))}catch{return P=!1,null}return P.onmessage=({data:{tiles:e,timestamp:t,id:n,hasBitmap:r,error:i}})=>{N=0;let s=I.get(n);if(!s){if(e)for(let t of e)t.bitmap?.close?.();return}clearTimeout(s.timer),I.delete(n),s.resolve(i?null:{tiles:e,timestamp:t,hasBitmap:r})},P.onerror=e=>{console.error("[Worker] tileDecoder:",e.message),function(){if(P)try{P.terminate()}catch{}for(let{resolve:e}of(P=null,I.values()))try{e(null)}catch{}I.clear()}(),++N>=3&&(P=!1)},P}();if(!a){clearTimeout(i),I.delete(t),r(null);return}I.set(t,{resolve:r,timer:i}),a.postMessage({buffer:e,id:t,v:2},[e])}).then(e=>{if(!e)return;let{tiles:t,timestamp:n,hasBitmap:i}=e;for(let e of(this._pendingEmit||(this._pendingEmit={tiles:new Map,timestamp:n,hasBitmap:i,bytes:0}),this._pendingEmit.bytes+=r,t))n>=(this._latestTileTs.get(e.tileIndex)??0)?(this._latestTileTs.set(e.tileIndex,n),this._pendingEmit.tiles.get(e.tileIndex)?.bitmap?.close?.(),this._pendingEmit.tiles.set(e.tileIndex,e),n>this._pendingEmit.timestamp&&(this._pendingEmit.timestamp=n)):e.bitmap?.close?.();this._flushTimer&&clearTimeout(this._flushTimer),this._flushTimer=setTimeout(()=>{if(this._flushTimer=null,!this._pendingEmit)return;let{tiles:e,timestamp:t,hasBitmap:n,bytes:r}=this._pendingEmit;this._pendingEmit=null;let i=[...e.values()];i.length&&this._emit("message",{event:"tiles-data",data:{tiles:i,timestamp:t,hasBitmap:n,bytes:r,transport:this._typeDetail},source:"rtc"})},0)})}}let L=new Map;function O(e){if(!e?.id)throw Error("Adapter missing static id");L.set(e.id,e)}function $({urls:e,timeoutMs:t,PeerConnection:n}={}){let i=n||("u">typeof RTCPeerConnection?RTCPeerConnection:null);if(!i)return Promise.resolve(null);let s=[{urls:e||r.cx.urls}];return new Promise(e=>{let n,a,o=!1,l=t=>{if(!o){o=!0,clearTimeout(a);try{n.onicecandidate=null,n.close()}catch{}e(t)}};try{n=new i({iceServers:s,iceCandidatePoolSize:0})}catch{return e(null)}a=setTimeout(()=>l(null),t??r.cx.timeoutMs),n.onicecandidate=({candidate:e})=>{var t;if(!e)return l(null);let n=(t=e.candidate)&&t.includes("typ srflx")&&t.split(" ")[4]||null;n&&l(n)};try{n.createDataChannel("probe"),n.createOffer().then(e=>n.setLocalDescription(e)).catch(()=>l(null))}catch{l(null)}})}let E="no-public-ip";function U(e){let t=0,n=!1;for(let r of e.values())"candidate-pair"===r.type&&(r.nominated||r.selected)&&(n=!0,t+=(r.bytesReceived??0)+(r.responsesReceived??0));return n?t:null}function B(e,t){let n=e._adapters.get("rtc"),i=n?._pc;if(!i||"failed"===i.connectionState)return void e._forceRestartRtc(`${t}-pc-failed`);if(e._probeLive?.rtc===n)return void(0,m.Lq)("switch",`${t} probe shared (already measuring this peer)`);clearTimeout(e._resumeProbeTimer);let s=++e._probeToken;e._probeLive={rtc:n,token:s},(async()=>{let t=U(await i.getStats());return null==t||(await new Promise(t=>{e._resumeProbeTimer=setTimeout(t,r.UT)}),s!==e._probeToken)?null:U(await i.getStats())-t})().then(i=>{if(s!==e._probeToken)return;let a=n?.lastInboundAt&&Date.now()-n.lastInboundAt<r.An;null!=i&&i>0||a?(0,m.Lq)("switch",`${t} probe alive (Δ=${i}, recent=${!!a})`):((0,m.Lq)("switch",`${t} probe DEAD (Δ=${i}) → forceRestartRtc`),e._forceRestartRtc(`${t}-probe-dead`))}).catch(()=>{s!==e._probeToken||(n?.lastInboundAt&&Date.now()-n.lastInboundAt<r.An?(0,m.Lq)("switch",`${t} probe error ignored (rtc recently active)`):((0,m.Lq)("switch",`${t} probe error → forceRestartRtc`),e._forceRestartRtc(`${t}-probe-error`)))}).finally(()=>{e._probeLive?.token===s&&(e._probeLive=null)})}function j(e,t){if(t?.type!=="error")return!1;let n=t.message===r.bg.pending?"pending":t.message===r.bg.rejected?"rejected":null;return!!n&&((0,h.c)("transport",`[pm] device ${n} → approval UI`),e._awaitingApproval=!0,e._wsCallbacks.onApproval?.(n),!0)}function W(e){if((0,m.Lq)("switch","signaling ready"),H(e),e._awaitingApproval)return;let t=e._adapters.get("rtc");if(!t){(0,m.Lq)("switch","sig-ready → start rtc (was deferred)"),e._startSecondaryAdapters();return}t.state===r.Of.closed&&((0,m.Lq)("switch","sig-ready → restartRtc (rtc was closed)"),e._restartRtc("sig-ready"))}function K(e,t){!(e._sig?.ready&&e._sig.send(t))&&("offer"===t.type&&(e._sigBuffer=e._sigBuffer.filter(e=>"offer"!==e.type&&"ice"!==e.type)),e._sigBuffer.push(t),e._sigBuffer.length>32&&e._sigBuffer.shift())}function H(e){if(!e._sigBuffer.length)return;let t=e._sigBuffer;for(let n of(e._sigBuffer=[],t))K(e,n)}async function q(e){if(e._auth.tunnelUrl!==window.location.origin)try{(0,h.c)("transport",`[pm] refreshTunnelUrl: fetching from ${u.O}/api/connect`);let t=await fetch(`${u.O}/api/connect`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e._auth.apiKey})});if(!t.ok)return void(0,h.c)("transport",`[pm] refreshTunnelUrl: HTTP ${t.status}`);let n=await t.json();(0,h.c)("transport",`[pm] refreshTunnelUrl: got ${n.tunnelUrl} (was ${e._auth.tunnelUrl})`),n.tunnelUrl&&n.tunnelUrl!==e._auth.tunnelUrl&&(e._auth.tunnelUrl=n.tunnelUrl)}catch(e){(0,h.c)("transport",`[pm] refreshTunnelUrl: error ${e.message}`)}}O(w),O(M);class z{constructor(e,t){const{profile:n,auth:i,wsCallbacks:s,rtcCallbacks:a,peerId:o}=function(e,t){let n=t?.enableWebRTC?"remoteDesktop":"clientApp",i={...r.j3[n]};t?.enableWebRTC||(i.enabled=["ws"]),t?.enableTurn&&(i.rtc={...i.rtc,enableTurn:!0});let s={tunnelUrl:e.tunnelUrl,localIp:e.localIp,apiKey:e.apiKey,tempKey:e.tempKey,deviceId:e.deviceId,namespace:e.namespace,socketOptions:e.socketOptions},a={onConnect:e.onConnect,onDisconnect:e.onDisconnect,onRetryStatus:e.onRetryStatus,onUrlUpdate:e.onUrlUpdate,onApproval:e.onApproval},o=t?{onUpgrade:t.onUpgrade,onFallback:t.onFallback,onTransportChange:t.onTransportChange}:{},l=`${e.deviceId}:${Math.random().toString(36).slice(2,10)}`;return s.socketOptions?.auth&&(s.socketOptions.auth.peerId=l),{profile:i,auth:s,wsCallbacks:a,rtcCallbacks:o,peerId:l}}(e,t);for(const e of(this._profile=n,this._auth=i,this._wsCallbacks=s,this._rtcCallbacks=a,this._peerId=o,Object.assign(this,{_adapters:new Map,_buffer:[],_pendingAcks:new Map,_ackTimers:new Map,_ackSeq:0,_rtcRestartAttempts:0,_rtcRestartTimer:null,_rtcRestartDueAt:0,_probeAttempts:0,_rtcGivenUp:!1,_giveUpIp:null,_lastStunProbeAt:0,_rejoinDebounceTimer:null,_netFingerprint:null,_awaitingApproval:!1,_ackTimeoutMs:r.QZ.ackTimeoutMs,_hiddenAt:null,_resumeProbeTimer:null,_probeToken:0,_probeLive:null,_connected:!1,_type:"ws",_connectionMode:"tunnel",_lastWsState:null,_rawSocket:null,_onConnectFired:!1,_rtcSignalingHandler:null,_sig:null,_sigDestroyed:!1,_sigBuffer:[],_wsFallbackTimer:null}),this._bus=function(e){let t=new Map,n=(e,n)=>{t.has(e)||t.set(e,[]),t.get(e).push(n)},r=(e,n)=>{let r=t.get(e);if(!r)return;let i=r.findIndex(e=>e===n||e._original===n);-1!==i&&r.splice(i,1)};return{_listeners:t,get connected(){return e._anyAdapterReady()},get id(){return e._rawSocket?.id||null},emit(t,...n){e._sendControl(t,n)},on(e,t){n(e,t)},off(e,t){r(e,t)},once(e,t){let i=(...n)=>{r(e,i),t(...n)};i._original=t,n(e,i)},listeners:e=>[...t.get(e)||[]],dispatch(e,n=[]){let r=t.get(e);if(r?.length){for(let e of[...r])if(r.includes(e))try{e(...n)}catch{}}},clear(){t.clear()},disconnect(){e._rawSocket?.disconnect()}}}(this),this.busRef={current:this._bus},R.IU))this._bus.on(e,t=>(0,R.lu)(this,e,t));this._watchers=function(e){let t=()=>{let t;if((0,m.Lq)("switch",`visibility=${document.visibilityState}`),"visible"!==document.visibilityState)return;let n=e._adapters.get("ws"),i=e._adapters.get("rtc");(0,m.Lq)("switch",`resume check: ws=${n?.ready?"ready":n?.state} rtc=${i?.ready?"ready":i?.state}`);let s=Math.max(n?.lastInboundAt??0,n?.lastMsgAt??0),a=n?.ready&&function({ready:e=!0,lastInboundAt:t=0,now:n}={}){return!!e&&(!t||n-t>=r.Rh)}({ready:!0,lastInboundAt:s,now:Date.now()});if(n){let e=n.lastInboundAt??0,t=n.lastMsgAt??0,r=Date.now();(0,m.Lq)("switch",`zombie check: verdict=${!!a} ready=${!!n.ready} lastPong=${e?`${r-e}ms`:"never"} lastMsg=${t?`${r-t}ms`:"never"}`)}if(a){(0,h.c)("transport","[pm] ws zombie on resume → force reconnect");try{n.forceReconnect?.()}catch{}}if(e._awaitingApproval)return;if(e._rtcGivenUp)return void e._maybeRearmRtc();if(t=e._rtcRestartTimer?Math.max(e._rtcRestartDueAt-Date.now(),0):-1,(0,m.Lq)("switch",`RESET attempts (was ${e._rtcRestartAttempts}) reason=resume pendingIn=${t}ms`),e._rtcRestartAttempts=0,e._probeAttempts=0,t<=r.QZ.backoffMs[0]||((0,m.Lq)("switch",`resume: pending rung was ${t}ms out → re-arm fast`),e._disarmRestart(),e._scheduleRtcRestart("resume-rearm")),!e._canSignal())return void e._sig?.retryNow("resume-no-carrier");let o=i?.state;i&&o!==r.Of.closed&&o!==r.Of.degraded?function(e){let t=e._adapters.get("rtc");if(!t?.ready)return e._restartRtc("resume-not-ready");let n=e._hiddenAt?Date.now()-e._hiddenAt:0;if("function"==typeof matchMedia&&matchMedia("(pointer: coarse)").matches&&n>r.Tr){(0,m.Lq)("switch",`resume: hidden ${Math.round(n/1e3)}s on touch → skip probe, force restart`),(0,h.c)("transport",`[pm] resume: hidden ${Math.round(n/1e3)}s → immediate restart`),e._forceRestartRtc("resume-hidden-touch");return}B(e,"resume")}(e):((0,m.Lq)("switch",`visibility → restartRtc (rtc=${o||"absent"})`),e._restartRtc("resume-dead-rtc"))},n=()=>{if("hidden"===document.visibilityState){e._hiddenAt=Date.now();return}clearTimeout(e._resumeCoalesceTimer),e._resumeCoalesceTimer=setTimeout(t,150)};document.addEventListener("visibilitychange",n);let i=()=>{"visible"===document.visibilityState&&n()},s=()=>{e._hiddenAt=Date.now()};document.addEventListener("resume",i),document.addEventListener("freeze",s);let a=()=>{clearTimeout(e._netDebounceTimer),e._netDebounceTimer=setTimeout(()=>{!1===navigator.onLine?(0,m.Lq)("switch","net-change: still offline → wait"):((0,h.c)("transport","[pm] network change → probe rtc"),(0,m.Lq)("switch",`net-change: online=${navigator.onLine} → kick sig + ws + rtc`),e._sig?.retryNow("net-change"),e.retryNow("net-change"),(0,m.Lq)("switch",`RESET attempts (was ${e._rtcRestartAttempts}) givenUp=${e._rtcGivenUp} reason=net-change`),e._rtcRestartAttempts=0,e._probeAttempts=0,e._rtcGivenUp=!1,e._giveUpIp=null,e._shouldRenegotiate()&&e._restartRtc("net-change"))},r.o_.debounceMs)};return window.addEventListener("online",a),navigator.connection?.addEventListener?.("change",a),{visibilityHandler:n,detach(){document.removeEventListener("visibilitychange",n),document.removeEventListener("resume",i),document.removeEventListener("freeze",s),window.removeEventListener("online",a),navigator.connection?.removeEventListener?.("change",a),clearTimeout(e._netDebounceTimer),e._netDebounceTimer=null,clearTimeout(e._resumeCoalesceTimer),e._resumeCoalesceTimer=null}}}(this)}get type(){return this._type}get connected(){return this._connected}get connectionMode(){return this._connectionMode}get wsBlocked(){return this._adapters.get("ws")?.blocked||!1}setWsBlocked(e){this._adapters.get("ws")?.setBlocked(e)}setUpdating(e){this._adapters.get("ws")?.setUpdating(e)}retryNow(e="user"){let t=this._adapters.get("ws");t?t.retryNow?.(e):((0,m.Lq)("switch",`retryNow by=${e}: no ws adapter → full connect()`),this.connect())}emit(e,...t){this._sendControl(e,t)}sendBinary(e,t){let n=this._pickAdapter(e);return!!n&&n.send(e,t)}connect(){this._sigDestroyed=!1;let e=this._profile.enabled.includes("rtc");e&&this._initSignalingClient(),e&&(this._canSignal()?this._startSecondaryAdapters():((0,m.Lq)("switch","rtc deferred — waiting for signaling relay"),clearTimeout(this._rtcDeferTimer),this._rtcDeferTimer=setTimeout(()=>{this._sigDestroyed||this._adapters.has("rtc")||((0,m.Lq)("switch","rtc defer expired → start anyway"),this._startSecondaryAdapters())},r.BF))),this._startWsFallback(),(0,h.c)("transport","[pm] connect: RTC + WS parallel (RTC preferred, WS warm standby)."),(0,m.Lq)("switch","connect: RTC + WS parallel")}async _startWsFallback(){if(!(this._adapters.has("ws")||this._sigDestroyed||this._adapters.get("rtc")?.isLoopback)){if((0,m.Lq)("switch","ws-fallback: start (refresh url)"),await this._refreshTunnelUrl(),this._adapters.has("ws")||this._sigDestroyed||this._adapters.get("rtc")?.isLoopback)return void(0,m.Lq)("switch","ws-fallback: aborted (destroyed, loopback or already attached)");(0,m.Lq)("switch","ws-fallback: connecting"),this._instantiate("ws"),this._adapters.get("ws")?.connect(this._buildCtx("ws"))}}async _refreshTunnelUrl(){return q(this)}_initSignalingClient(){!function(e){if(!r.gI.enabled||e._sig||e._sigDestroyed||!e._auth.deviceId||!e._auth.apiKey)return;let t=u.O.replace(/^http/,"ws")+"/signaling";n.e(6739).then(n.bind(n,46739)).then(({SignalingClient:n})=>{e._sig||e._sigDestroyed||(e._sig=new n({url:t,role:"client",roomId:e._auth.apiKey,apiKey:e._auth.apiKey,from:e._peerId,onReady:()=>W(e),pingMs:r.gI.pingMs}),e._sig.on(t=>{if("error"===t.type&&"rtc-disabled"===t.message){e._rtcTestDisabled=!0,(0,m.Lq)("switch","rtc-disabled by agent → stop RTC retry (use WS)");return}j(e,t)||e._rtcSignalingHandler?.(t)}),e._sig.connect())}).catch(e=>(0,h.c)("transport",`[pm] SignalingClient load failed: ${e?.message||e}`))}(this)}_instantiate(e){if(this._adapters.has(e))return;let t=L.get(e);if(!t)return;let n=new t;n.on("stateChange",t=>this._onAdapterStateChange(e,t)),n.on("message",({event:e,data:t,source:n})=>this._dispatch(e,t,n)),n.on("binary",e=>this._onBinary(e)),"rtc"===e&&(n.on("netFingerprint",e=>this._onNetFingerprint(e)),this._srvCaps&&n.setPeerCaps?.(this._srvCaps)),this._adapters.set(e,n)}_onNetFingerprint(e){if(!e||e===this._netFingerprint)return;let t=this._netFingerprint;this._netFingerprint=e,t&&(0,h.c)("transport",`[pm] net fingerprint ${t}→${e} (same network — no backoff reset)`)}_maybeRearmRtc(){if(!this._rtcGivenUp)return;let e=Date.now();e-this._lastStunProbeAt<r.cx.minIntervalMs||(this._lastStunProbeAt=e,$().then(e=>{var t;if(this._sigDestroyed||!this._rtcGivenUp)return;let n=e||(this._giveUpIp===E?E:null);(t=this._giveUpIp,n&&(!t||n!==t))?((0,m.Lq)("switch",`rearm check: ip ${this._giveUpIp||"unknown"}→${n} changed → re-arm RTC`),(0,h.c)("transport","[pm] public ip changed → re-arm rtc"),this._rtcGivenUp=!1,this._giveUpIp=null,this._probeAttempts=0,this._rtcRestartAttempts=0,this._netFingerprint=e,this._canSignal())?this._shouldRenegotiate()&&this._restartRtc("stun-rearm"):this._sig?.retryNow("stun-rearm"):(0,m.Lq)("switch",`rearm check: ip=${n||"unknown"} same as give-up → stay WS-only`)}).catch(()=>{}))}_startSecondaryAdapters(){for(let e of((0,h.c)("transport",`[pm] startSecondary enabled=${this._profile.enabled}`),(0,h.c)("transport",`[pm] startSecondary rtcTestDisabled=${!!this._rtcTestDisabled}`),this._profile.enabled))"ws"!==e&&("rtc"!==e||!this._rtcTestDisabled)&&(this._adapters.has(e)||((0,h.c)("transport",`[pm] start adapter ${e}`),this._instantiate(e),this._adapters.get(e)?.connect(this._buildCtx(e))))}_handleApprovalSignal(e){return j(this,e)}_onSignalingReady(){W(this)}_canSignal(){return!!this._sig?.ready}_shouldRenegotiate(){return!this._awaitingApproval&&this._canSignal()}_restartRtc(e="?"){(0,m.Lq)("switch",`restartRtc CALLED by=${e} attempts=${this._rtcRestartAttempts}`);let t=this._adapters.get("rtc"),n=function({testDisabled:e,givenUp:t,rtcState:n,hasRtc:i}){return e?"skip-test-disabled":t?"skip-given-up":i&&(n===r.Of.connecting||n===r.Of.open)?"skip-in-flight":i?"restart":"start-fresh"}({testDisabled:!!this._rtcTestDisabled,givenUp:this._rtcGivenUp,rtcState:t?.state,hasRtc:!!t});if("skip-test-disabled"===n)return void(0,m.Lq)("switch","restartRtc skipped (rtcTestDisabled)");if("skip-given-up"===n)return void(0,m.Lq)("switch","restartRtc skipped (hard NAT → WS-only)");if("skip-in-flight"===n)return void(0,m.Lq)("switch",`restartRtc skipped (rtc=${t.state})`);if("start-fresh"===n){(0,m.Lq)("switch","restartRtc: no rtc → startSecondary"),this._startSecondaryAdapters();return}(0,m.Lq)("switch","restartRtc: tear down + renegotiate"),(0,h.c)("transport","[pm] ws reconnected → restart rtc");try{t.disconnect(`restart:${e}`)}catch{}this._adapters.delete("rtc"),this._rtcSignalingHandler=null,this._startSecondaryAdapters()}_forceRestartRtc(e="?"){(0,m.Lq)("switch",`forceRestartRtc CALLED by=${e}`);let t=this._adapters.get("rtc");if(t){try{t.disconnect(`force:${e}`)}catch{}this._adapters.delete("rtc"),this._rtcSignalingHandler=null}this._rtcGivenUp?(0,m.Lq)("switch","forceRestartRtc: torn down, no renegotiate (hard NAT)"):this._startSecondaryAdapters()}disconnect(){this._watchers?.detach(),this._watchers=null,clearTimeout(this._resumeProbeTimer),this._resumeProbeTimer=null,clearTimeout(this._rtcDeferTimer),this._rtcDeferTimer=null,this._probeToken++;try{this._sig?.disconnect()}catch{}for(let e of(this._sig=null,this._sigDestroyed=!0,this._sigBuffer=[],clearTimeout(this._wsFallbackTimer),clearTimeout(this._rejoinDebounceTimer),this._rejoinDebounceTimer=null,this._adapters.values()))try{e.disconnect("pm-disconnect")}catch{}for(let e of(this._adapters.clear(),this._bus.clear(),this._buffer=[],this._connected=!1,this._rawSocket=null,this._disarmRestart(),(0,m.Lq)("switch",`RESET attempts (was ${this._rtcRestartAttempts}) reason=pm-disconnect`),this._rtcRestartAttempts=0,this._probeAttempts=0,this._rtcGivenUp=!1,this._giveUpIp=null,this._lastStunProbeAt=0,this._ackTimers.values()))clearTimeout(e);this._ackTimers.clear()}_buildCtx(e,t){let n={auth:this._auth,profile:this._profile};return"ws"===e&&(n.onRetryStatus=this._wsCallbacks.onRetryStatus,n.onUrlUpdate=e=>{e.tunnelUrl&&(this._auth.tunnelUrl=e.tunnelUrl),void 0!==e.localIp&&(this._auth.localIp=e.localIp),this._wsCallbacks.onUrlUpdate?.(e)}),"rtc"===e&&(n.signaling={send:e=>this._sendSignaling(e),on:e=>{this._rtcSignalingHandler=e},off:()=>{this._rtcSignalingHandler=null}}),n}_onAdapterStateChange(e,t){(0,h.c)("transport",`[pm] ${e} state=${t}`),("rtc"!==e||t!==r.Of.closed)&&(0,m.Lq)("switch",`${e}→${t}`),"ws"===e&&function(e,t){let n=e._adapters.get("ws");if(t===r.Of.open){let t=e._lastWsState===r.Of.degraded;e._connected=!0,e._connectionMode=n?.connectionMode||"tunnel",e._rawSocket=n?.socket||null,t&&e._maybeFireRejoin("ws","ws reconnect while rtc ready"),e._lastWsState!==r.Of.open&&(e._onConnectFired?e._wsCallbacks.onUrlUpdate?.({}):(e._onConnectFired=!0,(0,m.Lq)("switch",`onConnect FIRE (ws, mode=${e._connectionMode})`),e._wsCallbacks.onConnect?.(e._bus,e._connectionMode)))}else e._rawSocket=null,e._lastWsState===r.Of.open&&((0,m.Lq)("switch","ws down"),e._anyAdapterReady()&&(0,m.Lq)("switch","ws down but rtc alive → skip onDisconnect"));e._lastWsState=t}(this,t),"rtc"===e&&function(e,t){if(t===r.Of.open){let t=e._onConnectFired;clearTimeout(e._wsFallbackTimer),e._rtcCallbacks.onUpgrade?.(e._adapters.get("rtc")?.typeDetail||"dc-stun"),e._onConnectFired||(e._onConnectFired=!0,e._connected=!0,e._connectionMode="webrtc",(0,m.Lq)("switch","onConnect FIRE (rtc, mode=webrtc)"),e._wsCallbacks.onConnect?.(e._bus,e._connectionMode)),e._rtcRestartAttempts=0,e._probeAttempts=0,e._rtcGivenUp=!1,e._giveUpIp=null,e._disarmRestart(),clearTimeout(e._rejoinDebounceTimer),e._rejoinDebounceTimer=null;let n=e._adapters.get("rtc");if(n?.isLoopback){(0,m.Lq)("switch","rtc loopback detected (same machine) → drop ws standby");let t=e._adapters.get("ws");if(t){try{t.disconnect()}catch{}e._adapters.delete("ws")}}t&&e._maybeFireRejoin("rtc","rtc reconnect while ws ready")}if(t===r.Of.closed){for(let t of(e._rtcCallbacks.onFallback?.("ws"),(0,m.Lq)("switch","rtc closed → startWsFallback + scheduleRtcRestart"),e._startWsFallback(),clearTimeout(e._wsFallbackTimer),e._pendingAcks.values()))try{t({error:"rtc-closed"})}catch{}for(let t of(e._pendingAcks.clear(),e._ackTimers.values()))clearTimeout(t);e._ackTimers.clear(),e._scheduleRtcRestart("rtc-closed")}}(this,t),"rtc"===e&&t===r.Of.open&&((0,h.c)("auth","[seal] rtc OPEN → sending proof"),(0,R.pV)(this)),this._recomputeType();let n=this._anyAdapterReady();n!==this._connected&&(this._connected=n,n||(this._onConnectFired=!1,(0,m.Lq)("switch",`onDisconnect FIRE (last carrier gone: ${e}→${t})`),this._wsCallbacks.onDisconnect?.(`${e}-${t}`))),this._flushBuffer()}_maybeFireRejoin(e,t){let n="ws"===e?this._adapters.get("rtc"):this._adapters.get("ws");if(n?.ready){(0,h.c)("transport",`[pm] ${t} → skip rejoin (other ready)`),(0,m.Lq)("switch",`${t} → skip rejoin (other ready)`);return}if("ws"===e&&n&&n.state===r.Of.connecting){(0,h.c)("transport",`[pm] ${t} → debounce rejoin (rtc connecting)`),(0,m.Lq)("switch",`${t} → debounce rejoin ${r.ZN}ms (rtc connecting)`),clearTimeout(this._rejoinDebounceTimer),this._rejoinDebounceTimer=setTimeout(()=>{this._rejoinDebounceTimer=null;let e=this._adapters.get("rtc");e?.ready?(0,m.Lq)("switch","debounce: rtc opened → skip rejoin"):((0,m.Lq)("switch",`debounce expired → FIRE rejoin (rtc=${e?.state||"absent"})`),this._bus.dispatch("connect",[]))},r.ZN);return}(0,m.Lq)("switch",`${t} → FIRE rejoin`),this._bus.dispatch("connect",[])}_recomputeType(){let e=this._pickAdapter(r.l_.binary)||this._pickAdapter(r.l_.control),t=e&&"rtc"===e.constructor.id?e.typeDetail||"dc-stun":"ws";t!==this._type&&(this._type=t,this._rtcCallbacks.onTransportChange?.(t))}_anyAdapterReady(){for(let e of this._adapters.values())if(e.ready)return!0;return!1}_pickAdapter(e){return function(e,t,n){let r=t.channels[n];if(!r)return null;let i=[...e.values()].filter(e=>e.supports(n)&&e.ready);return i.length?(i.sort((e,t)=>{let i=t.getPriority?t.getPriority(n):t.constructor.priority[n]??0,s=e.getPriority?e.getPriority(n):e.constructor.priority[n]??0;if(i!==s)return i-s;if(r.prefer){if(t.constructor.id===r.prefer)return 1;if(e.constructor.id===r.prefer)return -1}return 0}),i[0]||null):null}(this._adapters,this._profile,e)}_sendControl(e,t){!function(e,t,n){let i="function"==typeof n[n.length-1]?n.pop():null,s=e._pickAdapter(r.l_.control);if(!s){(0,h.c)("transport",`[pm] buffer event=${t} (no adapter ready)`),(0,m.Lq)("switch",`buffer "${t}" (no adapter)`),e._buffer.push({event:t,args:n,cb:i});return}if((0,h.c)("transport",`[pm] send control event=${t} via=${s.constructor.id}`),"rtc"===s.constructor.id){let a=null;if(i&&(a=`c_${++e._ackSeq}`,e._pendingAcks.set(a,i),e._scheduleAckTimeout(a,{event:t,args:n})),!s.send(r.l_.control,{event:t,args:n,ackId:a})){let o=e._pickAdapter(r.l_.control);if(o&&o!==s&&o.send(r.l_.control,i?{event:t,args:n,ackId:a,cb:i}:{event:t,args:n,ackId:a}))return;(0,h.c)("transport",`[pm] rtc refused event=${t} → buffered`),e._buffer.push({event:t,args:n,cb:i})}}else s.send(r.l_.control,{event:t,args:n,cb:i})}(this,e,t)}_flushBuffer(){!function(e){if(!e._buffer.length)return;let t=e._pickAdapter(r.l_.control);if(!t)return;let n=e._buffer.splice(0);for(let{event:r,args:i,cb:s}of((0,h.c)("transport",`[pm] flush ${n.length} buffered via=${t.constructor.id}`),n))e._sendControl(r,s?[...i,s]:i)}(this)}_dispatch(e,t,n){!function(e,t,n,i){if("srvCaps"===t){let t="rtc"===i?n?.args?.[0]:n;(0,h.c)("transport",`[pm] srvCaps from agent via ${i}: ${JSON.stringify(t)}`),e._srvCaps=t||{},e._adapters.get("rtc")?.setPeerCaps?.(e._srvCaps)}if("__ack"===t){let{ackId:t,args:r}=n||{},i=e._pendingAcks.get(t);if(i){e._pendingAcks.delete(t);let n=e._ackTimers.get(t);n&&(clearTimeout(n),e._ackTimers.delete(t)),i(...r||[])}return}if("device:approved"===t){e._awaitingApproval=!1;let t=e._adapters.get("rtc");e._canSignal()&&(!t||t.state===r.Of.closed)&&e._restartRtc("device-approved")}if("rtc:enabled"===t){e._rtcTestDisabled&&(e._rtcTestDisabled=!1,(0,m.Lq)("switch","rtc:enabled by agent → clear flag + restart RTC"),e._restartRtc("rtc-enabled"));return}if("tunnel:updated"===t){let t="rtc"===i?n?.args?.[0]:n;if(t){let{tunnelUrl:n,localIp:r,status:i}=t;if(e._auth.tunnelUrl===window.location?.origin)return(0,m.Lq)("switch",`tunnel:updated ignored (carrier is the page origin; got url=${n||"none"})`);if((0,m.Lq)("switch",`tunnel:updated recv (status=${i} url=${n||"none"})`),"ready"===i&&n){let t=e._auth.tunnelUrl!==n;e._auth.tunnelUrl=n,r&&(e._auth.localIp=r),e._wsCallbacks.onUrlUpdate?.({tunnelUrl:n,localIp:r});let i=e._adapters.get("ws");if(i&&(!i.ready||t)){(0,m.Lq)("switch",`tunnel:updated → ${t?"url changed":"ws not ready"} → retry ws with new URL`);try{i.retryNow("tunnel-updated")}catch{}}}else"down"===i&&(e._auth.tunnelUrl="",e._wsCallbacks.onUrlUpdate?.({tunnelUrl:"",localIp:r}))}return}let s="rtc"===i&&Array.isArray(n?.args)?n.args:[n];e._bus?.dispatch(t,s)}(this,e,t,n)}_onBinary(e){e&&"file"===e.channel&&this._bus?.dispatch("file-bin",[e.buffer])}_scheduleAckTimeout(e){var t;let n;t=this,n=setTimeout(()=>{t._ackTimers.delete(e),(0,h.c)("transport",`[pm] ack timeout ackId=${e} event=undefined → suspect zombie RTC`);let n=t._pendingAcks.get(e),i=t._adapters.get("rtc");t._adapters.get("ws");let s=Date.now(),a=i?.lastInboundAt||0;i?.ready&&a&&s-a<r.An?(0,m.Lq)("switch",`ack-timeout ? ignored (rtc active, lastInbound=${s-a}ms ago)`):i?.state===r.Of.open?B(t,"ack-timeout:?"):t._scheduleRtcRestart("ack-timeout")},t._ackTimeoutMs),t._ackTimers.set(e,n)}_armRestart(e,t){clearTimeout(this._rtcRestartTimer),this._rtcRestartDueAt=Date.now()+t,this._rtcRestartTimer=setTimeout(e,t)}_disarmRestart(){let e=this._rtcRestartTimer?Math.max(this._rtcRestartDueAt-Date.now(),0):-1;return clearTimeout(this._rtcRestartTimer),this._rtcRestartTimer=null,this._rtcRestartDueAt=0,e}_scheduleRtcRestart(e="?"){if((0,m.Lq)("switch",`rtcRestart REQ by=${e} attempts=${this._rtcRestartAttempts} probe=${this._probeAttempts} givenUp=${this._rtcGivenUp} pending=${!!this._rtcRestartTimer}`),this._rtcRestartTimer){let t=Math.max(this._rtcRestartDueAt-Date.now(),0);(0,m.Lq)("switch",`rtcRestart SKIP by=${e} (pending rung ${this._rtcRestartAttempts} fires in ${t}ms)`);return}if(this._rtcGivenUp){(0,m.Lq)("switch","scheduleRtcRestart skipped (hard NAT → WS-only)"),(0,h.c)("transport","[pm] rtc probe skipped (given up — hard NAT)");return}let t=function({attempts:e,probeAttempts:t,verdict:n}){let i,s,a=e>=r.QZ.maxAttempts,o=t;if(a){if(i=r.QZ.probeBackoffMs[t]??r.QZ.probeBackoffMs.at(-1),(o=t+1)>=r.QZ.classifyAfterProbes){if("hard"===(s=n?.()??"unknown"))return{giveUp:!0,verdict:s,probeAttempts:o};o=0}}else i=r.QZ.backoffMs[e]??r.QZ.backoffMs.at(-1);return{delay:i,isProbe:a,attempts:e+1,probeAttempts:o,verdict:s}}({attempts:this._rtcRestartAttempts,probeAttempts:this._probeAttempts,verdict:()=>this._adapters.get("rtc")?.natVerdict?.()??"unknown"});if(void 0!==t.verdict&&((0,m.Lq)("switch",`scheduleRtcRestart natVerdict=${t.verdict} probeAttempts=${t.probeAttempts}`),(0,h.c)("transport",`[pm] rtc nat verdict=${t.verdict} after ${t.probeAttempts} probes`)),t.giveUp){this._probeAttempts=t.probeAttempts,this._rtcGivenUp=!0,this._giveUpIp=this._netFingerprint,this._giveUpIp||$().then(e=>{this._rtcGivenUp&&!this._giveUpIp&&(this._giveUpIp=e||E,(0,m.Lq)("switch",`give-up baseline from probe: ip=${this._giveUpIp}`))}).catch(()=>{}),(0,m.Lq)("switch",`RTC give-up: hard NAT → WS-only (ip=${this._giveUpIp||"pending"})`);return}let{delay:n,isProbe:i}=t;this._probeAttempts=t.probeAttempts,this._rtcRestartAttempts=t.attempts,(0,m.Lq)("switch",`rtcRestart ARM by=${e} rung=${this._rtcRestartAttempts} delay=${n}ms probe=${i}`),(0,h.c)("transport",`[pm] schedule rtc ${i?"probe":"restart"} #${this._rtcRestartAttempts} in ${n}ms`);let s=()=>{if(this._disarmRestart(),this._awaitingApproval||!this._sig?.ready)return;let e=this._adapters.get("rtc");if(e){let t=function({state:e,connectingSince:t,connectDeadline:n,now:i,connectTimeoutMs:s}){return e!==r.Of.connecting?"restart":i<function({connectingSince:e,connectDeadline:t,connectTimeoutMs:n}){return t??(e??0)+n}({connectingSince:t,connectDeadline:n,connectTimeoutMs:s})?"wait":"teardown"}({state:e.state,connectingSince:e.connectingSince,connectDeadline:e.connectDeadline,now:Date.now(),connectTimeoutMs:r.AC});if("wait"===t){let t=Math.max(function({connectingSince:e,connectDeadline:t,connectTimeoutMs:n}){return t??(e??0)+n}({connectingSince:e.connectingSince,connectDeadline:e.connectDeadline,connectTimeoutMs:r.AC})-Date.now(),n);(0,m.Lq)("switch",`restart tick: peer still young (rung ${this._rtcRestartAttempts}) → re-arm in ${t}ms, no rung spent`),this._armRestart(s,t);return}if("teardown"===t){try{e.disconnect(`rung-${this._rtcRestartAttempts}-teardown`)}catch{}this._adapters.delete("rtc"),this._rtcSignalingHandler=null}}this._restartRtc(`rung-${this._rtcRestartAttempts}`)};this._armRestart(s,n)}_sendSignaling(e){K(this,e)}_flushSigBuffer(){H(this)}}},80186:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});var r=n(73365);function i({children:e,variant:t="primary",size:n="md",disabled:s=!1,loading:a=!1,onClick:o,className:l="",...c}){let d=`font-semibold rounded-brand transition-all duration-150 ease-out transform active:scale-[0.97] ${{primary:"bg-brand-500 hover:bg-brand-600 disabled:bg-surface-3 disabled:text-text-muted text-white shadow-sm",secondary:"bg-surface-2 hover:bg-surface-3 disabled:bg-surface disabled:text-text-muted text-text",danger:"bg-red-500 hover:bg-red-600 disabled:bg-surface-3 disabled:text-text-muted text-white",success:"bg-green-600 hover:bg-green-700 disabled:bg-surface-3 disabled:text-text-muted text-white"}[t]} ${{sm:"px-3 py-1.5 text-sm",md:"px-4 py-2 text-base",lg:"px-6 py-3 text-lg"}[n]} ${s||a?"cursor-not-allowed":""} ${l}`;return(0,r.jsx)("button",{onClick:o,disabled:s||a,className:d,...c,children:a?(0,r.jsxs)("span",{className:"flex items-center justify-center gap-2",children:[(0,r.jsx)("span",{className:"animate-spin rounded-full h-4 w-4 border-b-2 border-white"}),e]}):e})}},86129:(e,t,n)=>{"use strict";n.d(t,{AC:()=>u,An:()=>d,BF:()=>m,El:()=>v,HE:()=>P,HJ:()=>p,Ic:()=>C,J2:()=>w,Jd:()=>A,KF:()=>c,ML:()=>_,N0:()=>T,Of:()=>D,QS:()=>h,QZ:()=>s,Rh:()=>x,Tr:()=>f,UT:()=>g,ZN:()=>o,aS:()=>S,bg:()=>b,cx:()=>a,dT:()=>i,gI:()=>y,j3:()=>I,l_:()=>r,o_:()=>R,qM:()=>k,si:()=>l});let r={control:"control",binary:"binary",file:"file"},i=65536,s={ackTimeoutMs:5e3,maxAttempts:3,backoffMs:[500,1500,3e3],probeBackoffMs:[3e4,6e4,12e4,3e5],classifyAfterProbes:3},a={urls:["stun:stun.l.google.com:19302","stun:stun1.l.google.com:19302"],timeoutMs:2500,minIntervalMs:15e3},o=500,l=3,c=1e4,d=25e3,u=4e3,p=15e3,h=1e3,m=12e3,g=2e3,f=1e4,y={enabled:!0,pingMs:25e3},b={pending:"pending-approval",rejected:"device-rejected"},_={mismatch:"mismatch",sealUnreadable:"seal-unreadable",timeout:"proof-timeout"},w={pending:"pending",approved:"approved",rejected:"rejected",reconnect:"reconnect"},k=8,v="9remote_pending_save",S="9remote_wants_save",T="9remote:keys-changed",A="9remote_login_error",C="strict",R={debounceMs:500},x=3e4,P={chunkSize:65528,windowSize:64,dcBufferThreshold:8388608,maxUploadSize:0x3200000,maxDownloadSize:0xc800000,maxStreamMediaSize:524288e3},D={idle:"idle",connecting:"connecting",open:"open",degraded:"degraded",closed:"closed"},I={clientApp:{enabled:["ws","rtc"],parallel:!0,channels:{control:{strategy:"priority",prefer:"rtc"},binary:{strategy:"priority",prefer:"rtc"},file:{strategy:"priority",prefer:"rtc"}},rtc:{enableTurn:!0,dcControl:{ordered:!0}}},remoteDesktop:{enabled:["ws","rtc"],parallel:!0,channels:{control:{strategy:"priority",prefer:"rtc"},binary:{strategy:"priority",prefer:"rtc"},file:{strategy:"priority",prefer:"rtc"}},rtc:{enableTurn:!0,dcControl:{ordered:!0}}}}},86251:(e,t,n)=>{"use strict";n.d(t,{O:()=>u,Y:()=>c});let r=new Uint8Array([48,42,48,5,6,3,43,101,110,3,33,0]);function i(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}function s(e){let t="",n=new Uint8Array(e);for(let e=0;e<n.length;e++)t+=String.fromCharCode(n[e]);return btoa(t)}function a(...e){let t=new Uint8Array(e.reduce((e,t)=>e+t.length,0)),n=0;for(let r of e)t.set(r,n),n+=r.length;return t}async function o(e){let t;try{t=i(String(e))}catch{return null}if(32!==t.length)return null;try{return await crypto.subtle.importKey("spki",a(r,t),{name:"X25519"},!0,[])}catch{return null}}async function l(e,t,n,r){let i=await crypto.subtle.deriveBits({name:"X25519",public:t},e,256),s=await crypto.subtle.importKey("raw",i,"HKDF",!1,["deriveKey"]);return await crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:a(n,r),info:new TextEncoder().encode("9remote-tail-seal-v1")},s,{name:"AES-GCM",length:256},!1,["encrypt"])}async function c(e,t){if("string"!=typeof e||!e||"string"!=typeof t||!t)return null;let n=await o(t);if(!n)return null;try{let t=await crypto.subtle.generateKey({name:"X25519"},!0,["deriveBits"]),r=new Uint8Array(await crypto.subtle.exportKey("spki",t.publicKey)).slice(-32),i=new Uint8Array(await crypto.subtle.exportKey("spki",n)).slice(-32),a=await l(t.privateKey,n,r,i),o=crypto.getRandomValues(new Uint8Array(12)),c=await crypto.subtle.encrypt({name:"AES-GCM",iv:o},a,new TextEncoder().encode(e));return{epk:s(r),iv:s(o),ct:s(c)}}catch{return null}}let d="ABCDEFGHJKLMNPQRSTUVWXYZ23456789";async function u(e,t){if("u"<typeof crypto||!crypto.subtle)return null;let n=[e,t].map(e=>{let t;try{t=i(String(e||""))}catch{t=new Uint8Array(0)}let n=new Uint8Array(2);return new DataView(n.buffer).setUint16(0,t.length),a(n,t)}),r=new Uint8Array(await crypto.subtle.digest("SHA-256",a(...n)));return d[r[0]%32]+d[r[1]%32]}},90076:(e,t,n)=>{"use strict";n.d(t,{Go:()=>a,O:()=>r,Sn:()=>o,_8:()=>i,cC:()=>u,dM:()=>c,jP:()=>l,lE:()=>s,qn:()=>d});let r="https://9remote.cc",i=2208,s=`http://127.0.0.1:${i}`,a=`${s}/api/ui/state`,o={connect:`${r}/api/connect`,tempKeyCreate:`${r}/api/temp-key/create`,tempKeyVerify:`${r}/api/temp-key/verify`,tempKeyRemove:`${r}/api/temp-key/remove`,localSites:"/api/local-sites",turnCredentials:`${r}/api/webrtc/turn-credentials`},l=5,c=2e3,d=5e3,u=1e4},90084:(e,t,n)=>{"use strict";n.d(t,{$4:()=>d,D5:()=>_,HY:()=>h,I8:()=>f,IU:()=>w,LG:()=>u,cH:()=>y,e1:()=>m,lu:()=>k,lz:()=>c,pV:()=>v,t8:()=>p});var r=n(86129);n(52159);var i=n(86251);let s="9remote_device_trust",a="9remote_pending_fp2";function o(){try{return JSON.parse(localStorage.getItem(s)||"{}")}catch{return{}}}function l(e){localStorage.setItem(s,JSON.stringify(e))}function c(e){return o()[e]||null}function d(e){if(!e)return e;let t=c(e)?.tail;return t?`${e}-${t}`:e}function u(e,t){let n=o();n[e]={...n[e]||{},...t},l(n)}async function p(e,t){return e&&t?await (0,i.O)(e,t):null}function h(){let e=sessionStorage.getItem(a);return sessionStorage.removeItem(a),e?JSON.parse(e).fp2??null:null}function m(){try{let e=sessionStorage.getItem(a);if(!e)return null;let{fp2:t,exp:n}=JSON.parse(e);if(!t||Date.now()>n)return sessionStorage.removeItem(a),null;return t}catch{return null}}let g="9remote_api_keys";function f(){try{let e=sessionStorage.getItem(r.El);if(!e)return;sessionStorage.removeItem(r.El);let t=JSON.parse(localStorage.getItem(g)||"[]");if(t.some(t=>{try{return atob(t.key)===e}catch{return!1}}))return;t.push({id:String(Date.now()),key:btoa(e),label:`Key ${t.length+1}`,createdAt:new Date().toISOString(),lastLoginDate:new Date().toISOString()}),localStorage.setItem(g,JSON.stringify(t));try{window.dispatchEvent(new Event(r.N0))}catch{}}catch{}}function y(e){if(e)try{let t=o();delete t[e],l(t)}catch{}}function b(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}async function _(e,t,n){try{let r=await crypto.subtle.importKey("raw",b(e),{name:"Ed25519"},!1,["verify"]);return await crypto.subtle.verify("Ed25519",r,b(n),new TextEncoder().encode(t))}catch{return null}}let w=["device:keyIssued","device:tailRejected"];function k(e,t,n){let i=e._auth?.apiKey;if(!i)return!1;if("device:keyIssued"===t){e._auth.tempKey=null,e._auth.socketOptions?.auth&&(e._auth.socketOptions.auth.tempKey=null);try{sessionStorage.removeItem("tempKey")}catch{}let t=n?.tail;return!t||(u(i,{tail:t}),e._tailProofSent=e._adapters.get("rtc")?._peerEpoch??0,sessionStorage.getItem(r.aS)&&(sessionStorage.removeItem(r.aS),sessionStorage.setItem(r.El,`${i}-${t}`),f()),!0)}return"device:tailRejected"===t&&(n?.reason===r.ML.sealUnreadable&&u(i,{hostSealKey:null}),!0)}async function v(e){let t=e._auth?.apiKey;if(!t)return;let i=e._adapters.get("rtc");if(!i?.ready)return;let s=i._peerEpoch??0;if(e._tailProofSent===s)return;let{freshAuth:a}=await Promise.resolve().then(n.bind(n,63977)),o=await a({apiKey:t,tempKey:e._auth?.tempKey||null},"rtc");(o.keyTail||o.keyTailSealed)&&i.send(r.l_.control,{event:"device:tailProof",args:[{keyTail:o.keyTail,keyTailSealed:o.keyTailSealed,tempKey:e._auth?.tempKey||null}]})&&(e._tailProofSent=s)}},94858:(e,t,n)=>{"use strict";n.d(t,{d:()=>s});var r=n(2074),i=n(86129);let s=(0,r.v)(e=>({bus:null,busRef:{current:null},protocolRef:{current:null},connected:!1,everConnected:!1,deliberate:!1,connectionMode:"tunnel",carrier:"ws",approvalStatus:null,admitted:!1,authKey:null,endpoint:null,retryStatus:{isRetrying:!1,attempt:0,maxAttempts:10,failed:!1},setConnection:t=>e(e=>({...e,...t})),setConnected:t=>e({connected:t}),setCarrier:t=>e({carrier:t}),setConnectionMode:t=>e({connectionMode:t}),setRetryStatus:t=>e({retryStatus:t}),setAuthKey:t=>e({authKey:t}),setAdmitted:t=>e({admitted:t}),applyApproval:t=>e(e=>{let n=e.approvalStatus;return t===i.J2.reconnect?n===i.J2.approved?{approvalStatus:null}:{}:n===i.J2.approved&&t===i.J2.pending?{}:{approvalStatus:t}}),reset:()=>e({bus:null,connected:!1,deliberate:!1,everConnected:!1,connectionMode:"tunnel",carrier:"ws",endpoint:null,approvalStatus:null,admitted:!1,retryStatus:{isRetrying:!1,attempt:0,maxAttempts:10,failed:!1}})}))},97711:(e,t,n)=>{"use strict";n.d(t,{Fo:()=>u,U0:()=>l,vd:()=>d});var r=n(1521),i=n(94858);let s="9remote_auth",a="9remote_auth_state",o=["apiKey","tunnelUrl","mode","localIp"];function l(){try{localStorage.removeItem(a)}catch{}}function c(e){"u">typeof document&&(document.cookie=`${s}=${e}; path=/; max-age=86400; SameSite=Lax`)}function d({apiKey:e,tunnelUrl:t,mode:n="remote",tempKey:r=null,localIp:s=null}){if(!e){try{localStorage.removeItem(a)}catch{}return}try{sessionStorage.setItem("apiKey",e),sessionStorage.setItem("tunnelUrl",t),sessionStorage.setItem("mode",n||"remote"),r?sessionStorage.setItem("tempKey",r):sessionStorage.removeItem("tempKey"),s?sessionStorage.setItem("localIp",s):sessionStorage.removeItem("localIp")}catch{}c(e);try{sessionStorage.removeItem("9remote_manual_disconnect")}catch{}try{!function(){try{return"false"!==localStorage.getItem("9remote_remember_key_preference")}catch{return!1}}()?localStorage.removeItem(a):localStorage.setItem(a,JSON.stringify({apiKey:e,tunnelUrl:t,mode:n,localIp:s}))}catch{}i.d.getState().setAuthKey(e)}function u(){let e=(0,r.useCallback)(()=>{let e,t,n,r,i;try{e=sessionStorage.getItem("apiKey"),t=sessionStorage.getItem("tunnelUrl"),n=sessionStorage.getItem("mode"),r=sessionStorage.getItem("tempKey"),i=sessionStorage.getItem("localIp")}catch{return null}if(!e){let r=function(){try{return JSON.parse(localStorage.getItem(a)||"null")}catch{return null}}();if(!r?.apiKey)return null;try{for(let e of o)r[e]&&sessionStorage.setItem(e,r[e])}catch{}e=r.apiKey,t=r.tunnelUrl??null,n=r.mode??null,i=r.localIp??null}return c(e),{apiKey:e,tunnelUrl:t,mode:n,tempKey:r,localIp:i}},[]);return{getAuth:e,setAuth:(0,r.useCallback)(e=>d(e),[]),clearAuth:(0,r.useCallback)(()=>{try{sessionStorage.clear()}catch{}try{localStorage.removeItem(a)}catch{}"u">typeof document&&(document.cookie=`${s}=; path=/; max-age=0`)},[])}}},98988:(e,t,n)=>{"use strict";n.d(t,{Nw:()=>C,eJ:()=>T,d:()=>A,rh:()=>S});var r=n(2074),i=n(29091),s=n(94858),a=n(79453),o=n(7938),l=n(11155),c=n(90084);let d="9remote_fleet_connected";function u(){try{return JSON.parse(localStorage.getItem(d)||"[]")}catch{return[]}}class p{constructor({hostOf:e,patch:t,bindBus:n,ready:r,probeTargets:i,servedBy:s=null,servedBus:a=null}){this._hostOf=e,this._patch=t,this._bindBus=n,this._ready=r,this._probeTargets=i,this._servedBy=s||(()=>!1),this._servedBus=a||(()=>null),this.buses=new Map,this.pending=new Map,this._probeTimer=null,this._probeVisible=null}busOf(e){return e&&this.buses.get(e)?.busRef?.current||null}pmOf(e){return this.buses.get(e)||null}has(e){return this.buses.has(e)}whenReady(e,t){let n=this._hostOf(e);if(!e||!n)return;if(this._servedBy(e)){let n=this._servedBus(e);n&&t(n);return}let r=this.busOf(e);if(r&&"online"===n.status)return void t(r);if(!this._canOpen(n,e))return;this.open(e,n);let i=this.pending.get(e)||[];i.push(t),this.pending.set(e,i)}persistIntent(e,t){if(e)try{let n=new Set(u());t?n.add(e):n.delete(e),localStorage.setItem(d,JSON.stringify([...n]))}catch{}}_canOpen(e,t){return!(!e||this._servedBy(t))&&!!e.full}open(e,t){if(this.has(e))return;let n=function(){try{return localStorage.getItem("9remote_deviceId")}catch{return null}}();if(!this._canOpen(t,e)||!n)return;this.persistIntent(e,!0);let r=(0,l.Cj)(t.full);r&&(0,c.LG)(e,{tail:r});let i=t=>this._patch(e,t),s=!1,d=null,u=new a.g({tunnelUrl:null,localIp:null,namespace:"",socketOptions:{auth:{apiKey:e,tempKey:null,deviceId:n}},apiKey:e,deviceId:n,tempKey:null,onConnect:t=>{clearTimeout(d),i({status:"online",lastSeenAt:Date.now(),updating:!1,approval:null});let n=this.pending.get(e);if(n)for(let r of(this.pending.delete(e),n))try{r(t)}catch{}s||(s=!0,this._bindBus(t,e)),this._ready(t,e)},onDisconnect:()=>{this.pending.delete(e),i({status:"offline",lastSeenAt:Date.now()})}},{enableWebRTC:o.eR.enableWebRTC,enableTurn:o.eR.enableTurn,apiKey:e,onTransportChange:e=>i({carrier:e||"ws"})});this.buses.set(e,u),i({status:"connecting"}),d=setTimeout(()=>this._onConnectTimeout(e),15e3),u.connect()}_onConnectTimeout(e){this.buses.has(e)&&this._hostOf(e)?.status==="connecting"&&(this._patch(e,{status:"offline"}),this._hostOf(e)?.approval!=="pending"&&this.persistIntent(e,!1))}drop(e){let t=this.buses.get(e);t&&(t.disconnect(),this.buses.delete(e)),this.pending.delete(e)}retry(e){this.drop(e),this.open(e,this._hostOf(e))}closeAll(){for(let e of this.buses.values())e.disconnect();this.buses.clear(),this.pending.clear(),this.disarmProbe()}armProbe(){this._probeTimer||(this._probeTimer=setInterval(()=>{document.hidden||this.probeOnce()},6e4),this._probeVisible=()=>{"visible"===document.visibilityState&&this.probeOnce()},document.addEventListener("visibilitychange",this._probeVisible))}disarmProbe(){this._probeTimer&&(clearInterval(this._probeTimer),this._probeTimer=null,document.removeEventListener("visibilitychange",this._probeVisible),this._probeVisible=null)}probeOnce(){let e=this._probeTargets().filter(e=>!this.has(e));e.length&&fetch("/api/host-status",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({heads:e})}).then(e=>e.ok?e.json():null).then(t=>{for(let n of e){if(this.has(n))continue;let e=t?.hosts?.[n];e&&this._patch(n,{status:e.online?"online":"offline"})}}).catch(()=>{})}}var h=n(51627),m=n(31408),g=n(27520);let f="9remote_fleet_cache",y=null;function b(e){clearTimeout(y),y=setTimeout(()=>{y=null;let t={};for(let[n,r]of Object.entries(e().hosts))t[n]={label:r.label,platform:r.platform,version:r.version,sessions:r.sessions,workspaces:r.workspaces,statusMap:r.statusMap,lastSeenAt:r.lastSeenAt};try{localStorage.setItem(f,JSON.stringify(t))}catch{}},1e3)}let _=e=>({key:e,full:null,label:"",status:"offline",carrier:"ws",sessions:[],workspaces:[],statusMap:{},platform:null,version:null,lastSeenAt:null,updateAvailable:null,canSelfUpdate:!1,updating:!1,approval:null,remoteAvailable:!1,mobileAvailable:!1,isCodespaces:!1,mobileDeviceCount:0}),w=(e,t)=>S.getState()._patchHost(e,t),k=(e,t)=>{e?.emit("getSessions",e=>{Array.isArray(e)&&w(t,{sessions:e})}),e?.emit("getWorkspaces",e=>{Array.isArray(e)&&w(t,{workspaces:e})}),e?.emit("getStatusState")},v=null,S=(0,r.v)((e,t)=>({hosts:{},currentKey:null,sync(n,r){let i=r||"",s=new Map;for(let e of n){let t=(0,l.Uo)(e.key);t&&!s.has(t)&&s.set(t,{full:e.key,label:e.label||""})}i&&!s.has(i)&&s.set(i,{full:null,label:""});let a=[...s.keys()].filter(e=>e!==i).slice(0,8),o=new Set(a);for(let e of[...v.buses.keys()])o.has(e)||v.drop(e);let c=function(){try{return JSON.parse(localStorage.getItem(f)||"{}")}catch{return{}}}(),d=new Set(u()),p=!1;try{p="1"===sessionStorage.getItem("9remote_manual_disconnect")}catch{}for(let n of(e(e=>{let t={};for(let[n,r]of s){let s=e.hosts[n]||{..._(n),...c[n]||{}};t[n]={...s,key:n,full:r.full,label:r.label||s.label,status:n===i?p?"offline":"full":o.has(n)&&("online"===s.status||"connecting"===s.status)?s.status:"offline"}}return{hosts:t,currentKey:i}}),a))d.has(n)&&v.open(n,t().hosts[n]);v.probeOnce(),v.armProbe()},_patchHost(n,r){e(e=>{let t=e.hosts[n];return t?{hosts:{...e.hosts,[n]:{...t,...r}}}:e}),b(t)},applyStatusState(n,r){let i=r||{};e(e=>{let t=e.hosts[n];return!t||(0,m.h3)(t.statusMap,i)?e:{hosts:{...e.hosts,[n]:{...t,statusMap:i}}}}),b(t)},applyStatusChange(n,{sessionId:r,state:i,tool:s,since:a,conversationId:o}={}){r&&(e(e=>{let t=e.hosts[n];if(!t)return e;let l=t.statusMap[r],c={state:i,tool:void 0!==s?s:l?.tool,since:a,...o||l?.conversationId?{conversationId:o||l?.conversationId}:{}};return(0,m.dI)(l,c)?e:{hosts:{...e.hosts,[n]:{...t,statusMap:{...t.statusMap,[r]:c}}}}}),b(t))},applyStatusCleared(n,r){r&&(e(e=>{let t=e.hosts[n],i=t?.statusMap?.[r];return i?{hosts:{...e.hosts,[n]:{...t,statusMap:{...t.statusMap,[r]:{...i,state:"idle"}}}}}:e}),b(t))},_closeHost(e,n={}){v.drop(e),t()._patchHost(e,{status:"offline",lastSeenAt:Date.now(),approval:null,...n})},ensureHost(e){e===t().currentKey||v.has(e)||v.open(e,t().hosts[e])},connectHost(e){t().retryHost(e)},requestHostUpdate(e,n="update"){let r=t().hosts[e];if(!r||r.updating)return;let i={updating:!0,updateAvailable:null};if("full"===r.status){let r=s.d.getState(),a=r.busRef?.current;if(!a?.connected)return void(0,g.Lq)("update",`request ${n} on ACTIVE ${e} dropped: bus not connected`);t()._patchHost(e,i),r.protocolRef?.current?.setUpdating?.(!0),a.emit("restart"===n?"requestRestart":"requestUpdate")}else t()._patchHost(e,i),v.pmOf(e)?.setUpdating?.(!0),v.whenReady(e,t=>{v.pmOf(e)?.setUpdating?.(!0),(0,g.Lq)("update",`request ${n} sent on fleet bus ${e}`),t.emit("restart"===n?"requestRestart":"requestUpdate")});setTimeout(()=>{t().hosts[e]?.updating&&t()._patchHost(e,{updating:!1})},12e4)},setAutoConnect(e,t){v.persistIntent(e,t)},retryHost(e){v.retry(e)},disconnectHost(e){v.persistIntent(e,!1),t()._closeHost(e)},closeAll(){v.closeAll()}}));function T(e){return v?.busOf(e)||null}function A(e){return v?.pmOf(e)||null}function C(e,t){v?.whenReady(e,t)}v=new p({hostOf:e=>S.getState().hosts[e],patch:w,bindBus:(e,t)=>{e.on("connect",()=>{e.emit("device:clientReady"),k(e,t)}),e.on("serverInfo",e=>{let n=!!S.getState().hosts[t]?.updating;w(t,{platform:e?.platform||null,isCodespaces:!!e?.isCodespaces,version:e?.version||null,updateAvailable:!n&&(0,h.U)(e?.updateAvailable?.version,e?.version)?e.updateAvailable:null,canSelfUpdate:!!e?.canSelfUpdate,remoteAvailable:!!e?.remoteAvailable,mobileAvailable:!!e?.mobileAvailable})}),e.on("statusState",e=>S.getState().applyStatusState(t,e)),e.on("statusChange",e=>S.getState().applyStatusChange(t,e)),e.on("statusCleared",e=>S.getState().applyStatusCleared(t,e)),e.on("sessionsChanged",()=>k(e,t)),e.on("workspacesChanged",()=>k(e,t)),e.on("session-renamed",()=>k(e,t)),e.on("sessionClosed",n=>{n&&i.B.getState().closeSession(n),k(e,t)}),e.on("device:pendingApproval",()=>w(t,{approval:"pending"})),e.on("device:approved",()=>w(t,{approval:null})),e.on("device:rejected",()=>S.getState()._closeHost(t,{approval:"rejected"})),e.on("device:tailRejected",()=>S.getState()._closeHost(t))},ready:(e,t)=>{e.emit("device:clientReady"),k(e,t)},probeTargets:()=>{let e=S.getState(),t=new Set(u());return Object.values(e.hosts).filter(n=>n.key!==e.currentKey&&t.has(n.key)).map(e=>e.key)},servedBy:e=>!!e&&e===S.getState().currentKey,servedBus:()=>{let e=s.d.getState();return e.connected?e.busRef?.current||e.bus:null}})}}]);