@xopcai/xopc 0.0.84 → 0.0.86

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 (418) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  3. package/dist/extensions/feishu/src/plugin.d.ts +2 -0
  4. package/dist/extensions/feishu/src/plugin.js +10 -0
  5. package/dist/extensions/feishu/src/plugin.js.map +1 -1
  6. package/dist/extensions/feishu/src/workflow-progress.d.ts +27 -0
  7. package/dist/extensions/feishu/src/workflow-progress.js +99 -0
  8. package/dist/extensions/feishu/src/workflow-progress.js.map +1 -0
  9. package/dist/extensions/telegram/src/plugin.d.ts +2 -0
  10. package/dist/extensions/telegram/src/plugin.js +11 -1
  11. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  12. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  13. package/dist/extensions/telegram/src/workflow-progress.d.ts +24 -0
  14. package/dist/extensions/telegram/src/workflow-progress.js +73 -0
  15. package/dist/extensions/telegram/src/workflow-progress.js.map +1 -0
  16. package/dist/extensions/telegram/xopc.extension.json +1 -1
  17. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +158 -0
  18. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +1 -0
  19. package/dist/extensions/weixin/src/api/api.js +2 -2
  20. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  21. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  22. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  23. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  24. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  25. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  26. package/dist/extensions/weixin/src/plugin.d.ts +2 -0
  27. package/dist/extensions/weixin/src/plugin.js +11 -1
  28. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  29. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  30. package/dist/extensions/weixin/src/workflow-progress.d.ts +26 -0
  31. package/dist/extensions/weixin/src/workflow-progress.js +99 -0
  32. package/dist/extensions/weixin/src/workflow-progress.js.map +1 -0
  33. package/dist/gateway/static/root/assets/agents-mS3_HpRI.js +222 -0
  34. package/dist/gateway/static/root/assets/apps-page-DrfytjOb.js +1 -0
  35. package/dist/gateway/static/root/assets/channels-settings-BG6b9KrW.js +1 -0
  36. package/dist/gateway/static/root/assets/channels-status-swr-Bs5kMCMI.js +8 -0
  37. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +1 -0
  38. package/dist/gateway/static/root/assets/cron-api-BuVcZ5zR.js +1 -0
  39. package/dist/gateway/static/root/assets/cron-page-BMrloeFH.js +1 -0
  40. package/dist/gateway/static/root/assets/dist-BTWC-BTN.js +45 -0
  41. package/dist/gateway/static/root/assets/{dist-CqNMNhJM.js → dist-CKU1OOTf.js} +1 -1
  42. package/dist/gateway/static/root/assets/{extension-debug-page-gf2L0kY_.js → extension-debug-page-BdW_46sN.js} +1 -1
  43. package/dist/gateway/static/root/assets/extension-page-DW47KI82.js +1 -0
  44. package/dist/gateway/static/root/assets/extension-settings-page-B-W4x2xP.js +1 -0
  45. package/dist/gateway/static/root/assets/fetch-B2MYHbWg.js +1 -0
  46. package/dist/gateway/static/root/assets/{field-primitives-DTtlp-l8.js → field-primitives-DPG-oJmx.js} +1 -1
  47. package/dist/gateway/static/root/assets/heartbeat-config-api-C8dNts9i.js +1 -0
  48. package/dist/gateway/static/root/assets/index-BmVYculr.js +4700 -0
  49. package/dist/gateway/static/root/assets/index-ew_2L2We.css +1 -0
  50. package/dist/gateway/static/root/assets/logs-page-sTsVWz0X.js +1 -0
  51. package/dist/gateway/static/root/assets/sessions-page-FaG_Vlkb.js +1 -0
  52. package/dist/gateway/static/root/assets/settings-form-section-DuvRQW--.js +1 -0
  53. package/dist/gateway/static/root/assets/settings-page-Bet1OerL.js +3 -0
  54. package/dist/gateway/static/root/assets/share-preview-page-BtG2kLDh.js +2 -0
  55. package/dist/gateway/static/root/assets/skills-page-DhUO235y.js +2 -0
  56. package/dist/gateway/static/root/assets/theme-store-DryYl3qD.js +1 -0
  57. package/dist/gateway/static/root/assets/url-BwNL6Rgk.js +3 -0
  58. package/dist/gateway/static/root/assets/utils-BY7bU1DT.js +1 -0
  59. package/dist/gateway/static/root/assets/voice-api-key-field-CGEydndO.js +1 -0
  60. package/dist/gateway/static/root/index.html +7 -6
  61. package/dist/package.js +1 -1
  62. package/dist/src/agent/agent-manager.js +7 -7
  63. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  64. package/dist/src/agent/context/workspace-seed.js +3 -3
  65. package/dist/src/agent/embedded/map-stream-events.js +6 -0
  66. package/dist/src/agent/embedded/map-stream-events.js.map +1 -1
  67. package/dist/src/agent/embedded/subscribe-session.js +24 -0
  68. package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
  69. package/dist/src/agent/embedded/types.d.ts +19 -0
  70. package/dist/src/agent/goals/goal-locale.js +2 -2
  71. package/dist/src/agent/goals/goal-run-store.js +4 -4
  72. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  73. package/dist/src/agent/goals/post-turn.js +2 -2
  74. package/dist/src/agent/image/load-image-media.js +2 -2
  75. package/dist/src/agent/ipc/bus.js +1 -1
  76. package/dist/src/agent/ipc/inbox.js +2 -2
  77. package/dist/src/agent/ipc/socket.js +1 -1
  78. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  79. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  80. package/dist/src/agent/memory/dreaming/events.js +1 -1
  81. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  82. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  83. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  84. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  85. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  86. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  87. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  88. package/dist/src/agent/models/manager.js +1 -1
  89. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  90. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  91. package/dist/src/agent/reply/startup-context.d.ts +3 -0
  92. package/dist/src/agent/reply/startup-context.js +25 -2
  93. package/dist/src/agent/reply/startup-context.js.map +1 -1
  94. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  95. package/dist/src/agent/sandbox/path-policy.js +2 -2
  96. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  97. package/dist/src/agent/service.d.ts +1 -0
  98. package/dist/src/agent/service.js +10 -4
  99. package/dist/src/agent/service.js.map +1 -1
  100. package/dist/src/agent/session/session-inspector.js +1 -1
  101. package/dist/src/agent/skills/config.js +1 -1
  102. package/dist/src/agent/skills/hub-hash.js +2 -2
  103. package/dist/src/agent/skills/hub-lock.js +1 -1
  104. package/dist/src/agent/skills/hub-pull.js +3 -3
  105. package/dist/src/agent/skills/index.js +1 -1
  106. package/dist/src/agent/skills/managed-store.js +1 -1
  107. package/dist/src/agent/skills/scanner.js +1 -1
  108. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  109. package/dist/src/agent/skills/skill-manager.js +1 -1
  110. package/dist/src/agent/tools/create-share-tool.d.ts +27 -0
  111. package/dist/src/agent/tools/create-share-tool.js +237 -0
  112. package/dist/src/agent/tools/create-share-tool.js.map +1 -0
  113. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  114. package/dist/src/agent/tools/factory.js +35 -1
  115. package/dist/src/agent/tools/factory.js.map +1 -1
  116. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  117. package/dist/src/agent/tools/index.d.ts +2 -0
  118. package/dist/src/agent/tools/index.js +3 -1
  119. package/dist/src/agent/tools/send-media.js +1 -1
  120. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  121. package/dist/src/agent/tools/workflow-tool.d.ts +41 -0
  122. package/dist/src/agent/tools/workflow-tool.js +271 -0
  123. package/dist/src/agent/tools/workflow-tool.js.map +1 -0
  124. package/dist/src/agent/tools/write.js +1 -1
  125. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +13 -0
  126. package/dist/src/agent/workflow/builtins/audit-repo.js +156 -0
  127. package/dist/src/agent/workflow/builtins/audit-repo.js.map +1 -0
  128. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +13 -0
  129. package/dist/src/agent/workflow/builtins/debug-incident.js +155 -0
  130. package/dist/src/agent/workflow/builtins/debug-incident.js.map +1 -0
  131. package/dist/src/agent/workflow/builtins/index.d.ts +17 -0
  132. package/dist/src/agent/workflow/builtins/index.js +38 -0
  133. package/dist/src/agent/workflow/builtins/index.js.map +1 -0
  134. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +14 -0
  135. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +149 -0
  136. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +1 -0
  137. package/dist/src/agent/workflow/builtins/pr-review.d.ts +12 -0
  138. package/dist/src/agent/workflow/builtins/pr-review.js +156 -0
  139. package/dist/src/agent/workflow/builtins/pr-review.js.map +1 -0
  140. package/dist/src/agent/workflow/builtins/research.d.ts +13 -0
  141. package/dist/src/agent/workflow/builtins/research.js +160 -0
  142. package/dist/src/agent/workflow/builtins/research.js.map +1 -0
  143. package/dist/src/agent/workflow/catalog.d.ts +56 -0
  144. package/dist/src/agent/workflow/catalog.js +159 -0
  145. package/dist/src/agent/workflow/catalog.js.map +1 -0
  146. package/dist/src/agent/workflow/channel-capability.d.ts +76 -0
  147. package/dist/src/agent/workflow/channel-capability.js +1 -0
  148. package/dist/src/agent/workflow/index.d.ts +11 -0
  149. package/dist/src/agent/workflow/index.js +10 -0
  150. package/dist/src/agent/workflow/last-run-memory.d.ts +42 -0
  151. package/dist/src/agent/workflow/last-run-memory.js +60 -0
  152. package/dist/src/agent/workflow/last-run-memory.js.map +1 -0
  153. package/dist/src/agent/workflow/parser.d.ts +20 -0
  154. package/dist/src/agent/workflow/parser.js +146 -0
  155. package/dist/src/agent/workflow/parser.js.map +1 -0
  156. package/dist/src/agent/workflow/progress-broker.d.ts +80 -0
  157. package/dist/src/agent/workflow/progress-broker.js +263 -0
  158. package/dist/src/agent/workflow/progress-broker.js.map +1 -0
  159. package/dist/src/agent/workflow/runtime.d.ts +31 -0
  160. package/dist/src/agent/workflow/runtime.js +301 -0
  161. package/dist/src/agent/workflow/runtime.js.map +1 -0
  162. package/dist/src/agent/workflow/snapshot.d.ts +18 -0
  163. package/dist/src/agent/workflow/snapshot.js +144 -0
  164. package/dist/src/agent/workflow/snapshot.js.map +1 -0
  165. package/dist/src/agent/workflow/structured-output-tool.d.ts +33 -0
  166. package/dist/src/agent/workflow/structured-output-tool.js +58 -0
  167. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -0
  168. package/dist/src/agent/workflow/subagent-runner.d.ts +42 -0
  169. package/dist/src/agent/workflow/subagent-runner.js +104 -0
  170. package/dist/src/agent/workflow/subagent-runner.js.map +1 -0
  171. package/dist/src/agent/workflow/types.d.ts +145 -0
  172. package/dist/src/agent/workflow/types.js +1 -0
  173. package/dist/src/auth/credentials.js +3 -3
  174. package/dist/src/auth/profiles/store.js +1 -1
  175. package/dist/src/auth/sync-provider-auth.js +1 -1
  176. package/dist/src/browser/cache-dir-policy.js +1 -1
  177. package/dist/src/browser/cdp-local-launcher.js +2 -2
  178. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  179. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  180. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  181. package/dist/src/browser/stealth.js +1 -1
  182. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  183. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  184. package/dist/src/channels/outbound/persist-store.js +1 -1
  185. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  186. package/dist/src/channels/pairing/pairing-store.js +2 -2
  187. package/dist/src/chat-commands/builtins/config.js +2 -2
  188. package/dist/src/chat-commands/builtins/model.js +40 -23
  189. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  190. package/dist/src/chat-commands/builtins/system.js +30 -15
  191. package/dist/src/chat-commands/builtins/system.js.map +1 -1
  192. package/dist/src/chat-commands/builtins/workflow.d.ts +18 -0
  193. package/dist/src/chat-commands/builtins/workflow.js +172 -0
  194. package/dist/src/chat-commands/builtins/workflow.js.map +1 -0
  195. package/dist/src/chat-commands/context.js +1 -1
  196. package/dist/src/chat-commands/format-output.d.ts +28 -0
  197. package/dist/src/chat-commands/format-output.js +45 -0
  198. package/dist/src/chat-commands/format-output.js.map +1 -0
  199. package/dist/src/chat-commands/index.d.ts +1 -0
  200. package/dist/src/chat-commands/index.js +3 -1
  201. package/dist/src/chat-commands/index.js.map +1 -1
  202. package/dist/src/cli/commands/config.js +2 -2
  203. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  204. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  205. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  206. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  207. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  208. package/dist/src/cli/commands/extension-dev.js +1 -1
  209. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  210. package/dist/src/cli/commands/extension-pack.js +1 -1
  211. package/dist/src/cli/commands/gateway/lifecycle.js +10 -4
  212. package/dist/src/cli/commands/gateway/lifecycle.js.map +1 -1
  213. package/dist/src/cli/commands/gateway/shared.js +1 -1
  214. package/dist/src/cli/commands/image.js +1 -1
  215. package/dist/src/cli/commands/init.js +4 -4
  216. package/dist/src/cli/commands/onboard.js +2 -2
  217. package/dist/src/cli/commands/tunnel.js +2 -2
  218. package/dist/src/cli/utils/gateway-client.js +1 -1
  219. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  220. package/dist/src/config/agent-profile.js +1 -1
  221. package/dist/src/config/gateway-bind.js +1 -1
  222. package/dist/src/config/index.js +5 -5
  223. package/dist/src/config/loader.js +2 -2
  224. package/dist/src/config/models-json.js +2 -2
  225. package/dist/src/config/paths-state.js +1 -1
  226. package/dist/src/config/profile.js +2 -2
  227. package/dist/src/config/public-url.d.ts +28 -0
  228. package/dist/src/config/public-url.js +103 -0
  229. package/dist/src/config/public-url.js.map +1 -0
  230. package/dist/src/config/schema.d.ts +82 -0
  231. package/dist/src/config/schema.js +130 -1
  232. package/dist/src/config/schema.js.map +1 -1
  233. package/dist/src/config/workspace-path.js +1 -1
  234. package/dist/src/cron/executor.js +2 -2
  235. package/dist/src/cron/persistence.js +1 -1
  236. package/dist/src/cron/run-log-store.js +1 -1
  237. package/dist/src/daemon/constants.js +1 -1
  238. package/dist/src/daemon/install-plan.js +3 -3
  239. package/dist/src/daemon/install-plan.js.map +1 -1
  240. package/dist/src/daemon/launchd.js +2 -2
  241. package/dist/src/daemon/schtasks.js +38 -1
  242. package/dist/src/daemon/schtasks.js.map +1 -1
  243. package/dist/src/daemon/systemd.js +2 -2
  244. package/dist/src/extensions/bundle-mcp.js +1 -1
  245. package/dist/src/extensions/discover-extensions.js +1 -1
  246. package/dist/src/extensions/health.js +1 -1
  247. package/dist/src/extensions/loader.js +1 -1
  248. package/dist/src/extensions/lockfile.js +2 -2
  249. package/dist/src/gateway/agents-admin.js +2 -2
  250. package/dist/src/gateway/file-path-classifier.js +2 -2
  251. package/dist/src/gateway/heartbeat/service.js +1 -1
  252. package/dist/src/gateway/hono/app.js +33 -2
  253. package/dist/src/gateway/hono/app.js.map +1 -1
  254. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  255. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  256. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  257. package/dist/src/gateway/hono/oauth.js +1 -1
  258. package/dist/src/gateway/hono/routes/agents.js +1 -1
  259. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  260. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  261. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  262. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  263. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  264. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  265. package/dist/src/gateway/hono/routes/models.js +1 -1
  266. package/dist/src/gateway/hono/routes/shares.js +631 -34
  267. package/dist/src/gateway/hono/routes/shares.js.map +1 -1
  268. package/dist/src/gateway/hono/routes/site-shares.d.ts +3 -0
  269. package/dist/src/gateway/hono/routes/site-shares.js +228 -0
  270. package/dist/src/gateway/hono/routes/site-shares.js.map +1 -0
  271. package/dist/src/gateway/hono/routes/tunnel.js +97 -8
  272. package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
  273. package/dist/src/gateway/hono/routes/workspace.js +5 -5
  274. package/dist/src/gateway/hono/sse.js +2 -2
  275. package/dist/src/gateway/host.d.ts +3 -1
  276. package/dist/src/gateway/host.js +3 -1
  277. package/dist/src/gateway/host.js.map +1 -1
  278. package/dist/src/gateway/lock.js +3 -3
  279. package/dist/src/gateway/ports.d.ts +6 -0
  280. package/dist/src/gateway/ports.js +38 -2
  281. package/dist/src/gateway/ports.js.map +1 -1
  282. package/dist/src/gateway/public-url.d.ts +8 -0
  283. package/dist/src/gateway/public-url.js +10 -0
  284. package/dist/src/gateway/public-url.js.map +1 -0
  285. package/dist/src/gateway/security/origin-check.d.ts +9 -1
  286. package/dist/src/gateway/security/origin-check.js +4 -0
  287. package/dist/src/gateway/security/origin-check.js.map +1 -1
  288. package/dist/src/gateway/server.js +15 -0
  289. package/dist/src/gateway/server.js.map +1 -1
  290. package/dist/src/gateway/service/agent-runner.js +2 -2
  291. package/dist/src/gateway/service/marketplace-service.js +2 -2
  292. package/dist/src/gateway/service/run-gateway-agent.js +2 -2
  293. package/dist/src/gateway/service.js +3 -2
  294. package/dist/src/gateway/service.js.map +1 -1
  295. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  296. package/dist/src/heartbeat/index.js +1 -1
  297. package/dist/src/i18n/goals-bundle.js +1 -1
  298. package/dist/src/i18n/index.d.ts +1 -0
  299. package/dist/src/i18n/index.js +2 -1
  300. package/dist/src/i18n/locales/share-tool.en.js +15 -0
  301. package/dist/src/i18n/locales/share-tool.en.js.map +1 -0
  302. package/dist/src/i18n/locales/share-tool.zh.js +15 -0
  303. package/dist/src/i18n/locales/share-tool.zh.js.map +1 -0
  304. package/dist/src/i18n/share-tool-bundle.d.ts +20 -0
  305. package/dist/src/i18n/share-tool-bundle.js +56 -0
  306. package/dist/src/i18n/share-tool-bundle.js.map +1 -0
  307. package/dist/src/infra/gateway-processes.js +1 -0
  308. package/dist/src/infra/gateway-processes.js.map +1 -1
  309. package/dist/src/infra/restart.js +2 -2
  310. package/dist/src/infra/update-check.js +1 -1
  311. package/dist/src/infra/update-lock.js +3 -3
  312. package/dist/src/infra/update-runner.js +1 -1
  313. package/dist/src/infra/update-startup.js +2 -2
  314. package/dist/src/infra/write-file-atomic.js +2 -2
  315. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  316. package/dist/src/providers/index.js +2 -2
  317. package/dist/src/providers/model-registry.js +1 -1
  318. package/dist/src/session/config-store.js +2 -2
  319. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  320. package/dist/src/session/parity/sessions-json-file.js +1 -1
  321. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  322. package/dist/src/session/parity/transcript-paths.js +1 -1
  323. package/dist/src/session/search-index-cache.js +1 -1
  324. package/dist/src/session/search-index.js +1 -1
  325. package/dist/src/session/session-title.js +3 -2
  326. package/dist/src/session/session-title.js.map +1 -1
  327. package/dist/src/session/store.js +5 -5
  328. package/dist/src/share/share-auto.d.ts +74 -0
  329. package/dist/src/share/share-auto.js +247 -0
  330. package/dist/src/share/share-auto.js.map +1 -0
  331. package/dist/src/share/share-config.js +63 -4
  332. package/dist/src/share/share-config.js.map +1 -1
  333. package/dist/src/share/share-landing.d.ts +28 -2
  334. package/dist/src/share/share-landing.js +155 -34
  335. package/dist/src/share/share-landing.js.map +1 -1
  336. package/dist/src/share/share-store.d.ts +48 -4
  337. package/dist/src/share/share-store.js +322 -51
  338. package/dist/src/share/share-store.js.map +1 -1
  339. package/dist/src/share/share-thumbnail.d.ts +35 -0
  340. package/dist/src/share/share-thumbnail.js +277 -0
  341. package/dist/src/share/share-thumbnail.js.map +1 -0
  342. package/dist/src/share/share-types.d.ts +68 -10
  343. package/dist/src/share/share-types.js +18 -1
  344. package/dist/src/share/share-types.js.map +1 -1
  345. package/dist/src/share/share-url.js +1 -1
  346. package/dist/src/share/share-zip.d.ts +35 -0
  347. package/dist/src/share/share-zip.js +303 -0
  348. package/dist/src/share/share-zip.js.map +1 -0
  349. package/dist/src/share/site-proxy.d.ts +35 -0
  350. package/dist/src/share/site-proxy.js +234 -0
  351. package/dist/src/share/site-proxy.js.map +1 -0
  352. package/dist/src/share/site-share-config.d.ts +11 -0
  353. package/dist/src/share/site-share-config.js +103 -0
  354. package/dist/src/share/site-share-config.js.map +1 -0
  355. package/dist/src/share/site-share-router.d.ts +23 -0
  356. package/dist/src/share/site-share-router.js +147 -0
  357. package/dist/src/share/site-share-router.js.map +1 -0
  358. package/dist/src/share/site-share-store.d.ts +53 -0
  359. package/dist/src/share/site-share-store.js +400 -0
  360. package/dist/src/share/site-share-store.js.map +1 -0
  361. package/dist/src/share/site-share-types.d.ts +103 -0
  362. package/dist/src/share/site-share-types.js +41 -0
  363. package/dist/src/share/site-share-types.js.map +1 -0
  364. package/dist/src/share/site-static-serve.d.ts +10 -0
  365. package/dist/src/share/site-static-serve.js +145 -0
  366. package/dist/src/share/site-static-serve.js.map +1 -0
  367. package/dist/src/tui/clipboard-image.js +3 -3
  368. package/dist/src/tui/theme-manager.js +1 -1
  369. package/dist/src/tui/tui-commands.js +18 -0
  370. package/dist/src/tui/tui-commands.js.map +1 -1
  371. package/dist/src/tui/tui-keybindings-file.js +1 -1
  372. package/dist/src/tui/tui-scoped-models.js +2 -2
  373. package/dist/src/tui/tui-settings.js +1 -1
  374. package/dist/src/tui/tui-workflow-slash.d.ts +32 -0
  375. package/dist/src/tui/tui-workflow-slash.js +63 -0
  376. package/dist/src/tui/tui-workflow-slash.js.map +1 -0
  377. package/dist/src/tui/tui.js +2 -2
  378. package/dist/src/tunnel/enable-lan-pairing.js +1 -1
  379. package/dist/src/tunnel/frpc-binary.js +3 -3
  380. package/dist/src/tunnel/frpc-config.js +1 -1
  381. package/dist/src/tunnel/frpc-extract.js +1 -1
  382. package/dist/src/tunnel/index.js +2 -2
  383. package/dist/src/tunnel/pair-context.d.ts +7 -1
  384. package/dist/src/tunnel/pair-context.js +25 -9
  385. package/dist/src/tunnel/pair-context.js.map +1 -1
  386. package/dist/src/tunnel/pair-url.d.ts +14 -1
  387. package/dist/src/tunnel/pair-url.js +14 -1
  388. package/dist/src/tunnel/pair-url.js.map +1 -1
  389. package/dist/src/tunnel/tunnel-service.js +2 -2
  390. package/dist/src/tunnel/tunnel-state.js +1 -1
  391. package/dist/src/utils/logger/audit.js +1 -1
  392. package/dist/src/utils/logger/log-store.js +1 -1
  393. package/dist/src/utils/logger/rotation.js +1 -1
  394. package/dist/src/voice/tts/audio.js +1 -1
  395. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  396. package/package.json +3 -2
  397. package/dist/gateway/static/root/assets/agents-tR-nNP04.js +0 -222
  398. package/dist/gateway/static/root/assets/apps-page-BDw6SP-d.js +0 -1
  399. package/dist/gateway/static/root/assets/button-KafIU8dx.js +0 -1
  400. package/dist/gateway/static/root/assets/channels-settings-DEFd-jj1.js +0 -1
  401. package/dist/gateway/static/root/assets/channels-status-swr-DI5FHdGe.js +0 -8
  402. package/dist/gateway/static/root/assets/cron-api-BSqY8LwW.js +0 -1
  403. package/dist/gateway/static/root/assets/cron-page-D7lVDjcR.js +0 -1
  404. package/dist/gateway/static/root/assets/dist-C57OMHW8.js +0 -48
  405. package/dist/gateway/static/root/assets/extension-page-CQo2Xsmg.js +0 -1
  406. package/dist/gateway/static/root/assets/extension-settings-page-CZf0WoZg.js +0 -1
  407. package/dist/gateway/static/root/assets/fetch-2iRFmd3n.js +0 -3
  408. package/dist/gateway/static/root/assets/heartbeat-config-api-B0drdQEJ.js +0 -1
  409. package/dist/gateway/static/root/assets/index-0Gt3TG4j.js +0 -4693
  410. package/dist/gateway/static/root/assets/index-BuFldCsB.css +0 -1
  411. package/dist/gateway/static/root/assets/logs-page-DMuORLfC.js +0 -1
  412. package/dist/gateway/static/root/assets/sessions-page-_UO8g6NN.js +0 -1
  413. package/dist/gateway/static/root/assets/settings-form-section-DkmHkknc.js +0 -1
  414. package/dist/gateway/static/root/assets/settings-page-Cz8FoW_A.js +0 -3
  415. package/dist/gateway/static/root/assets/skills-page-HrUOxF7H.js +0 -2
  416. package/dist/gateway/static/root/assets/theme-store-D01dJt95.js +0 -1
  417. package/dist/gateway/static/root/assets/utils-BFwcR6pL.js +0 -1
  418. package/dist/gateway/static/root/assets/voice-api-key-field-JF8-aqc5.js +0 -1
@@ -0,0 +1,3 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{a as t}from"./vendor-react-BOUWij0V.js";var n=e(t(),1),r=e=>typeof e==`string`,i=()=>{let e,t,n=new Promise((n,r)=>{e=n,t=r});return n.resolve=e,n.reject=t,n},a=e=>e==null?``:String(e),o=(e,t,n)=>{e.forEach(e=>{t[e]&&(n[e]=t[e])})},s=/###/g,c=e=>e&&e.includes(`###`)?e.replace(s,`.`):e,l=e=>!e||r(e),u=(e,t,n)=>{let i=r(t)?t.split(`.`):t,a=0;for(;a<i.length-1;){if(l(e))return{};let t=c(i[a]);!e[t]&&n&&(e[t]=new n),e=Object.prototype.hasOwnProperty.call(e,t)?e[t]:{},++a}return l(e)?{}:{obj:e,k:c(i[a])}},d=(e,t,n)=>{let{obj:r,k:i}=u(e,t,Object);if(r!==void 0||t.length===1){r[i]=n;return}let a=t[t.length-1],o=t.slice(0,t.length-1),s=u(e,o,Object);for(;s.obj===void 0&&o.length;)a=`${o[o.length-1]}.${a}`,o=o.slice(0,o.length-1),s=u(e,o,Object),s?.obj&&s.obj[`${s.k}.${a}`]!==void 0&&(s.obj=void 0);s.obj[`${s.k}.${a}`]=n},f=(e,t,n,r)=>{let{obj:i,k:a}=u(e,t,Object);i[a]=i[a]||[],i[a].push(n)},p=(e,t)=>{let{obj:n,k:r}=u(e,t);if(n&&Object.prototype.hasOwnProperty.call(n,r))return n[r]},m=(e,t,n)=>{let r=p(e,n);return r===void 0?p(t,n):r},h=(e,t,n)=>{for(let i in t)i!==`__proto__`&&i!==`constructor`&&(i in e?r(e[i])||e[i]instanceof String||r(t[i])||t[i]instanceof String?n&&(e[i]=t[i]):h(e[i],t[i],n):e[i]=t[i]);return e},g=e=>e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,`\\$&`),_={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`,"/":`&#x2F;`},v=e=>r(e)?e.replace(/[&<>"'\/]/g,e=>_[e]):e,y=class{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){let t=this.regExpMap.get(e);if(t!==void 0)return t;let n=new RegExp(e);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,n),this.regExpQueue.push(e),n}},b=[` `,`,`,`?`,`!`,`;`],x=new y(20),S=(e,t,n)=>{t||=``,n||=``;let r=b.filter(e=>!t.includes(e)&&!n.includes(e));if(r.length===0)return!0;let i=x.getRegExp(`(${r.map(e=>e===`?`?`\\?`:e).join(`|`)})`),a=!i.test(e);if(!a){let t=e.indexOf(n);t>0&&!i.test(e.substring(0,t))&&(a=!0)}return a},C=(e,t,n=`.`)=>{if(!e)return;if(e[t])return Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0;let r=t.split(n),i=e;for(let e=0;e<r.length;){if(!i||typeof i!=`object`)return;let t,a=``;for(let o=e;o<r.length;++o)if(o!==e&&(a+=n),a+=r[o],t=i[a],t!==void 0){if([`string`,`number`,`boolean`].includes(typeof t)&&o<r.length-1)continue;e+=o-e+1;break}i=t}return i},w=e=>e?.replace(/_/g,`-`),T={type:`logger`,log(e){this.output(`log`,e)},warn(e){this.output(`warn`,e)},error(e){this.output(`error`,e)},output(e,t){console?.[e]?.apply?.(console,t)}},E=new class e{constructor(e,t={}){this.init(e,t)}init(e,t={}){this.prefix=t.prefix||`i18next:`,this.logger=e||T,this.options=t,this.debug=t.debug}log(...e){return this.forward(e,`log`,``,!0)}warn(...e){return this.forward(e,`warn`,``,!0)}error(...e){return this.forward(e,`error`,``)}deprecate(...e){return this.forward(e,`warn`,`WARNING DEPRECATED: `,!0)}forward(e,t,n,i){return i&&!this.debug?null:(e=e.map(e=>r(e)?e.replace(/[\r\n\x00-\x1F\x7F]/g,` `):e),r(e[0])&&(e[0]=`${n}${this.prefix} ${e[0]}`),this.logger[t](e))}create(t){return new e(this.logger,{prefix:`${this.prefix}:${t}:`,...this.options})}clone(t){return t||=this.options,t.prefix=t.prefix||this.prefix,new e(this.logger,t)}},D=class{constructor(){this.observers={}}on(e,t){return e.split(` `).forEach(e=>{this.observers[e]||(this.observers[e]=new Map);let n=this.observers[e].get(t)||0;this.observers[e].set(t,n+1)}),this}off(e,t){if(this.observers[e]){if(!t){delete this.observers[e];return}this.observers[e].delete(t)}}once(e,t){let n=(...r)=>{t(...r),this.off(e,n)};return this.on(e,n),this}emit(e,...t){this.observers[e]&&Array.from(this.observers[e].entries()).forEach(([e,n])=>{for(let r=0;r<n;r++)e(...t)}),this.observers[`*`]&&Array.from(this.observers[`*`].entries()).forEach(([n,r])=>{for(let i=0;i<r;i++)n(e,...t)})}},O=class extends D{constructor(e,t={ns:[`translation`],defaultNS:`translation`}){super(),this.data=e||{},this.options=t,this.options.keySeparator===void 0&&(this.options.keySeparator=`.`),this.options.ignoreJSONStructure===void 0&&(this.options.ignoreJSONStructure=!0)}addNamespaces(e){this.options.ns.includes(e)||this.options.ns.push(e)}removeNamespaces(e){let t=this.options.ns.indexOf(e);t>-1&&this.options.ns.splice(t,1)}getResource(e,t,n,i={}){let a=i.keySeparator===void 0?this.options.keySeparator:i.keySeparator,o=i.ignoreJSONStructure===void 0?this.options.ignoreJSONStructure:i.ignoreJSONStructure,s;e.includes(`.`)?s=e.split(`.`):(s=[e,t],n&&(Array.isArray(n)?s.push(...n):r(n)&&a?s.push(...n.split(a)):s.push(n)));let c=p(this.data,s);return!c&&!t&&!n&&e.includes(`.`)&&(e=s[0],t=s[1],n=s.slice(2).join(`.`)),c||!o||!r(n)?c:C(this.data?.[e]?.[t],n,a)}addResource(e,t,n,r,i={silent:!1}){let a=i.keySeparator===void 0?this.options.keySeparator:i.keySeparator,o=[e,t];n&&(o=o.concat(a?n.split(a):n)),e.includes(`.`)&&(o=e.split(`.`),r=t,t=o[1]),this.addNamespaces(t),d(this.data,o,r),i.silent||this.emit(`added`,e,t,n,r)}addResources(e,t,n,i={silent:!1}){for(let i in n)(r(n[i])||Array.isArray(n[i]))&&this.addResource(e,t,i,n[i],{silent:!0});i.silent||this.emit(`added`,e,t,n)}addResourceBundle(e,t,n,r,i,a={silent:!1,skipCopy:!1}){let o=[e,t];e.includes(`.`)&&(o=e.split(`.`),r=n,n=t,t=o[1]),this.addNamespaces(t);let s=p(this.data,o)||{};a.skipCopy||(n=JSON.parse(JSON.stringify(n))),r?h(s,n,i):s={...s,...n},d(this.data,o,s),a.silent||this.emit(`added`,e,t,n)}removeResourceBundle(e,t){this.hasResourceBundle(e,t)&&delete this.data[e][t],this.removeNamespaces(t),this.emit(`removed`,e,t)}hasResourceBundle(e,t){return this.getResource(e,t)!==void 0}getResourceBundle(e,t){return t||=this.options.defaultNS,this.getResource(e,t)}getDataByLanguage(e){return this.data[e]}hasLanguageSomeTranslations(e){let t=this.getDataByLanguage(e);return!!(t&&Object.keys(t)||[]).find(e=>t[e]&&Object.keys(t[e]).length>0)}toJSON(){return this.data}},k={processors:{},addPostProcessor(e){this.processors[e.name]=e},handle(e,t,n,r,i){return e.forEach(e=>{t=this.processors[e]?.process(t,n,r,i)??t}),t}},A=Symbol(`i18next/PATH_KEY`);function ee(){let e=[],t=Object.create(null),n;return t.get=(r,i)=>(n?.revoke?.(),i===A?e:(e.push(i),n=Proxy.revocable(r,t),n.proxy)),Proxy.revocable(Object.create(null),t).proxy}function j(e,t){let{[A]:n}=e(ee()),r=t?.keySeparator??`.`,i=t?.nsSeparator??`:`,a=t?.enableSelector===`strict`;if(n.length>1&&i){let e=t?.ns,o=a?Array.isArray(e)?e:e?[e]:null:Array.isArray(e)?e:null;if(o&&(a?o:o.length>1?o.slice(1):[]).includes(n[0]))return`${n[0]}${i}${n.slice(1).join(r)}`}return n.join(r)}var M=e=>!r(e)&&typeof e!=`boolean`&&typeof e!=`number`,N=class e extends D{constructor(e,t={}){super(),o([`resourceStore`,`languageUtils`,`pluralResolver`,`interpolator`,`backendConnector`,`i18nFormat`,`utils`],e,this),this.options=t,this.options.keySeparator===void 0&&(this.options.keySeparator=`.`),this.logger=E.create(`translator`),this.checkedLoadedFor={}}changeLanguage(e){e&&(this.language=e)}exists(e,t={interpolation:{}}){let n={...t};if(e==null)return!1;let r=this.resolve(e,n);if(r?.res===void 0)return!1;let i=M(r.res);return!(n.returnObjects===!1&&i)}extractFromKey(e,t){let n=t.nsSeparator===void 0?this.options.nsSeparator:t.nsSeparator;n===void 0&&(n=`:`);let i=t.keySeparator===void 0?this.options.keySeparator:t.keySeparator,a=t.ns||this.options.defaultNS||[],o=n&&e.includes(n),s=!this.options.userDefinedKeySeparator&&!t.keySeparator&&!this.options.userDefinedNsSeparator&&!t.nsSeparator&&!S(e,n,i);if(o&&!s){let t=e.match(this.interpolator.nestingRegexp);if(t&&t.length>0)return{key:e,namespaces:r(a)?[a]:a};let o=e.split(n);(n!==i||n===i&&this.options.ns.includes(o[0]))&&(a=o.shift()),e=o.join(i)}return{key:e,namespaces:r(a)?[a]:a}}translate(t,n,i){let a=typeof n==`object`?{...n}:n;if(typeof a!=`object`&&this.options.overloadTranslationOptionHandler&&(a=this.options.overloadTranslationOptionHandler(arguments)),typeof a==`object`&&(a={...a}),a||={},t==null)return``;typeof t==`function`&&(t=j(t,{...this.options,...a})),Array.isArray(t)||(t=[String(t)]),t=t.map(e=>typeof e==`function`?j(e,{...this.options,...a}):String(e));let o=a.returnDetails===void 0?this.options.returnDetails:a.returnDetails,s=a.keySeparator===void 0?this.options.keySeparator:a.keySeparator,{key:c,namespaces:l}=this.extractFromKey(t[t.length-1],a),u=l[l.length-1],d=a.nsSeparator===void 0?this.options.nsSeparator:a.nsSeparator;d===void 0&&(d=`:`);let f=a.lng||this.language,p=a.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(f?.toLowerCase()===`cimode`)return p?o?{res:`${u}${d}${c}`,usedKey:c,exactUsedKey:c,usedLng:f,usedNS:u,usedParams:this.getUsedParamsDetails(a)}:`${u}${d}${c}`:o?{res:c,usedKey:c,exactUsedKey:c,usedLng:f,usedNS:u,usedParams:this.getUsedParamsDetails(a)}:c;let m=this.resolve(t,a),h=m?.res,g=m?.usedKey||c,_=m?.exactUsedKey||c,v=[`[object Number]`,`[object Function]`,`[object RegExp]`],y=a.joinArrays===void 0?this.options.joinArrays:a.joinArrays,b=!this.i18nFormat||this.i18nFormat.handleAsObject,x=a.count!==void 0&&!r(a.count),S=e.hasDefaultValue(a),C=x?this.pluralResolver.getSuffix(f,a.count,a):``,w=a.ordinal&&x?this.pluralResolver.getSuffix(f,a.count,{ordinal:!1}):``,T=x&&!a.ordinal&&a.count===0,E=T&&a[`defaultValue${this.options.pluralSeparator}zero`]||a[`defaultValue${C}`]||a[`defaultValue${w}`]||a.defaultValue,D=h;b&&!h&&S&&(D=E);let O=M(D),k=Object.prototype.toString.apply(D);if(b&&D&&O&&!v.includes(k)&&!(r(y)&&Array.isArray(D))){if(!a.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn(`accessing an object - but returnObjects options is not enabled!`);let e=this.options.returnedObjectHandler?this.options.returnedObjectHandler(g,D,{...a,ns:l}):`key '${c} (${this.language})' returned an object instead of string.`;return o?(m.res=e,m.usedParams=this.getUsedParamsDetails(a),m):e}if(s){let e=Array.isArray(D),t=e?[]:{},n=e?_:g;for(let e in D)if(Object.prototype.hasOwnProperty.call(D,e)){let r=`${n}${s}${e}`;S&&!h?t[e]=this.translate(r,{...a,defaultValue:M(E)?E[e]:void 0,joinArrays:!1,ns:l}):t[e]=this.translate(r,{...a,joinArrays:!1,ns:l}),t[e]===r&&(t[e]=D[e])}h=t}}else if(b&&r(y)&&Array.isArray(h))h=h.join(y),h&&=this.extendTranslation(h,t,a,i);else{let e=!1,n=!1;!this.isValidLookup(h)&&S&&(e=!0,h=E),this.isValidLookup(h)||(n=!0,h=c);let r=(a.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&n?void 0:h,o=S&&E!==h&&this.options.updateMissing;if(n||e||o){if(this.logger.log(o?`updateKey`:`missingKey`,f,u,x&&!o?`${c}${this.pluralResolver.getSuffix(f,a.count,a)}`:c,o?E:h),s){let e=this.resolve(c,{...a,keySeparator:!1});e&&e.res&&this.logger.warn(`Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.`)}let e=[],t=this.languageUtils.getFallbackCodes(this.options.fallbackLng,a.lng||this.language);if(this.options.saveMissingTo===`fallback`&&t&&t[0])for(let n=0;n<t.length;n++)e.push(t[n]);else this.options.saveMissingTo===`all`?e=this.languageUtils.toResolveHierarchy(a.lng||this.language):e.push(a.lng||this.language);let n=(e,t,n)=>{let i=S&&n!==h?n:r;this.options.missingKeyHandler?this.options.missingKeyHandler(e,u,t,i,o,a):this.backendConnector?.saveMissing&&this.backendConnector.saveMissing(e,u,t,i,o,a),this.emit(`missingKey`,e,u,t,h)};this.options.saveMissing&&(this.options.saveMissingPlurals&&x?e.forEach(e=>{let t=this.pluralResolver.getSuffixes(e,a);T&&a[`defaultValue${this.options.pluralSeparator}zero`]&&!t.includes(`${this.options.pluralSeparator}zero`)&&t.push(`${this.options.pluralSeparator}zero`),t.forEach(t=>{n([e],c+t,a[`defaultValue${t}`]||E)})}):n(e,c,E))}h=this.extendTranslation(h,t,a,m,i),n&&h===c&&this.options.appendNamespaceToMissingKey&&(h=`${u}${d}${c}`),(n||e)&&this.options.parseMissingKeyHandler&&(h=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${u}${d}${c}`:c,e?h:void 0,a))}return o?(m.res=h,m.usedParams=this.getUsedParamsDetails(a),m):h}extendTranslation(e,t,n,i,a){if(this.i18nFormat?.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...n},n.lng||this.language||i.usedLng,i.usedNS,i.usedKey,{resolved:i});else if(!n.skipInterpolation){n.interpolation&&this.interpolator.init({...n,interpolation:{...this.options.interpolation,...n.interpolation}});let o=r(e)&&(n?.interpolation?.skipOnVariables===void 0?this.options.interpolation.skipOnVariables:n.interpolation.skipOnVariables),s;if(o){let t=e.match(this.interpolator.nestingRegexp);s=t&&t.length}let c=n.replace&&!r(n.replace)?n.replace:n;if(this.options.interpolation.defaultVariables&&(c={...this.options.interpolation.defaultVariables,...c}),e=this.interpolator.interpolate(e,c,n.lng||this.language||i.usedLng,n),o){let t=e.match(this.interpolator.nestingRegexp),r=t&&t.length;s<r&&(n.nest=!1)}!n.lng&&i&&i.res&&(n.lng=this.language||i.usedLng),n.nest!==!1&&(e=this.interpolator.nest(e,(...e)=>a?.[0]===e[0]&&!n.context?(this.logger.warn(`It seems you are nesting recursively key: ${e[0]} in key: ${t[0]}`),null):this.translate(...e,t),n)),n.interpolation&&this.interpolator.reset()}let o=n.postProcess||this.options.postProcess,s=r(o)?[o]:o;return e!=null&&s?.length&&n.applyPostProcessor!==!1&&(e=k.handle(s,e,t,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...i,usedParams:this.getUsedParamsDetails(n)},...n}:n,this)),e}resolve(e,t={}){let n,i,a,o,s;return r(e)&&(e=[e]),Array.isArray(e)&&(e=e.map(e=>typeof e==`function`?j(e,{...this.options,...t}):e)),e.forEach(e=>{if(this.isValidLookup(n))return;let c=this.extractFromKey(e,t),l=c.key;i=l;let u=c.namespaces;this.options.fallbackNS&&(u=u.concat(this.options.fallbackNS));let d=t.count!==void 0&&!r(t.count),f=d&&!t.ordinal&&t.count===0,p=t.context!==void 0&&(r(t.context)||typeof t.context==`number`)&&t.context!==``,m=t.lngs?t.lngs:this.languageUtils.toResolveHierarchy(t.lng||this.language,t.fallbackLng);u.forEach(e=>{this.isValidLookup(n)||(s=e,!this.checkedLoadedFor[`${m[0]}-${e}`]&&this.utils?.hasLoadedNamespace&&!this.utils?.hasLoadedNamespace(s)&&(this.checkedLoadedFor[`${m[0]}-${e}`]=!0,this.logger.warn(`key "${i}" for languages "${m.join(`, `)}" won't get resolved as namespace "${s}" was not yet loaded`,`This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!`)),m.forEach(r=>{if(this.isValidLookup(n))return;o=r;let i=[l];if(this.i18nFormat?.addLookupKeys)this.i18nFormat.addLookupKeys(i,l,r,e,t);else{let e;d&&(e=this.pluralResolver.getSuffix(r,t.count,t));let n=`${this.options.pluralSeparator}zero`,a=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(d&&(t.ordinal&&e.startsWith(a)&&i.push(l+e.replace(a,this.options.pluralSeparator)),i.push(l+e),f&&i.push(l+n)),p){let r=`${l}${this.options.contextSeparator||`_`}${t.context}`;i.push(r),d&&(t.ordinal&&e.startsWith(a)&&i.push(r+e.replace(a,this.options.pluralSeparator)),i.push(r+e),f&&i.push(r+n))}}let s;for(;s=i.pop();)this.isValidLookup(n)||(a=s,n=this.getResource(r,e,s,t))}))})}),{res:n,usedKey:i,exactUsedKey:a,usedLng:o,usedNS:s}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e===``)}getResource(e,t,n,r={}){return this.i18nFormat?.getResource?this.i18nFormat.getResource(e,t,n,r):this.resourceStore.getResource(e,t,n,r)}getUsedParamsDetails(e={}){let t=[`defaultValue`,`ordinal`,`context`,`replace`,`lng`,`lngs`,`fallbackLng`,`ns`,`keySeparator`,`nsSeparator`,`returnObjects`,`returnDetails`,`joinArrays`,`postProcess`,`interpolation`],n=e.replace&&!r(e.replace),i=n?e.replace:e;if(n&&e.count!==void 0&&(i.count=e.count),this.options.interpolation.defaultVariables&&(i={...this.options.interpolation.defaultVariables,...i}),!n){i={...i};for(let e of t)delete i[e]}return i}static hasDefaultValue(e){for(let t in e)if(Object.prototype.hasOwnProperty.call(e,t)&&t.startsWith(`defaultValue`)&&e[t]!==void 0)return!0;return!1}},P=class{constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=E.create(`languageUtils`)}getScriptPartFromCode(e){if(e=w(e),!e||!e.includes(`-`))return null;let t=e.split(`-`);return t.length===2||(t.pop(),t[t.length-1].toLowerCase()===`x`)?null:this.formatLanguageCode(t.join(`-`))}getLanguagePartFromCode(e){if(e=w(e),!e||!e.includes(`-`))return e;let t=e.split(`-`);return this.formatLanguageCode(t[0])}formatLanguageCode(e){if(r(e)&&e.includes(`-`)){let t;try{t=Intl.getCanonicalLocales(e)[0]}catch{}return t&&this.options.lowerCaseLng&&(t=t.toLowerCase()),t||(this.options.lowerCaseLng?e.toLowerCase():e)}return this.options.cleanCode||this.options.lowerCaseLng?e.toLowerCase():e}isSupportedCode(e){return(this.options.load===`languageOnly`||this.options.nonExplicitSupportedLngs)&&(e=this.getLanguagePartFromCode(e)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.includes(e)}getBestMatchFromCodes(e){if(!e)return null;let t;return e.forEach(e=>{if(t)return;let n=this.formatLanguageCode(e);(!this.options.supportedLngs||this.isSupportedCode(n))&&(t=n)}),!t&&this.options.supportedLngs&&e.forEach(e=>{if(t)return;let n=this.getScriptPartFromCode(e);if(this.isSupportedCode(n))return t=n;let r=this.getLanguagePartFromCode(e);if(this.isSupportedCode(r))return t=r;t=this.options.supportedLngs.find(e=>e===r?!0:!e.includes(`-`)&&!r.includes(`-`)?!1:!!(e.includes(`-`)&&!r.includes(`-`)&&e.slice(0,e.indexOf(`-`))===r||e.startsWith(r)&&r.length>1))}),t||=this.getFallbackCodes(this.options.fallbackLng)[0],t}getFallbackCodes(e,t){if(!e)return[];if(typeof e==`function`&&(e=e(t)),r(e)&&(e=[e]),Array.isArray(e))return e;if(!t)return e.default||[];let n=e[t];return n||=e[this.getScriptPartFromCode(t)],n||=e[this.formatLanguageCode(t)],n||=e[this.getLanguagePartFromCode(t)],n||=e.default,n||[]}toResolveHierarchy(e,t){let n=this.getFallbackCodes((t===!1?[]:t)||this.options.fallbackLng||[],e),i=[],a=e=>{e&&(this.isSupportedCode(e)?i.push(e):this.logger.warn(`rejecting language code not found in supportedLngs: ${e}`))};return r(e)&&(e.includes(`-`)||e.includes(`_`))?(this.options.load!==`languageOnly`&&a(this.formatLanguageCode(e)),this.options.load!==`languageOnly`&&this.options.load!==`currentOnly`&&a(this.getScriptPartFromCode(e)),this.options.load!==`currentOnly`&&a(this.getLanguagePartFromCode(e))):r(e)&&a(this.formatLanguageCode(e)),n.forEach(e=>{i.includes(e)||a(this.formatLanguageCode(e))}),i}},F={zero:0,one:1,two:2,few:3,many:4,other:5},I={select:e=>e===1?`one`:`other`,resolvedOptions:()=>({pluralCategories:[`one`,`other`]})},te=class{constructor(e,t={}){this.languageUtils=e,this.options=t,this.logger=E.create(`pluralResolver`),this.pluralRulesCache={}}clearCache(){this.pluralRulesCache={}}getRule(e,t={}){let n=w(e===`dev`?`en`:e),r=t.ordinal?`ordinal`:`cardinal`,i=JSON.stringify({cleanedCode:n,type:r});if(i in this.pluralRulesCache)return this.pluralRulesCache[i];let a;try{a=new Intl.PluralRules(n,{type:r})}catch{if(typeof Intl>`u`)return this.logger.error(`No Intl support, please use an Intl polyfill!`),I;if(!e.match(/-|_/))return I;let n=this.languageUtils.getLanguagePartFromCode(e);a=this.getRule(n,t)}return this.pluralRulesCache[i]=a,a}needsPlural(e,t={}){let n=this.getRule(e,t);return n||=this.getRule(`dev`,t),n?.resolvedOptions().pluralCategories.length>1}getPluralFormsOfKey(e,t,n={}){return this.getSuffixes(e,n).map(e=>`${t}${e}`)}getSuffixes(e,t={}){let n=this.getRule(e,t);return n||=this.getRule(`dev`,t),n?n.resolvedOptions().pluralCategories.sort((e,t)=>F[e]-F[t]).map(e=>`${this.options.prepend}${t.ordinal?`ordinal${this.options.prepend}`:``}${e}`):[]}getSuffix(e,t,n={}){let r=this.getRule(e,n);return r?`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:``}${r.select(t)}`:(this.logger.warn(`no plural rule found for: ${e}`),this.getSuffix(`dev`,t,n))}},ne=(e,t,n,i=`.`,a=!0)=>{let o=m(e,t,n);return!o&&a&&r(n)&&(o=C(e,n,i),o===void 0&&(o=C(t,n,i))),o},L=e=>e.replace(/\$/g,`$$$$`),R=class{constructor(e={}){this.logger=E.create(`interpolator`),this.options=e,this.format=e?.interpolation?.format||(e=>e),this.init(e)}init(e={}){e.interpolation||={escapeValue:!0};let{escape:t,escapeValue:n,useRawValueToEscape:r,prefix:i,prefixEscaped:a,suffix:o,suffixEscaped:s,formatSeparator:c,unescapeSuffix:l,unescapePrefix:u,nestingPrefix:d,nestingPrefixEscaped:f,nestingSuffix:p,nestingSuffixEscaped:m,nestingOptionsSeparator:h,maxReplaces:_,alwaysFormat:y}=e.interpolation;this.escape=t===void 0?v:t,this.escapeValue=n===void 0?!0:n,this.useRawValueToEscape=r===void 0?!1:r,this.prefix=i?g(i):a||`{{`,this.suffix=o?g(o):s||`}}`,this.formatSeparator=c||`,`,this.unescapePrefix=l?``:u?g(u):`-`,this.unescapeSuffix=this.unescapePrefix?``:l?g(l):``,this.nestingPrefix=d?g(d):f||g(`$t(`),this.nestingSuffix=p?g(p):m||g(`)`),this.nestingOptionsSeparator=h||`,`,this.maxReplaces=_||1e3,this.alwaysFormat=y===void 0?!1:y,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){let e=(e,t)=>e?.source===t?(e.lastIndex=0,e):new RegExp(t,`g`);this.regexp=e(this.regexp,`${this.prefix}(.+?)${this.suffix}`),this.regexpUnescape=e(this.regexpUnescape,`${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`),this.nestingRegexp=e(this.nestingRegexp,`${this.nestingPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${this.nestingSuffix}`)}interpolate(e,t,n,i){let o,s,c,l=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},u=e=>{if(!e.includes(this.formatSeparator)){let r=ne(t,l,e,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(r,void 0,n,{...i,...t,interpolationkey:e}):r}let r=e.split(this.formatSeparator),a=r.shift().trim(),o=r.join(this.formatSeparator).trim();return this.format(ne(t,l,a,this.options.keySeparator,this.options.ignoreJSONStructure),o,n,{...i,...t,interpolationkey:a})};this.resetRegExp(),!this.escapeValue&&typeof e==`string`&&/\$t\([^)]*\{[^}]*\{\{/.test(e)&&this.logger.warn(`nesting options string contains interpolated variables with escapeValue: false — if any of those values are attacker-controlled they can inject additional nesting options (e.g. redirect lng/ns). Sanitise untrusted input before passing it to t(), or keep escapeValue: true.`);let d=i?.missingInterpolationHandler||this.options.missingInterpolationHandler,f=i?.interpolation?.skipOnVariables===void 0?this.options.interpolation.skipOnVariables:i.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:e=>L(e)},{regex:this.regexp,safeValue:e=>this.escapeValue?L(this.escape(e)):L(e)}].forEach(t=>{for(c=0;o=t.regex.exec(e);){let n=o[1].trim();if(s=u(n),s===void 0)if(typeof d==`function`){let t=d(e,o,i);s=r(t)?t:``}else if(i&&Object.prototype.hasOwnProperty.call(i,n))s=``;else if(f){s=o[0];continue}else this.logger.warn(`missed to pass in variable ${n} for interpolating ${e}`),s=``;else !r(s)&&!this.useRawValueToEscape&&(s=a(s));let l=t.safeValue(s);if(e=e.replace(o[0],l),f?(t.regex.lastIndex+=s.length,t.regex.lastIndex-=o[0].length):t.regex.lastIndex=0,c++,c>=this.maxReplaces)break}}),e}nest(e,t,n={}){let i,o,s,c=(e,t)=>{let n=this.nestingOptionsSeparator;if(!e.includes(n))return e;let r=e.split(RegExp(`${g(n)}[ ]*{`)),i=`{${r[1]}`;e=r[0],i=this.interpolate(i,s);let a=i.match(/'/g),o=i.match(/"/g);((a?.length??0)%2==0&&!o||(o?.length??0)%2!=0)&&(i=i.replace(/'/g,`"`));try{s=JSON.parse(i),t&&(s={...t,...s})}catch(t){return this.logger.warn(`failed parsing options string in nesting for key ${e}`,t),`${e}${n}${i}`}return s.defaultValue&&s.defaultValue.includes(this.prefix)&&delete s.defaultValue,e};for(;i=this.nestingRegexp.exec(e);){let l=[];s={...n},s=s.replace&&!r(s.replace)?s.replace:s,s.applyPostProcessor=!1,delete s.defaultValue;let u=/{.*}/.test(i[1])?i[1].lastIndexOf(`}`)+1:i[1].indexOf(this.formatSeparator);if(u!==-1&&(l=i[1].slice(u).split(this.formatSeparator).map(e=>e.trim()).filter(Boolean),i[1]=i[1].slice(0,u)),o=t(c.call(this,i[1].trim(),s),s),o&&i[0]===e&&!r(o))return o;r(o)||(o=a(o)),o||=(this.logger.warn(`missed to resolve ${i[1]} for nesting ${e}`),``),l.length&&(o=l.reduce((e,t)=>this.format(e,t,n.lng,{...n,interpolationkey:i[1].trim()}),o.trim())),e=e.replace(i[0],o),this.regexp.lastIndex=0}return e}},re=e=>{let t=e.toLowerCase().trim(),n={};if(e.includes(`(`)){let r=e.split(`(`);t=r[0].toLowerCase().trim();let i=r[1].slice(0,-1);t===`currency`&&!i.includes(`:`)?n.currency||=i.trim():t===`relativetime`&&!i.includes(`:`)?n.range||=i.trim():i.split(`;`).forEach(e=>{if(e){let[t,...r]=e.split(`:`),i=r.join(`:`).trim().replace(/^'+|'+$/g,``),a=t.trim();n[a]||(n[a]=i),i===`false`&&(n[a]=!1),i===`true`&&(n[a]=!0),isNaN(i)||(n[a]=parseInt(i,10))}})}return{formatName:t,formatOptions:n}},z=e=>{let t={};return(n,r,i)=>{let a=i;i&&i.interpolationkey&&i.formatParams&&i.formatParams[i.interpolationkey]&&i[i.interpolationkey]&&(a={...a,[i.interpolationkey]:void 0});let o=r+JSON.stringify(a),s=t[o];return s||(s=e(w(r),i),t[o]=s),s(n)}},ie=e=>(t,n,r)=>e(w(n),r)(t),ae=class{constructor(e={}){this.logger=E.create(`formatter`),this.options=e,this.init(e)}init(e,t={interpolation:{}}){this.formatSeparator=t.interpolation.formatSeparator||`,`;let n=t.cacheInBuiltFormats?z:ie;this.formats={number:n((e,t)=>{let n=new Intl.NumberFormat(e,{...t});return e=>n.format(e)}),currency:n((e,t)=>{let n=new Intl.NumberFormat(e,{...t,style:`currency`});return e=>n.format(e)}),datetime:n((e,t)=>{let n=new Intl.DateTimeFormat(e,{...t});return e=>n.format(e)}),relativetime:n((e,t)=>{let n=new Intl.RelativeTimeFormat(e,{...t});return e=>n.format(e,t.range||`day`)}),list:n((e,t)=>{let n=new Intl.ListFormat(e,{...t});return e=>n.format(e)})}}add(e,t){this.formats[e.toLowerCase().trim()]=t}addCached(e,t){this.formats[e.toLowerCase().trim()]=z(t)}format(e,t,n,r={}){if(!t||e==null)return e;let i=t.split(this.formatSeparator);if(i.length>1&&i[0].indexOf(`(`)>1&&!i[0].includes(`)`)&&i.find(e=>e.includes(`)`))){let e=i.findIndex(e=>e.includes(`)`));i[0]=[i[0],...i.splice(1,e)].join(this.formatSeparator)}return i.reduce((e,t)=>{let{formatName:i,formatOptions:a}=re(t);if(this.formats[i]){let t=e;try{let o=r?.formatParams?.[r.interpolationkey]||{},s=o.locale||o.lng||r.locale||r.lng||n;t=this.formats[i](e,s,{...a,...r,...o})}catch(e){this.logger.warn(e)}return t}else this.logger.warn(`there was no format function for ${i}`);return e},e)}},oe=(e,t)=>{e.pending[t]!==void 0&&(delete e.pending[t],e.pendingCount--)},se=class extends D{constructor(e,t,n,r={}){super(),this.backend=e,this.store=t,this.services=n,this.languageUtils=n.languageUtils,this.options=r,this.logger=E.create(`backendConnector`),this.waitingReads=[],this.maxParallelReads=r.maxParallelReads||10,this.readingCalls=0,this.maxRetries=r.maxRetries>=0?r.maxRetries:5,this.retryTimeout=r.retryTimeout>=1?r.retryTimeout:350,this.state={},this.queue=[],this.backend?.init?.(n,r.backend,r)}queueLoad(e,t,n,r){let i={},a={},o={},s={};return e.forEach(e=>{let r=!0;t.forEach(t=>{let o=`${e}|${t}`;!n.reload&&this.store.hasResourceBundle(e,t)?this.state[o]=2:this.state[o]<0||(this.state[o]===1?a[o]===void 0&&(a[o]=!0):(this.state[o]=1,r=!1,a[o]===void 0&&(a[o]=!0),i[o]===void 0&&(i[o]=!0),s[t]===void 0&&(s[t]=!0)))}),r||(o[e]=!0)}),(Object.keys(i).length||Object.keys(a).length)&&this.queue.push({pending:a,pendingCount:Object.keys(a).length,loaded:{},errors:[],callback:r}),{toLoad:Object.keys(i),pending:Object.keys(a),toLoadLanguages:Object.keys(o),toLoadNamespaces:Object.keys(s)}}loaded(e,t,n){let r=e.split(`|`),i=r[0],a=r[1];t&&this.emit(`failedLoading`,i,a,t),!t&&n&&this.store.addResourceBundle(i,a,n,void 0,void 0,{skipCopy:!0}),this.state[e]=t?-1:2,t&&n&&(this.state[e]=0);let o={};this.queue.forEach(n=>{f(n.loaded,[i],a),oe(n,e),t&&n.errors.push(t),n.pendingCount===0&&!n.done&&(Object.keys(n.loaded).forEach(e=>{o[e]||(o[e]={});let t=n.loaded[e];t.length&&t.forEach(t=>{o[e][t]===void 0&&(o[e][t]=!0)})}),n.done=!0,n.errors.length?n.callback(n.errors):n.callback())}),this.emit(`loaded`,o),this.queue=this.queue.filter(e=>!e.done)}read(e,t,n,r=0,i=this.retryTimeout,a){if(!e.length)return a(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:t,fcName:n,tried:r,wait:i,callback:a});return}this.readingCalls++;let o=(o,s)=>{if(this.readingCalls--,this.waitingReads.length>0){let e=this.waitingReads.shift();this.read(e.lng,e.ns,e.fcName,e.tried,e.wait,e.callback)}if(o&&s&&r<this.maxRetries){setTimeout(()=>{this.read(e,t,n,r+1,i*2,a)},i);return}a(o,s)},s=this.backend[n].bind(this.backend);if(s.length===2){try{let n=s(e,t);n&&typeof n.then==`function`?n.then(e=>o(null,e)).catch(o):o(null,n)}catch(e){o(e)}return}return s(e,t,o)}prepareLoading(e,t,n={},i){if(!this.backend)return this.logger.warn(`No backend was added via i18next.use. Will not load resources.`),i&&i();r(e)&&(e=this.languageUtils.toResolveHierarchy(e)),r(t)&&(t=[t]);let a=this.queueLoad(e,t,n,i);if(!a.toLoad.length)return a.pending.length||i(),null;a.toLoad.forEach(e=>{this.loadOne(e)})}load(e,t,n){this.prepareLoading(e,t,{},n)}reload(e,t,n){this.prepareLoading(e,t,{reload:!0},n)}loadOne(e,t=``){let n=e.split(`|`),r=n[0],i=n[1];this.read(r,i,`read`,void 0,void 0,(n,a)=>{n&&this.logger.warn(`${t}loading namespace ${i} for language ${r} failed`,n),!n&&a&&this.logger.log(`${t}loaded namespace ${i} for language ${r}`,a),this.loaded(e,n,a)})}saveMissing(e,t,n,r,i,a={},o=()=>{}){if(this.services?.utils?.hasLoadedNamespace&&!this.services?.utils?.hasLoadedNamespace(t)){this.logger.warn(`did not save key "${n}" as the namespace "${t}" was not yet loaded`,`This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!`);return}if(!(n==null||n===``)){if(this.backend?.create){let s={...a,isUpdate:i},c=this.backend.create.bind(this.backend);if(c.length<6)try{let i;i=c.length===5?c(e,t,n,r,s):c(e,t,n,r),i&&typeof i.then==`function`?i.then(e=>o(null,e)).catch(o):o(null,i)}catch(e){o(e)}else c(e,t,n,r,o,s)}!e||!e[0]||this.store.addResource(e[0],t,n,r)}}},B=()=>({debug:!1,initAsync:!0,ns:[`translation`],defaultNS:[`translation`],fallbackLng:[`dev`],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:`all`,preload:!1,keySeparator:`.`,nsSeparator:`:`,pluralSeparator:`_`,contextSeparator:`_`,enableSelector:!1,partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:`fallback`,saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:e=>{let t={};if(typeof e[1]==`object`&&(t=e[1]),r(e[1])&&(t.defaultValue=e[1]),r(e[2])&&(t.tDescription=e[2]),typeof e[2]==`object`||typeof e[3]==`object`){let n=e[3]||e[2];Object.keys(n).forEach(e=>{t[e]=n[e]})}return t},interpolation:{escapeValue:!0,prefix:`{{`,suffix:`}}`,formatSeparator:`,`,unescapePrefix:`-`,nestingPrefix:`$t(`,nestingSuffix:`)`,nestingOptionsSeparator:`,`,maxReplaces:1e3,skipOnVariables:!0},cacheInBuiltFormats:!0}),V=e=>(r(e.ns)&&(e.ns=[e.ns]),r(e.fallbackLng)&&(e.fallbackLng=[e.fallbackLng]),r(e.fallbackNS)&&(e.fallbackNS=[e.fallbackNS]),e.supportedLngs&&!e.supportedLngs.includes(`cimode`)&&(e.supportedLngs=e.supportedLngs.concat([`cimode`])),e),H=()=>{},ce=e=>{Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach(t=>{typeof e[t]==`function`&&(e[t]=e[t].bind(e))})},U=class e extends D{constructor(e={},t){if(super(),this.options=V(e),this.services={},this.logger=E,this.modules={external:[]},ce(this),t&&!this.isInitialized&&!e.isClone){if(!this.options.initAsync)return this.init(e,t),this;setTimeout(()=>{this.init(e,t)},0)}}init(e={},t){this.isInitializing=!0,typeof e==`function`&&(t=e,e={}),e.defaultNS==null&&e.ns&&(r(e.ns)?e.defaultNS=e.ns:e.ns.includes(`translation`)||(e.defaultNS=e.ns[0]));let n=B();this.options={...n,...this.options,...V(e)},this.options.interpolation={...n.interpolation,...this.options.interpolation},e.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=e.keySeparator),e.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=e.nsSeparator),typeof this.options.overloadTranslationOptionHandler!=`function`&&(this.options.overloadTranslationOptionHandler=n.overloadTranslationOptionHandler);let a=e=>e?typeof e==`function`?new e:e:null;if(!this.options.isClone){this.modules.logger?E.init(a(this.modules.logger),this.options):E.init(null,this.options);let e;e=this.modules.formatter?this.modules.formatter:ae;let t=new P(this.options);this.store=new O(this.options.resources,this.options);let n=this.services;n.logger=E,n.resourceStore=this.store,n.languageUtils=t,n.pluralResolver=new te(t,{prepend:this.options.pluralSeparator}),e&&(n.formatter=a(e),n.formatter.init&&n.formatter.init(n,this.options),this.options.interpolation.format=n.formatter.format.bind(n.formatter)),n.interpolator=new R(this.options),n.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},n.backendConnector=new se(a(this.modules.backend),n.resourceStore,n,this.options),n.backendConnector.on(`*`,(e,...t)=>{this.emit(e,...t)}),this.modules.languageDetector&&(n.languageDetector=a(this.modules.languageDetector),n.languageDetector.init&&n.languageDetector.init(n,this.options.detection,this.options)),this.modules.i18nFormat&&(n.i18nFormat=a(this.modules.i18nFormat),n.i18nFormat.init&&n.i18nFormat.init(this)),this.translator=new N(this.services,this.options),this.translator.on(`*`,(e,...t)=>{this.emit(e,...t)}),this.modules.external.forEach(e=>{e.init&&e.init(this)})}if(this.format=this.options.interpolation.format,t||=H,this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){let e=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);e.length>0&&e[0]!==`dev`&&(this.options.lng=e[0])}!this.services.languageDetector&&!this.options.lng&&this.logger.warn(`init: no languageDetector is used and no lng is defined`),[`getResource`,`hasResourceBundle`,`getResourceBundle`,`getDataByLanguage`].forEach(e=>{this[e]=(...t)=>this.store[e](...t)}),[`addResource`,`addResources`,`addResourceBundle`,`removeResourceBundle`].forEach(e=>{this[e]=(...t)=>(this.store[e](...t),this)});let o=i(),s=()=>{let e=(e,n)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn(`init: i18next is already initialized. You should call init just once!`),this.isInitialized=!0,this.options.isClone||this.logger.log(`initialized`,this.options),this.emit(`initialized`,this.options),o.resolve(n),t(e,n)};if((this.languages||this.isLanguageChangingTo)&&!this.isInitialized)return e(null,this.t.bind(this));this.changeLanguage(this.options.lng,e)};return this.options.resources||!this.options.initAsync?s():setTimeout(s,0),o}loadResources(e,t=H){let n=t,i=r(e)?e:this.language;if(typeof e==`function`&&(n=e),!this.options.resources||this.options.partialBundledLanguages){if(i?.toLowerCase()===`cimode`&&(!this.options.preload||this.options.preload.length===0))return n();let e=[],t=t=>{t&&t!==`cimode`&&this.services.languageUtils.toResolveHierarchy(t).forEach(t=>{t!==`cimode`&&(e.includes(t)||e.push(t))})};i?t(i):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(e=>t(e)),this.options.preload?.forEach?.(e=>t(e)),this.services.backendConnector.load(e,this.options.ns,e=>{!e&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),n(e)})}else n(null)}reloadResources(e,t,n){let r=i();return typeof e==`function`&&(n=e,e=void 0),typeof t==`function`&&(n=t,t=void 0),e||=this.languages,t||=this.options.ns,n||=H,this.services.backendConnector.reload(e,t,e=>{r.resolve(),n(e)}),r}use(e){if(!e)throw Error(`You are passing an undefined module! Please check the object you are passing to i18next.use()`);if(!e.type)throw Error(`You are passing a wrong module! Please check the object you are passing to i18next.use()`);return e.type===`backend`&&(this.modules.backend=e),(e.type===`logger`||e.log&&e.warn&&e.error)&&(this.modules.logger=e),e.type===`languageDetector`&&(this.modules.languageDetector=e),e.type===`i18nFormat`&&(this.modules.i18nFormat=e),e.type===`postProcessor`&&k.addPostProcessor(e),e.type===`formatter`&&(this.modules.formatter=e),e.type===`3rdParty`&&this.modules.external.push(e),this}setResolvedLanguage(e){if(!(!e||!this.languages)&&![`cimode`,`dev`].includes(e)){for(let e=0;e<this.languages.length;e++){let t=this.languages[e];if(![`cimode`,`dev`].includes(t)&&this.store.hasLanguageSomeTranslations(t)){this.resolvedLanguage=t;break}}!this.resolvedLanguage&&!this.languages.includes(e)&&this.store.hasLanguageSomeTranslations(e)&&(this.resolvedLanguage=e,this.languages.unshift(e))}}changeLanguage(e,t){this.isLanguageChangingTo=e;let n=i();this.emit(`languageChanging`,e);let a=e=>{this.language=e,this.languages=this.services.languageUtils.toResolveHierarchy(e),this.resolvedLanguage=void 0,this.setResolvedLanguage(e)},o=(r,i)=>{i?this.isLanguageChangingTo===e&&(a(i),this.translator.changeLanguage(i),this.isLanguageChangingTo=void 0,this.emit(`languageChanged`,i),this.logger.log(`languageChanged`,i)):this.isLanguageChangingTo=void 0,n.resolve((...e)=>this.t(...e)),t&&t(r,(...e)=>this.t(...e))},s=t=>{!e&&!t&&this.services.languageDetector&&(t=[]);let n=r(t)?t:t&&t[0],i=this.store.hasLanguageSomeTranslations(n)?n:this.services.languageUtils.getBestMatchFromCodes(r(t)?[t]:t);i&&(this.language||a(i),this.translator.language||this.translator.changeLanguage(i),this.services.languageDetector?.cacheUserLanguage?.(i)),this.loadResources(i,e=>{o(e,i)})};return!e&&this.services.languageDetector&&!this.services.languageDetector.async?s(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(s):this.services.languageDetector.detect(s):s(e),n}getFixedT(e,t,n,i){let a=i?.scopeNs,o=(e,t,...r)=>{let i;i=typeof t==`object`?{...t}:this.options.overloadTranslationOptionHandler([e,t].concat(r)),i.lng=i.lng||o.lng,i.lngs=i.lngs||o.lngs;let s=i.ns!==void 0&&i.ns!==null;i.ns=i.ns||o.ns,i.keyPrefix!==``&&(i.keyPrefix=i.keyPrefix||n||o.keyPrefix);let c={...this.options,...i};Array.isArray(a)&&!s&&(c.ns=a),typeof i.keyPrefix==`function`&&(i.keyPrefix=j(i.keyPrefix,c));let l=this.options.keySeparator||`.`,u;return i.keyPrefix&&Array.isArray(e)?u=e.map(e=>(typeof e==`function`&&(e=j(e,c)),`${i.keyPrefix}${l}${e}`)):(typeof e==`function`&&(e=j(e,c)),u=i.keyPrefix?`${i.keyPrefix}${l}${e}`:e),this.t(u,i)};return r(e)?o.lng=e:o.lngs=e,o.ns=t,o.keyPrefix=n,o}t(...e){return this.translator?.translate(...e)}exists(...e){return this.translator?.exists(...e)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e,t={}){if(!this.isInitialized)return this.logger.warn(`hasLoadedNamespace: i18next was not initialized`,this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn(`hasLoadedNamespace: i18n.languages were undefined or empty`,this.languages),!1;let n=t.lng||this.resolvedLanguage||this.languages[0],r=this.options?this.options.fallbackLng:!1,i=this.languages[this.languages.length-1];if(n.toLowerCase()===`cimode`)return!0;let a=(e,t)=>{let n=this.services.backendConnector.state[`${e}|${t}`];return n===-1||n===0||n===2};if(t.precheck){let e=t.precheck(this,a);if(e!==void 0)return e}return!!(this.hasResourceBundle(n,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||a(n,e)&&(!r||a(i,e)))}loadNamespaces(e,t){let n=i();return this.options.ns?(r(e)&&(e=[e]),e.forEach(e=>{this.options.ns.includes(e)||this.options.ns.push(e)}),this.loadResources(e=>{n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}loadLanguages(e,t){let n=i();r(e)&&(e=[e]);let a=this.options.preload||[],o=e.filter(e=>!a.includes(e)&&this.services.languageUtils.isSupportedCode(e));return o.length?(this.options.preload=a.concat(o),this.loadResources(e=>{n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}dir(e){if(e||=this.resolvedLanguage||(this.languages?.length>0?this.languages[0]:this.language),!e)return`rtl`;try{let t=new Intl.Locale(e);if(t&&t.getTextInfo){let e=t.getTextInfo();if(e&&e.direction)return e.direction}}catch{}let t=`ar.shu.sqr.ssh.xaa.yhd.yud.aao.abh.abv.acm.acq.acw.acx.acy.adf.ads.aeb.aec.afb.ajp.apc.apd.arb.arq.ars.ary.arz.auz.avl.ayh.ayl.ayn.ayp.bbz.pga.he.iw.ps.pbt.pbu.pst.prp.prd.ug.ur.ydd.yds.yih.ji.yi.hbo.men.xmn.fa.jpr.peo.pes.prs.dv.sam.ckb`.split(`.`),n=this.services?.languageUtils||new P(B());return e.toLowerCase().indexOf(`-latn`)>1?`ltr`:t.includes(n.getLanguagePartFromCode(e))||e.toLowerCase().indexOf(`-arab`)>1?`rtl`:`ltr`}static createInstance(t={},n){let r=new e(t,n);return r.createInstance=e.createInstance,r}cloneInstance(t={},n=H){let r=t.forkResourceStore;r&&delete t.forkResourceStore;let i={...this.options,...t,isClone:!0},a=new e(i);if((t.debug!==void 0||t.prefix!==void 0)&&(a.logger=a.logger.clone(t)),[`store`,`services`,`language`].forEach(e=>{a[e]=this[e]}),a.services={...this.services},a.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},r&&(a.store=new O(Object.keys(this.store.data).reduce((e,t)=>(e[t]={...this.store.data[t]},e[t]=Object.keys(e[t]).reduce((n,r)=>(n[r]={...e[t][r]},n),e[t]),e),{}),i),a.services.resourceStore=a.store),t.interpolation){let e={...B().interpolation,...this.options.interpolation,...t.interpolation},n={...i,interpolation:e};a.services.interpolator=new R(n)}return a.translator=new N(a.services,i),a.translator.on(`*`,(e,...t)=>{a.emit(e,...t)}),a.init(i,n),a.translator.options=i,a.translator.backendConnector.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},a}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}.createInstance();U.createInstance,U.dir,U.init,U.loadResources,U.reloadResources,U.use,U.changeLanguage,U.getFixedT,U.t,U.exists,U.setDefaultNamespace,U.hasLoadedNamespace,U.loadNamespaces,U.loadLanguages;var le=/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g,ue={"&amp;":`&`,"&#38;":`&`,"&lt;":`<`,"&#60;":`<`,"&gt;":`>`,"&#62;":`>`,"&apos;":`'`,"&#39;":`'`,"&quot;":`"`,"&#34;":`"`,"&nbsp;":` `,"&#160;":` `,"&copy;":`©`,"&#169;":`©`,"&reg;":`®`,"&#174;":`®`,"&hellip;":`…`,"&#8230;":`…`,"&#x2F;":`/`,"&#47;":`/`},de=e=>ue[e],W={bindI18n:`languageChanged`,bindI18nStore:``,transEmptyNodeValue:``,transSupportBasicHtmlNodes:!0,transWrapTextNodes:``,transKeepBasicHtmlNodesFor:[`br`,`strong`,`i`,`p`],useSuspense:!0,unescape:e=>e.replace(le,de),transDefaultProps:void 0},fe=(e={})=>{W={...W,...e}},pe=()=>W,G,me=e=>{G=e},he=()=>G,ge={type:`3rdParty`,init(e){fe(e.options.react),me(e)}};function _e(e){let t=(e??``).trim().toLowerCase().replace(/_/g,`-`);return!t||t===`en`||t.startsWith(`en-`)?`en`:`zh`}function K(){if(typeof navigator>`u`)return`en`;let e=(navigator.language||navigator.languages?.[0]||``).trim();return e?_e(e):`en`}function q(e){return e===`zh`?`zh-CN`:`en`}var J=`xopc.token`,Y=`xopc.language`;function ve(){try{return localStorage.getItem(J)||``}catch{return``}}function ye(e){try{localStorage.setItem(J,e)}catch(e){console.error(`Failed to save token:`,e)}}function be(){try{localStorage.removeItem(J)}catch(e){console.error(`Failed to clear token:`,e)}}function X(){try{let e=localStorage.getItem(Y);return e===`en`||e===`zh`?e:K()}catch{return K()}}function xe(e){try{localStorage.setItem(Y,e)}catch(e){console.error(`Failed to save language:`,e)}}var Se={agentSettings:JSON.parse('{"subtitle":"Defaults for models, workspace, sampling, and how responses are shown.","sectionDesc":"Changes are written to your gateway config file. Some values apply on the next agent turn or session.","needToken":"Save a gateway token to load and change agent defaults.","loadError":"Failed to load settings","save":"Save","discard":"Discard","saving":"Saving…","saved":"Saved","saveError":"Failed to save","routeIntro":{"chat":"Primary model, sampling, and how replies appear. Saves to agents.defaults on the gateway.","workspace":"Working directory for agent files and limits for inbound images in the image tool.","browser":"Let the agent drive the web via browser_use. Enable tools, pick a connection method, then finish setup below.","runtime":"Per-turn time limits, tool call depth, request retries, and consecutive tool failure caps. Saves to agents.defaults.","context":"Context compaction and tool-result pruning before messages reach the model.","memory":"Memory snapshots, session_search summary model, and optional background review.","tools":"Optional tools (web_extract, delegate_task, execute_code), global built-in tool disables, and extension params JSON. Skill allowlist is under Skills.","skills":"Skills marketplace source (use the section Save button) and default skill allowlist for all agents (use the page header Save). Install skills in the Skills library. Per-tool toggles are under Tools.","systemPrompt":"Optional full replacement for the default system prompt; merges with per-agent entries (entry wins). Saves to agents.defaults."},"defaultsTabs":{"chat":"Model & chat","workspace":"Workspace","browser":"Browser","runtime":"Turn limits","context":"Context","memory":"Memory","tools":"Tools","skills":"Skills","system-prompt":"System prompt"},"defaultsTabsAria":"Agent default configuration sections","browserTabs":{"overview":"Overview","extension":"Chrome extension","local":"Local Chromium","cloakbrowser":"CloakBrowser","cdp":"CDP","cloud":"Cloud"},"browserTabsAria":"Browser settings sections","cardModelsTitle":"Models","cardModelsSubtitle":"Chat, vision, and image generation defaults","cardWorkspaceTitle":"Workspace & attachments","cardWorkspaceSubtitle":"Working directory and inbound media limits","cardBrowserTitle":"Browser automation","cardBrowserSubtitle":"browser_use — navigate, snapshot, click, screenshot, pipelines (Chrome extension, Playwright, CloakBrowser, …)","browserEnabledOn":"Enable browser tools","browserHeadlessOn":"Run headless (no visible window)","browserAllowPrivateOn":"Allow private/internal URLs","browserDialogPolicyMustRespond":"Agent must respond","browserDialogPolicyAutoDismiss":"Auto dismiss","browserDialogPolicyAutoAccept":"Auto accept","browserBackendLocal":"Local (Playwright)","browserBackendCdp":"CDP (Remote)","browserBackendCloud":"Cloud Provider","browserBackendExtension":"Chrome Extension","browserBackendCloakBrowser":"CloakBrowser","browserCloudProviderLocal":"Local (Playwright)","browserCloudProviderBrowserbase":"Browserbase","browserCloudProviderBrowserUse":"Browser Use","browserExtensionConnected":"Connected","browserExtensionDisconnected":"Disconnected","browserExtensionWaiting":"Waiting for connection…","browserExtensionServerOff":"Server not running","browserPlaywrightGuideTitle":"Local Playwright requires Chromium","browserPlaywrightGuideDesc":"When Local (Playwright) is selected, Chromium must be installed on the gateway host. You can install it here or run the install command manually on that machine.","browserPlaywrightInstall":"Install","browserPlaywrightInstalling":"Installing…","browserPlaywrightInstalled":"Chromium installed","browserPlaywrightInstallFailed":"Failed to install Chromium","browserPlaywrightManualInstall":"Manual install command","browserCloakGuideTitle":"Download CloakBrowser before first use","browserCloakGuideDesc":"CloakBrowser provides anti-fingerprint Chromium. After saving, the gateway uses it from this config; you can also run the install command first to download it.","browserCloakDownload":"Download","browserCloakInstalling":"Downloading…","browserCloakInstalled":"CloakBrowser downloaded","browserCloakInstallFailed":"Failed to download CloakBrowser","browserCloakOpen":"Open browser","browserCloakOpening":"Opening…","browserCloakOpenReused":"Connected to running browser · port {{port}}","browserCloakOpenLaunched":"Opened · port {{port}}","browserCloakProfileLabel":"Profile","browserCloakProfileAgentHint":"Uses the profile from saved config — same as agent runtime. Save settings after changing paths or profile options.","browserCloakRuntimeRunning":"Running · port {{port}}","browserCloakRuntimeOff":"Not running","browserCloakTemporaryProfileHint":"Temporary profile enabled — each launch uses a new profile","browserInstallPhaseStarting":"Preparing…","browserInstallPhaseDownloading":"Downloading…","browserInstallPhaseDownloadingPercent":"Downloading… {{percent}}%","browserInstallPhaseVerifying":"Verifying checksum…","browserInstallPhaseExtracting":"Extracting archive…","browserInstallPhaseRunning":"Running install…","browserInstallPhaseReady":"Finishing…","browserInstallCancel":"Cancel","browserInstallCancelling":"Cancelling…","browserInstallCancelled":"Install cancelled","browserCloakKeepOpenOn":"Keep browser alive between tasks","browserCloakTemporaryProfileOn":"Use a temporary profile each time","browserHumanizeOn":"Simulate more natural mouse, keyboard, and scroll input","browserHumanPresetCareful":"Careful (recommended)","browserHumanPresetDefault":"Standard","browserModeLocalShort":"Local Chromium","browserModeCloakShort":"CloakBrowser","browserModeCdpShort":"CDP","browserModeCloudShort":"Cloud","browserModeExtShort":"Extension","browserModeLocalTagline":"Playwright Chromium on the gateway host","browserModeCloakTagline":"Anti-fingerprint Chromium for stealth automation","browserModeCdpTagline":"Drive a local debuggable Chrome over CDP","browserModeCloudTagline":"Browserbase / Browser Use remote browsers","browserModeExtTagline":"Bridge a real user\'s Chrome via extension","browserDisabledHint":"Enable browser tools to choose a connection method and configure the backend.","browserDocsLink":"Browser tools docs","browserSetupTitle":"Get started","browserSetupSubtitle":"Pick a connection method — you can change it anytime after enabling browser tools.","browserSetupRecommended":"Recommended","browserSetupSelect":"Use this method","browserSetupExtTitle":"Chrome extension","browserSetupExtDesc":"Bridge your everyday Chrome. Best for sites that need a logged-in session.","browserSetupLocalTitle":"Local Playwright","browserSetupLocalDesc":"Headless or visible Chromium on the gateway host. Install once, then save.","browserSetupCloudTitle":"Cloud browser","browserSetupCloudDesc":"Browserbase or Browser Use — no local Chromium install required.","browserStatusStripBackend":"Connection","browserWorkspaceExtSubtitle":"Install the extension, start the bridge, and connect from Chrome.","browserWorkspaceLocalSubtitle":"Install Chromium on the gateway host to run Playwright locally.","browserWorkspaceCloakSubtitle":"Download CloakBrowser and tune anti-fingerprint options.","browserWorkspaceCdpSubtitle":"Launch or attach to a debuggable Chrome over CDP.","browserWorkspaceCloudSubtitle":"Connect to Browserbase or Browser Use with your API credentials.","browserBehaviorShow":"Runtime & dialogs","browserBehaviorHide":"Hide runtime & dialogs","browserBehaviorHint":"Headless mode and JavaScript dialog handling for all backends.","browserSecurityShow":"Security & limits","browserSecurityHide":"Hide security & limits","browserSecurityHint":"Private URL access and per-command timeouts. Cloud metadata endpoints are always blocked.","browserPickerTitle":"Active browser","browserPickerSubtitle":"Choose which backend agents use at runtime. Configure each method in its tab.","browserGoToConfigure":"Configure","browserConfiguringHeader":"Configuring: {{mode}}","browserSelectedBadge":"Selected","browserStatusReady":"Ready","browserStatusNotInstalled":"Not installed","browserStatusChecking":"Checking…","browserStatusUnknown":"Unknown","browserStatusError":"Error","browserAdvancedShow":"Advanced","browserAdvancedHide":"Hide advanced","browserReinstall":"Reinstall","browserConfirmDownloadTitle":"Download external binary","browserConfirmDownloadBody":"About to download CloakBrowser {{version}} for {{platform}} from {{url}}. The file will be SHA-256 verified before extraction.","browserConfirmDownloadConfirm":"Download & install","browserConfirmDownloadCancel":"Cancel","browserCloakSha256Skipped":"Manifest has no SHA-256 for this platform — integrity will NOT be verified.","browserCloakAdvancedShow":"Paths & fingerprint","browserCloakAdvancedHide":"Hide paths & fingerprint","browserCloakAdvancedHint":"Binary cache, custom executable, timezone/locale emulation, WebRTC IP, and extra Chromium flags.","browserCdpLaunchLocal":"Launch a debuggable Chrome locally","browserCdpLaunchLocalDesc":"Spawns Chrome with --remote-debugging-port so the agent can drive it. The window stays open until you click Stop.","browserCdpLaunching":"Launching…","browserCdpStopLocal":"Stop local Chrome","browserCdpLaunchedAtPort":"Launched on port {{port}} — endpoint filled in below.","browserCdpTestConnection":"Test connection","browserCdpTesting":"Testing…","browserCdpReachable":"Reachable — {{browser}}","browserCdpUnreachable":"Unreachable: {{error}}","browserCdpLoopbackOnly":"Only loopback endpoints (127.0.0.1 / localhost / ::1) are allowed for safety.","browserCdpChromePath":"Chrome executable (optional)","browserCdpChromePathDesc":"Optional override. Empty uses Playwright Chromium first, then the system Chrome/Chromium.","browserCloudTestConnection":"Test connection","browserCloudTestOk":"Connected ✓","browserCloudTestFailed":"Failed: {{error}}","browserBinaryPathWarning":"⚠ The gateway will execute the binary at this path with its own privileges. Only point to binaries you trust.","browserCacheDirHomeOnly":"Must be under your home directory (e.g. ~/.xopc/bin).","browserExtensionDownloadHint":"Load the xopc extension in Chrome and bridge to the gateway over WebSocket.","browserExtensionInstall":"Install locally","browserExtensionInstalling":"Installing…","browserExtensionInstalled":"Extension copied to","browserExtensionOpenChrome":"Open chrome://extensions","browserExtensionRevealFolder":"Copy path & open folder","browserExtensionPathCopied":"Path copied and folder opened in Finder/Explorer.","browserExtensionFolderOpened":"Folder opened in Finder/Explorer.","browserExtensionNeedsChromeReload":"xopc updated the extension on disk. Open chrome://extensions and click Reload on the xopc extension.","browserExtensionInstallGuideTitle":"Setup checklist","browserExtensionChecklistProgress":"{{done}}/{{total}} done","browserExtensionChecklistDone":"Completed:","browserExtensionChecklistPending":"Pending:","browserExtensionInstallStep1":"Click Install locally above to copy the extension to your machine.","browserExtensionInstallStep2":"Open chrome://extensions → turn on Developer mode → Load unpacked → select the folder below.","browserExtensionInstallStep2FolderLabel":"Extension folder","browserExtensionInstallStep3":"Click Start bridge, then Connect in the xopc extension popup from the Chrome toolbar.","browserExtensionStartBridge":"Start bridge","browserExtensionStarting":"Starting…","browserExtensionStopBridge":"Stop bridge","browserExtensionDisconnect":"Disconnect extension","browserExtensionPortConflict":"Port {{port}} is already in use. If this gateway owns the bridge, click Stop bridge; otherwise change the port or stop the process using it.","browserExtensionStartHint":"Start the WebSocket bridge now so you can pair the extension before saving. The bridge will keep running until you click Stop.","cardGenerationTitle":"Sampling & tools","cardGenerationSubtitle":"Token budget, randomness, and tool loop depth","cardBehaviorTitle":"Reasoning & output","cardBehaviorSubtitle":"Thinking depth, traces, and verbosity","label":{"model":"Model","modelFallbacks":"Fallback models","imageModel":"Image model","imageModelFallbacks":"Image understanding fallbacks","imageGenerationModel":"Image generation model","imageGenerationModelFallbacks":"Image generation fallbacks","mediaMaxMb":"Image load limit (MB)","workspace":"Workspace","browserEnabled":"Browser tools","browserHeadless":"Headless mode","browserAllowPrivateUrls":"Allow private URLs","browserCommandTimeout":"Command timeout (s)","browserBackend":"Backend mode","browserCloudProvider":"Cloud provider","browserCloudApiKey":"API Key","browserCloudProjectId":"Browserbase project ID","browserCloudRegion":"Cloud region","browserCdpUrl":"CDP endpoint URL","browserExtensionPort":"Extension port","browserExtensionHost":"Extension host","browserExtensionConnectionTimeout":"Connection timeout (s)","browserCloakKeepOpen":"Keep alive","browserCloakTemporaryProfile":"Temporary profile","browserCloakCacheDir":"Download cache dir","browserCloakBinaryPath":"Browser binary path","browserCloakTimezone":"Timezone","browserCloakLocale":"Locale","browserCloakWebrtcIp":"WebRTC public IP","browserCloakFingerprintPlatform":"Fingerprint platform","browserCloakExtraArgs":"Extra Chromium args","browserHumanize":"Humanized input","browserHumanPreset":"Input pace","browserDialogPolicy":"Dialog handling policy","browserDialogTimeout":"Dialog timeout (s)","maxTokens":"Max tokens","temperature":"Temperature","maxToolIterations":"Max tool iterations","thinkingDefault":"Thinking level","reasoningDefault":"Reasoning visibility","verboseDefault":"Verbose mode"},"desc":{"model":"Default model for new sessions.","modelFallbacks":"Tried in order when the primary model returns an error after transient retries. Requires API keys for each provider.","imageModel":"Optional. Used for image understanding / vision. Only models the gateway marks as accepting image input are listed.","imageModelFallbacks":"Tried in order when the primary vision model fails. Only models flagged as image-capable are listed.","imageGenerationModel":"Optional. For image_generate. Only providers the gateway reports as configured (API keys present) are listed.","imageGenerationModelFallbacks":"Tried in order when the primary image generation model fails. Only configured image-generation providers are listed.","mediaMaxMb":"Max size when loading images in the image tool.","workspace":"Working directory for agent files.","browserEnabled":"Exposes browser_use automation to the model (which browser runs depends on Backend mode below).","browserHeadless":"Default off: Chromium shows a window on the gateway machine. Turn on to run without a visible window (background).","browserAllowPrivateUrls":"Skip private-IP blocking for navigation. Cloud metadata endpoints (169.254.169.254, etc.) are always blocked regardless.","browserCommandTimeout":"Max seconds per browser command (navigate, click, etc.). Default 30.","browserBackend":"Connection mode: Local Playwright, direct CDP, cloud provider, or Chrome Extension bridge.","browserCloudProvider":"Cloud provider: Browserbase or Browser Use. You can set the API key here; environment variables BROWSERBASE_API_KEY / BROWSER_USE_API_KEY are still supported.","browserCloudApiKey":"Stored in gateway config. Leave empty to use process environment variables. Saved keys are masked on reload.","browserCloudProjectId":"Optional Browserbase project ID. Empty uses BROWSERBASE_PROJECT_ID or the provider default.","browserCloudRegion":"Optional. Passed to providers that support regions; empty uses the default region.","browserCdpUrl":"Direct Chrome DevTools Protocol WebSocket endpoint (e.g. ws://localhost:9222). Only used when backend is CDP.","browserExtensionPort":"WebSocket port for the Chrome Extension bridge. Default 19820.","browserExtensionHost":"Host for the Chrome Extension bridge. Default 127.0.0.1.","browserExtensionConnectionTimeout":"How long the gateway waits for the extension to connect (seconds). Default 30.","browserCloakKeepOpen":"Reuse one CloakBrowser process to reduce startup time for later tasks. Enabled by default.","browserCloakTemporaryProfile":"Use a temporary user-data directory on each launch and clean it up on close. Useful for isolated testing.","browserCloakCacheDir":"Optional. CloakBrowser home directory (binaries and profiles). Empty uses ~/.xopc/bin/cloakbrowser.","browserCloakBinaryPath":"Optional. Path to an existing CloakBrowser/Chromium executable, usually under ~/.xopc/bin. Set this to skip auto-download.","browserCloakTimezone":"Optional timezone to emulate (IANA name, e.g. America/New_York).","browserCloakLocale":"Optional locale to emulate (e.g. en-US).","browserCloakWebrtcIp":"Optional public IP for WebRTC leak prevention.","browserCloakFingerprintPlatform":"Optional platform string for fingerprint emulation (e.g. windows, macos).","browserCloakExtraArgs":"One Chromium flag per line. Args with the same --key= prefix override defaults.","browserHumanize":"Use Bezier mouse movement, per-character typing, and natural scroll pacing to reduce automation signals.","browserHumanPreset":"Choose the input pace. Careful is slower but closer to real user behavior.","browserDialogPolicy":"How JS dialogs (alert/confirm/prompt) are handled: agent must respond, auto dismiss, or auto accept.","browserDialogTimeout":"Seconds before an unhandled dialog is auto-dismissed/accepted (only for auto policies). Default 300.","maxTokens":"Maximum tokens in the model response.","temperature":"Randomness (0–2).","maxToolIterations":"Maximum tool calls per user message.","thinkingDefault":"Default thinking level for new sessions.","reasoningDefault":"Whether to surface model reasoning in the chat UI. Per-session overrides (e.g. /reasoning) take precedence until cleared.","verboseDefault":"Agent verbosity for logs/tool detail elsewhere — not the reasoning/thinking panel. Use Reasoning visibility to hide reasoning."},"addModelFallback":"Add fallback model","removeModelFallback":"Remove fallback model","setDefaultWorkspace":"Set default","visionRegistryEmpty":"No models flagged as image-capable for your configured providers. Add `input` including \\"image\\" in models.json, or pick a provider model that exposes image input.","visionOutOfFilterNote":"Registry does not mark this model as image-capable; choose a vision model when possible.","imageGenRegistryEmpty":"No image generation providers are configured with API credentials. Add keys for a provider (e.g. OpenAI) in config or environment, then refresh.","imageGenOutOfFilterNote":"This model’s provider is not configured with credentials; image_generate will fail until you configure it or pick a configured provider.","reasoning":{"off":"Off","on":"On","stream":"Stream"},"verbose":{"off":"Off","on":"On","full":"Full"},"advanced":{"advancedOptionsShow":"Advanced options","advancedOptionsHide":"Hide advanced options","cardLimitsTitle":"Turn limits & reliability","cardLimitsSubtitle":"Wall-clock cap per user turn, request retries, and tool failure budget.","maxTaskDurationMs":"Max task duration (minutes)","maxTaskDurationMsDesc":"Per-user-turn wall time for LLM and tools. Leave empty to use the server default. Range 1–240 min (1 min–4 h).","maxTaskDurationPlaceholder":"e.g. 30 (empty = default)","maxRequestsPerTurn":"Max requests per turn","maxRequestsPerTurnDesc":"LLM request attempts per user message (reliability; default 50).","maxToolFailuresPerTurn":"Max tool failures per turn","maxToolFailuresPerTurnDesc":"Consecutive tool errors before giving up (default 3).","goalsCheckLink":"Goal checking (/goal) → Goal judge settings","goalsCheckLinkHint":"Checklist judging defaults are configured under Settings → Automation → Goal judge.","cardCompactionTitle":"Context compaction","cardCompactionSubtitle":"When to compact older context to stay within the model window.","compactionEnabled":"Enable compaction","compactionEnabledDesc":"When off, the runtime skips compaction (may use more context).","compactionEnabledOn":"Compaction on","compactionMode":"Mode","compactionModeDesc":"default: standard strategy; safeguard: stricter heuristics when enabled.","compactionModeDefault":"default","compactionModeSafeguard":"safeguard","reserveTokens":"Reserve tokens","reserveTokensDesc":"Headroom to leave after compaction (default 8000).","triggerThreshold":"Trigger threshold","triggerThresholdDesc":"Fraction of context that triggers compaction (0.5–0.95).","minMessagesBeforeCompact":"Min messages before compact","minMessagesBeforeCompactDesc":"Message count before compaction can run (default 10).","keepRecentMessages":"Keep recent messages","keepRecentMessagesDesc":"Recent turns always kept near the tail (default 5).","evictionWindow":"Eviction window","evictionWindowDesc":"Portion of history eligible for summary-first eviction (0.1–0.5).","retentionWindow":"Retention window","retentionWindowDesc":"Recent turns in the retention band (3–20).","cardPruningTitle":"Tool result pruning","cardPruningSubtitle":"Trim oversized tool results before the model sees them.","pruningEnabled":"Enable pruning","pruningEnabledDesc":"When off, full tool output may be sent to the model (higher cost).","pruningEnabledOn":"Pruning on","maxToolResultChars":"Max tool result characters","maxToolResultCharsDesc":"Default cap for a single tool result string (default 10000).","headKeepRatio":"Head keep ratio","headKeepRatioDesc":"Fraction kept from the start when pruning (0–1, default 0.3).","tailKeepRatio":"Tail keep ratio","tailKeepRatioDesc":"Fraction kept from the end (0–1, default 0.3).","cardMemoryTitle":"Memory (curated & external)","cardMemorySubtitle":"System memory, USER.md, and optional provider hooks.","memoryEnabled":"Memory features","memoryEnabledDesc":"Master switch: curated memory snapshot, tool, and external prefetch (when set).","memoryEnabledOn":"Enabled","useEnhancedSystem":"Use enhanced system","useEnhancedSystemDesc":"When off, use profile Markdown in the workspace only (no extra memory snapshot in system).","useEnhancedSystemOn":"Enhanced system on","userProfileEnabled":"Include USER.md","userProfileEnabledDesc":"Add USER.md to the memory snapshot when present.","userProfileEnabledOn":"Include user profile","memoryProvider":"External memory provider","memoryProviderDesc":"none/stub, or leave unset to omit.","memoryProviderUnset":"(unset)","injectionFrequency":"External prefetch injection","injectionFrequencyDesc":"How often to inject prefetched memory into the user message context.","injectionFrequencyUnset":"(unset)","injectionEveryTurn":"Every turn (with cadence)","injectionFirstTurn":"First turn only","memoryCharLimit":"Memory character limit","memoryCharLimitDesc":"Max chars for the curated memory snapshot (optional).","userCharLimit":"User profile char limit","userCharLimitDesc":"Max chars for USER.md section (optional).","contextCadence":"Context cadence","contextCadenceDesc":"When using every turn: inject on turns 1, 1+N, … (min 1).","dialecticCadence":"Dialectic cadence (reserved)","dialecticCadenceDesc":"Reserved; not yet wired. Min 1 when set.","cardSessionSearchTitle":"Session search (transcripts)","cardSessionSearchSubtitle":"Model used to summarize past sessions for the session_search tool.","sessionSearchSummaryModel":"Summary model","sessionSearchSummaryModelDesc":"e.g. openai/gpt-4o-mini. Leave empty to use runtime defaults.","cardReviewTitle":"Background review","cardReviewSubtitle":"Post-turn nudges for memory/skills. Opt-in: enable below.","reviewEnabled":"Enable background review","reviewEnabledDesc":"When on, a quiet follow-up may run after successful turns.","reviewEnabledOn":"Enable","memoryNudgeInterval":"Memory nudge (every N user turns)","memoryNudgeIntervalDesc":"0 disables the memory channel. Default 10.","skillNudgeInterval":"Skill nudge (rounds without skill_manage)","skillNudgeIntervalDesc":"0 disables the skill channel. Default 10.","reviewMaxToolRounds":"Review max tool rounds","reviewMaxToolRoundsDesc":"1–32 (default 8).","reviewMaxHistoryMessages":"Max history in review (messages, tail)","reviewMaxHistoryMessagesDesc":"10–200 (default 80).","reviewMaxDurationMs":"Review time limit (seconds)","reviewMaxDurationMsDesc":"Wall clock for the review run (30–600 s; default 120).","cardWebExtractTitle":"web_extract (LLM pass)","cardWebExtractSubtitle":"Optional model and length for markdown web extraction.","webExtractModel":"Model","webExtractModelDesc":"Leave empty to use the default provider/model for extraction.","webExtractMaxLength":"Max length","webExtractMaxLengthDesc":"Max extracted characters (optional).","cardDelegateTitle":"Sub-agents & code execution","cardDelegateSubtitle":"Opt-in: delegate_task and sandboxed execute_code.","delegateEnabled":"Sub-agent delegate_task","delegateEnabledDesc":"When on, the agent may delegate to sub-agent runs (if supported).","delegateEnabledOn":"Enabled","executeCodeEnabled":"execute_code (sandboxed)","executeCodeEnabledDesc":"When on, the sandboxed code tool is available (if the runtime allows).","executeCodeEnabledOn":"Enabled","cardSystemPromptTitle":"System prompt","cardSystemPromptSubtitle":"Optional override of the default system context. Merged with per-agent values; entry-specific settings win.","cardSkillsTitle":"Skill allowlist","cardSkillsSubtitle":"When non-empty, only these skills appear in <available_skills> in the prompt.","systemPromptOverride":"System prompt override","systemPromptOverrideDesc":"Optional full replacement; merged with per-agent entry (entry wins). Leave empty to clear.","systemPromptPlaceholder":"","skillsAllowlist":"Skill name allowlist","skillsAllowlistDesc":"When set, only checked skills appear in <available_skills>. Use All skills for no filter, or Only selected to pick from the catalog (including entries not currently listed).","skillsAllowlistModeAll":"All skills","skillsAllowlistModeRestrict":"Only selected","skillsAllowlistNotInCatalog":"not in catalog","addSkillName":"Add skill name","removeListItem":"Remove row","cardToolsDisableTitle":"Tools — global disable","cardToolsDisableSubtitle":"Disable built-in tool names in agents.defaults (e.g. shell, web_search).","toolsDisableFieldLabel":"Built-in tools","toolsDisableHint":"Checked tools are available to the default agent; unchecked tools are blocked. Per-agent overrides in Agents still apply.","toolsDisableLoadingBuiltin":"Loading built-in tool list…","toolsDisableEmptyBuiltin":"No built-in tools returned by the gateway.","toolsDisableNotInBuiltin":"not in built-in list","toolsDisableQuickActionsLabel":"Quick actions","toolsDisableQuickEnableAll":"Enable all","toolsDisableQuickDisableAll":"Disable all","toolsDisableQuickReadOnlyWorkspace":"Read-only workspace","toolsDisableQuickHighRiskOff":"Block high-risk","toolsDisableQuickNoOutbound":"No outbound","addToolName":"Add tool name","cardParamsTitle":"Params (JSON)","cardParamsSubtitle":"Opaque key/value for extensions. Must be a JSON object.","paramsJson":"Params object","paramsJsonDesc":"e.g. {\\"myFlag\\": true}. Clear to remove params from the config file.","paramsInvalidJson":"Params must be valid JSON object (e.g. empty or {}). Check syntax."}}'),agentsSettings:JSON.parse(`{"title":"Agents","subtitle":"Manage agents.list entries: workspaces, default routing, and profile Markdown.","needToken":"Save a gateway token to manage agents.","loadError":"Failed to load agents","saveError":"Request failed","loading":"Loading…","tabOverview":"Agents","tabDefaults":"Defaults","tabFiles":"Profile Markdown","tabTools":"Tools","tabSkills":"Skills","tabChannels":"Channels","tabCron":"Cron","selectAgent":"Agent","selectAgentHint":"Choose an entry to edit. Profile Markdown (SOUL.md, IDENTITY.md, …) is read from that agent's \`agents/<id>/profile/\` directory.","agent":"Agent","defaultBadge":"default","setDefault":"Set as default","editAgent":"Edit entry","editAgentHint":"Updates agents.list on the gateway. Paths are expanded (~ → home).","inheritance":{"title":"Defaults vs this agent","subtitle":"Empty model uses the global default. Workspace matches the default path when unchanged.","editDefaultsLink":"Edit defaults","modelLabel":"Primary model","workspaceLabel":"Workspace","badgeInherit":"Inherits default","badgeOverride":"Custom","inheritsValue":"Default: {{value}}","unset":"Not set"},"displayName":"Display name","agentDescription":"Description","agentDescriptionPlaceholder":"Short summary shown on agent cards and in pickers (optional).","workspacePath":"Markdown workspace","modelPrimary":"Model (primary)","modelClear":"Clear","save":"Save","discard":"Discard","removeFromConfig":"Remove from config","purgeDisk":"Remove + delete data","addAgent":"Add agent","addAgentHint":"Same as CLI agents add: creates directories and seeds profile Markdown templates.","newAgentLabel":"Display name","newAgentIdOptional":"Agent ID (optional)","newAgentIdPlaceholder":"Leave empty to derive from display name","newAgentIdRules":"1–64 characters: letters, digits, underscores, hyphens; must start with a letter or digit. Avoid reserved ids (e.g. main, con).","newWorkspace":"Workspace directory (required)","newModelOptional":"Model (optional)","create":"Create agent","addAgentAria":"Add agent","createModalCancel":"Cancel","closeDialogAria":"Close","filesHint":"Editable persona files (SOUL, IDENTITY, …). Changes save automatically after you stop typing; use Preview to render Markdown.","filesLoading":"Loading file list…","filesEmpty":"No files yet.","pickFile":"Select a file to edit.","saveFile":"Save file","filesMarkdownEdit":"Edit","filesMarkdownPreview":"Preview","filesAutoSaveHint":"Auto-saves when you pause typing.","filesSavingStatus":"Saving…","missing":"missing","confirmDelete":"Remove this agent from config? Bindings referencing it will be stripped.","confirmDeletePurge":"Remove this agent and delete its workspace + ~/.xopc/agents/<id> data? This cannot be undone.","purgeConfirmLabel":"Type the agent id to confirm","purgeConfirmPlaceholder":"Type {{agentId}} to confirm","purgeConfirmHint":"This action is irreversible. Enter {{agentId}} exactly to enable deletion.","toolsTitle":"Built-in tools","toolsHint":"Per-agent tool disables (merged with agents.defaults). Tools already disabled in defaults cannot be re-enabled here.","toolsSave":"Save tool disables","toolsClearEntry":"Clear per-agent disables","toolsLockedByDefaults":"disabled in defaults","toolsDisableGroups":{"unknown":"Custom ids (not in built-in list)","workspace":"Workspace & search","execution":"Execution","web":"Web","messaging":"Channels & outbound","memory":"Memory & sessions","media":"Vision & generation","extensions":"Extensions","mcp":"MCP (bundle)","misc":"Other built-ins"},"toolDescriptions":{"read_file":"Read text and small files inside the agent workspace (paths are restricted to the workspace sandbox).","write_file":"Create new files or overwrite existing ones under the workspace.","edit_file":"Change existing files using locate-and-replace or patch-style edits.","list_dir":"List files and subfolders in a workspace directory.","grep":"Search file contents with regular expressions (similar to ripgrep).","find":"Find files by name or glob pattern under the workspace.","shell":"Run shell commands with workspace context — high impact; turn off for read-only or safer agents.","web_search":"Search the public web for facts and pages newer than the model may know.","web_fetch":"Fetch a URL and read its text content for the model.","send_message":"Send outbound chat messages on connected channels (e.g. Telegram, CLI, gateway) when the agent replies.","send_media":"Send images or other media attachments through those channels.","memory_search":"Search indexed memories and notes stored for this agent.","memory_get":"Load a specific memory entry or chunk by id.","curated_memory":"Read or update curated markdown memories under the agent home directory.","session_search":"Search across saved conversation transcripts and per-session summaries.","image":"Analyze or describe images (vision) from the workspace or the current turn.","image_generate":"Generate images using the configured image / image-generation model.","extensions":"Expose tools registered by enabled extensions — disable to block all extension tools.","bundle-mcp":"Load tools from configured MCP servers (global mcp.servers and extension .mcp.json)."},"skillsTitle":"Skill allowlist","skillsHint":"Optional allowlist for <available_skills>. Inherit uses agents.defaults only; customize sets this agent’s skills array.","skillsInherit":"Inherit defaults","skillsCustomize":"Customize allowlist","skillsSave":"Save skills","skillsCatalogLoading":"Loading skill catalog…","skillsEmptyCatalog":"No skills in catalog.","skillsNoDescription":"No description in SKILL.md metadata.","skillsDefaultsLabel":"Defaults allowlist:","skillsEffectiveLabel":"Effective allowlist:","skillsAllFromCatalog":"(all catalog skills)","channelsTitle":"Routing bindings","channelsHint":"config.bindings rows for this agent. Removing a rule updates the full bindings array on the gateway.","channelsLoading":"Loading bindings…","channelsNone":"No bindings target this agent.","channelLabel":"Channel","peerIdLabel":"Peer id (optional)","channelsLoadingChannels":"Loading channel list…","channelsManualChannelHint":"Gateway returned no channel list. Enter a channel id (e.g. telegram, webchat, gateway).","channelsDisabledSuffix":"(disabled)","channelsSessionLabel":"Match","channelsRefreshSessions":"Refresh","channelsRefreshSessionsHint":"Reload recent sessions for this channel","channelsLoadingSessions":"Loading sessions…","channelsPeerFromSessions":"From sessions","channelsPeerAny":"All traffic on this channel","channelsNoSessionsHint":"No session history for this channel yet. Send a message or enter a custom peer id below.","channelsCustomPeerHint":"If set, overrides the session picker. Supports * globs; see session routing docs.","channelsCustomPeerPlaceholder":"e.g. 12345 or *","addBinding":"Add binding","removeBinding":"Remove","cronTitle":"Scheduled jobs","cronHint":"Isolated cron jobs can pin an agent id for the session key. Jobs without an agent id use the default agent and appear when that agent is selected.","cronLoading":"Loading cron jobs…","cronNone":"No matching jobs.","cronColSchedule":"Schedule","cronColMessage":"Message","cronColSession":"Session","cronColAgent":"Agent","cronAgentDefault":"Default agent","cronAgentClear":"Reset to default","navIdentity":"Identity","navProfile":"About You","navPersona":"Persona","navTools":"Tools","navSkills":"Skills","navCoreFiles":"Profile Markdown","navAdvanced":"Advanced","listSearchPlaceholder":"Search by name, id, or workspace","listEmpty":"No agents match your search.","listNoAgentsYet":"No agents yet. Create one to get started.","listNewAgentCard":"New agent","listChatWithAgent":"Chat","defaultMainAgentName":"Smart Assistant","defaultMainAgentDescription":"Your personal intelligent assistant for answering questions, handling everyday tasks, and chatting with you anytime.","editorNavAria":"Agent editor sections","skillsLibraryLink":"Skill library","personaHint":"Set up your agent's identity and personality with a friendly form. For raw Markdown, use Profile Markdown.","personaSectionIdentity":"Agent Identity","personaSectionIdentityHint":"How your agent presents itself","personaSectionUser":"About You","personaSectionUserHint":"Help your agent know you better","personaSectionSoul":"Personality & Style","personaSectionSoulHint":"Define how your agent communicates","personaName":"Name","personaNamePlaceholder":"e.g. Aria, Nova, Kai…","personaCreature":"Type","personaCreaturePlaceholder":"Custom type…","personaVibe":"Vibe","personaVibePlaceholder":"Custom vibe…","personaEmoji":"Emoji","personaEmojiPlaceholder":"e.g. 🤖 ✨ 🧠","personaAvatar":"Avatar","personaAvatarPlaceholder":"URL or workspace path","avatarPickerTitle":"Agent avatar","avatarOpenSettingsAria":"Open agent avatar settings","avatarRowHint":"Pick a style or upload a custom image.","avatarUploadCustom":"Upload custom image","avatarStyleAdventurer":"Adventurer","avatarStyleRobot":"Robot","avatarStyleLorelei":"Lorelei","avatarStyleThumbs":"Thumbs","avatarStyleFunEmoji":"Fun Emoji","avatarMore":"More","avatarUploading":"Uploading…","avatarUploadFailed":"Upload failed. Try a smaller PNG, JPEG, or WebP.","avatarInvalidImage":"Use a PNG, JPEG, or WebP image.","avatarTooLarge":"Image must be at most 512 KB.","personaCallName":"What to call you","personaCallNamePlaceholder":"e.g. Michael","personaPronouns":"Pronouns","personaPronounsPlaceholder":"e.g. he/him, she/her, they/them","personaTimezone":"Timezone","personaTimezoneDetect":"Detect","personaTimezoneCustom":"Custom timezone…","personaNotes":"Notes","personaNotesPlaceholder":"Anything else your agent should know about you…","personaSoulTemplate":"Personality template","personaSoulCustomEdit":"Edit personality (Markdown)","personaSoulPreview":"Preview","personaSoulEdit":"Edit","personaMemoryNote":"Your agent will automatically remember preferences you share in conversation (like favorite foods or habits). No need to add those here.","personaSaving":"Saving…","personaSaved":"Saved","footerSaveNotApplicable":"Use actions in this section; the bar Save applies to Identity, Tools, Skills, and Profile Markdown.","presetSetupBadge":"Quick Setup","presetSetupTitle":"Get Started with Preset Agents","presetSetupSubtitle":"Choose agents to create. Each comes with a tailored personality and workspace. You can customize them later.","presetSkip":"Skip for now","presetCreateSelected":"Create {{count}} Agent(s)","presetCreating":"Creating…","presetCreatingProgress":"Creating agent {{current}} of {{total}}…","presetSetupComplete":"Agents created successfully!","presetCreateFailed":"Failed to create {{name}}: {{message}}"}`),goalsSettings:{title:`Goal judge (/goal)`,hint:`Defaults for persistent goal missions and the judge model that scores progress.`,save:`Save`,discard:`Discard`,saving:`Saving…`,saveError:`Failed to save goal settings`,maxTurns:`Max turns per run`,judgeModelRef:`Judge model`,judgeModelRefPlaceholder:`Use agent default (optional)`,judgeModelRefHint:`Optional. When unset, goal runs use each agent's configured model.`,judgeModelRefUseDefault:`Use agent default`,checklistMode:`Checklist mode`,parseFailures:`Max consecutive parse failures`,judgeTimeoutSec:`Judge timeout (seconds)`,checklistHistoryChars:`Checklist history chars`,checklistHistoryCharsHint:`Max characters of transcript history sent to the judge in checklist mode.`}},Ce={appsPage:{title:`Apps`,subtitle:`Marketplace, built-ins, and user extensions (CLI / store install to ~/.xopc/extensions). URL: ?tab=marketplace | builtin | user.`,tabMarketplace:`Marketplace`,tabBuiltin:`Built-in`,tabUser:`Installed`,appsNavAria:`Apps sections`,emptyBuiltin:`No built-in extensions were discovered by the gateway (check gateway logs and dist/extensions manifests).`,emptyUser:`No user-installed extensions found. Install from the marketplace or CLI into ~/.xopc/extensions.`,searchPlaceholder:`Search apps`,noSearchResults:`No apps match your filters.`,statusEnabled:`Enabled`,cardNoDescription:`No description in manifest.`,badgeKindUi:`UI`,badgeKindBackend:`Backend`,badgeBundled:`Built-in`,cardTooltipHasUi:`Declares Gateway console UI (pages or settings).`,cardTooltipNoUi:`No Gateway UI; may still expose tools, hooks, or channels.`,badgeSourceGlobal:`Global`,badgeSourceWorkspace:`Workspace`,badgeSourceOther:`Other`,detailTitle:`App details`,detailBack:`Back`,detailClose:`Close`,detailProviderPrefix:`Source:`,providerBundled:`Built-in (shipped with xopc)`,providerGlobal:`Global install (~/.xopc/extensions)`,providerWorkspace:`Workspace (.extensions)`,providerOther:`Other`,detailSectionFeatures:`Capabilities`,detailNoDescription:`No description was provided for this extension.`,restartNote:`Some extension changes require restarting the gateway for code to fully load.`,cliManageHint:`This copy is not bundled with xopc — install, remove, and upgrades are done via the CLI or filesystem.`,builtinConfigHint:`Channels and image provider keys are managed under Settings → Channels and Settings → Images.`,builtinRuntimeToggle:`Gateway runtime`,builtinToggleEnable:`Enable`,builtinToggleDisable:`Disable`,builtinToggleBusy:`Saving…`,builtinToggleFailed:`Could not update built-in extension.`,builtinToggleRestartHint:`Restart the gateway so extension code fully loads or unloads.`,backendOnlyHint:`This extension has no Gateway UI; tools and hooks still run when enabled.`,badgePages:`{{count}} page(s)`,badgeSettings:`{{count}} settings`,badgeWidgets:`{{count}} widget(s)`,badgeSidebar:`{{count}} sidebar`,open:`Open`,openSettings:`Settings`,runStateLive:`Running`,runStatePendingOn:`Enabled in config`,runStatePendingOff:`Disabled in config`,runStateOff:`Off`,marketplaceSearchPlaceholder:`Search extensions…`,marketplaceEmpty:`No extensions from xopc-store.`,marketplaceLoadFailed:`Failed to load marketplace.`,marketplaceDetailTitle:`Extension details`,marketplaceDetailLoadFailed:`Could not load package details.`,marketplaceDetailReadmeHeading:`Readme`,marketplaceNoReadme:`No readme was published for this package.`,marketplaceAuthor:`Author`,marketplaceVersion:`Version`,marketplaceDownloads:`Downloads`,marketplaceInstall:`Install`,marketplaceReinstall:`Reinstall`,marketplaceInstalled:`Installed`,marketplaceUninstall:`Uninstall`,marketplaceUninstallConfirm:`Remove this extension from disk and disable it in config? Restart the gateway if it stays listed.`,marketplaceReinstallConfirm:`Overwrite the existing install with the marketplace version?`,marketplaceInstallFailed:`Install failed.`,marketplaceUninstallFailed:`Uninstall failed.`,marketplaceRestartHint:`Restart the gateway to fully apply channel plugins or unload removed code.`,marketplaceBuiltin:`Built-in`,marketplaceBuiltinManageHint:`This package ships with xopc — it is not installed from the store. Use the Built-in tab to open its UI or change enablement.`,marketplaceBuiltinGoBuiltin:`Open Built-in tab`},extensionUi:{permissionTitle:`Allow “{{name}}”?`,permissionSubtitle:`This extension may use the following capabilities while its UI is open.`,permissionsNone:`No additional permissions are declared in the manifest.`,allow:`Allow`,deny:`Not now`,deniedHint:`The extension UI stays hidden until you approve it for this browser.`,reviewPermissions:`Review permissions`,loadFailed:`The extension panel failed to load.`,loadFailedConnectionHint:`If the frame shows “connection refused”, start the xopc gateway (and if you use Vite for web/, match the proxy target in web/vite.config.ts).`,retryLoad:`Reload panel`},extensionDebug:{nav:`Extension debug`,title:`Extension debug`,subtitle:`Inspect discovered extensions, declared permissions, and browser UI approval state.`,grantsHeading:`UI approval storage`,grantsHint:"Key `xopc.extensionUiGrants.v1` in localStorage — fingerprints of permission lists you approved per extension.",refresh:`Refresh`,listHeading:`Extensions from gateway`,colId:`Id`,colName:`Name`,colPermissions:`Manifest permissions`,futureHeading:`Coming later`,futureBody:`PostMessage capture, per-extension storage preview, and live permission overrides are planned for a future iteration.`}},we={channelsSettings:{needToken:`Save a gateway token to edit channel settings.`,subtitle:`Telegram, Weixin, and Feishu inbound channels. Changes are written to the gateway config file.`,docsLink:`Channel documentation`,refresh:`Refresh`,loadError:`Failed to load channel settings`,loading:`Loading…`,save:`Save`,discard:`Discard`,saving:`Saving…`,saved:`Saved`,saveError:`Failed to save`,retry:`Retry`,unsavedHint:`You have unsaved changes.`,hubConfigureButton:`Configure`,hubConnectedBadge:`Connected`,hubStatusRunning:`Running`,hubStatusOffline:`Not connected`,hubStatusDisabled:`Disabled`,hubStatusNotConfigured:`Not configured`,hubManageButton:`Manage channel`,hubSetupButton:`Set up`,hubFixButton:`Check configuration`,hubPairingButton:`Review pairing`,hubSummaryDm:`DM: {{policy}}`,hubSummaryStream:`Streaming: {{mode}}`,hubSummaryConnection:`Connection: {{mode}}`,hubSummaryAccountCount:`{{count}} account(s)`,hubConnectionWebsocket:`WebSocket`,hubConnectionWebhook:`Webhook`,hubViewDocs:`View documentation`,hubExtensionSubtitle:`Extension channel registered on the gateway.`,hubExtensionConfiguredHint:`Configuration present in gateway config`,hubExtensionManageHint:`This channel is provided by an extension. Configure it in the extension settings or gateway config file.`,hubExtensionStatusLabel:`Status`,hubExtensionEnabledLabel:`Enabled in config`,hubExtensionConnectedLabel:`Runtime connected`,hubExtensionYes:`Yes`,hubExtensionNo:`No`,enableChannelAria:`Enable or disable this channel`,modalCancel:`Cancel`,telegramTitle:`Telegram`,telegramSubtitle:`Bot token, allowlists, and optional multi-account JSON.`,weixinTitle:`Weixin`,weixinSubtitle:`Sign in with WeChat via QR (browser or CLI), then enable below. Credentials stay on the gateway host.`,feishuTitle:`Feishu/Lark`,feishuSubtitle:`Feishu app credentials, policies, and optional multi-account JSON.`,enableTelegramAria:`Enable Telegram channel`,enableWeixinAria:`Enable Weixin channel`,enableFeishuAria:`Enable Feishu channel`,telegramToken:`Bot token`,telegramTokenDesc:`From BotFather. Stored in the gateway config.`,feishuAppId:`App ID`,feishuAppIdDesc:`From Feishu developer console (cli_xxx). Stored in the gateway config.`,feishuAppSecret:`App secret`,feishuAppSecretDesc:`From Feishu developer console. Stored in the gateway config.`,feishuDomain:`Domain`,connectionMode:`Connection mode`,connectionModeDesc:`websocket: Socket Mode. webhook: local HTTP server receives events.`,renderMode:`Render mode`,enableStreaming:`Enable streaming`,requireMention:`Require @mention in groups`,reactionNotifications:`Reaction notifications`,allowFromDm:`Allow from (DM)`,allowFromDmDesc:`Static allowlist in config (comma-separated user IDs). Paired users from credential files are listed below.`,pairingTitle:`DM pairing`,pairingSubtitle:`When DM policy is pairing, new users message the bot to receive a code. Approve here — no CLI required.`,pairingSetupHint:`Send any message to your bot in Telegram, then enter the 8-character code below.`,pairingPendingTitle:`Pending requests`,pairingPendingEmpty:`No pending requests. Message the bot to start pairing.`,pairingCodePlaceholder:`Pairing code`,pairingApprove:`Approve`,pairingApproving:`Approving…`,pairingApproved:`Approved user {{id}}.`,pairingInvalid:`Invalid or expired pairing code.`,pairingLoadError:`Could not load pairing state.`,pairingRefresh:`Refresh`,pairingExpiresHint:`Expires {{time}}`,pairingCodeHint:`Code ends with {{suffix}}`,pairedTitle:`Allowed users`,pairedFromConfig:`Config allowlist`,pairedFromCredentials:`Paired (credential store)`,pairedEmpty:`None`,pairingAccountLabel:`Bot account`,pairingAccountNotPairing:`Account "{{account}}" does not use pairing DM policy. Select another account or change its dmPolicy in Advanced JSON.`,pairingRevokeAria:`Revoke pairing for {{id}}`,pairingRevoked:`Revoked pairing for {{id}}.`,pairingRevokeError:`Could not revoke pairing.`,hubPairingPendingBadge:`{{count}} pending`,telegramSetupStepToken:`1. Save bot token and enable Telegram`,telegramSetupStepPairing:`2. Message your bot, then approve the pairing code below`,pairingQuickApprove:`Quick approve`,pairingQuickApproveHint:`Quick approve skips the pairing code — only use it when you have verified the user id matches someone who messaged your bot.`,pairingDismiss:`Dismiss`,pairingDismissing:`Dismissing…`,pairingDismissed:`Dismissed pending request for {{id}}.`,pairingDismissError:`Could not dismiss pending request.`,pairingStaleItem:`Stale`,advancedShow:`Advanced options`,advancedHide:`Hide advanced options`,apiRoot:`API root`,proxy:`Proxy`,dmPolicy:`DM policy`,groupPolicy:`Group policy`,replyToMode:`Reply-to mode`,streamMode:`Stream mode`,allowFromGroups:`Allow from (groups)`,allowFromGroupsDesc:`Comma-separated group chat IDs (when group policy is allowlist).`,historyLimit:`History limit`,textChunkLimit:`Text chunk limit`,telegramDebug:`Debug mode`,multiAccountJson:`Multi-account (JSON)`,multiAccountJsonDesc:`Optional. Per-account botToken or tokenFile, policies, and groups. Empty {} uses the single token above only.`,weixinQuickStartTitle:`Quick start`,weixinStepLogin:`Use “Sign in with WeChat (QR)” below in this console, or see Channel documentation for CLI login.`,weixinStepEnable:`Turn on Weixin below and save.`,weixinStepPairing:`After QR login, DMs work immediately. Use allowlist DM policy only if you want to restrict who can message the bot.`,weixinAdvancedHint:`Optional: allowlist, route tag, streaming, and per-account JSON—only if you need them.`,weixinAllowFrom:`Allow from`,weixinAllowFromDesc:`When DM policy is allowlist: comma-separated wxid / openid. Default pairing allows all contacts after QR login.`,weixinRouteTag:`Route tag`,weixinRouteTagDesc:`Optional tag for routing; numeric or string.`,routeTagPlaceholder:`e.g. tag name or number`,weixinDebug:`Debug mode`,weixinDebugDesc:`Extra logging for the Weixin channel.`,weixinAccountsJson:`Accounts (JSON)`,weixinAccountsJsonDesc:`Per-account name, CDN base URL, route tag, and policies.`,weixinQrLoginTitle:`Browser QR login`,weixinQrLoginDesc:`Starts a login on the gateway. Scan with WeChat; when it succeeds, settings refresh automatically.`,weixinQrLoginButton:`Sign in with WeChat (QR)`,weixinQrLoginBusy:`Starting…`,weixinQrLoginScanned:`Scanned — confirm in WeChat`,weixinQrLoginSuccess:`Weixin connected.`,weixinQrLoginCancel:`Dismiss QR`,weixinQrImageError:`Could not render the QR code here. You can open the link in a new tab, or tap Regenerate to try again.`,weixinQrOpenLink:`Open in new tab`,weixinQrEncoding:`Rendering QR…`,weixinQrModalTitle:`Scan to sign in`,weixinQrModalSubtitle:`Use WeChat to scan the QR code below to connect.`,weixinQrRegenerate:`Regenerate QR code`,weixinQrModalCloseAria:`Close`,feishuQrModalTitle:`Scan to create app`,feishuQrModalSubtitle:`Starts with China (Feishu). Use the switch below the QR to use International (Lark). Expand Advanced options for manual credentials and policies.`,feishuQrCloseAria:`Close`,feishuRegionSwitchAria:`Registration region`,feishuRegionChina:`China (Feishu)`,feishuRegionInternational:`International (Lark)`,feishuAdvancedHint:`Optional: App ID / Secret from the developer console, connection mode, webhook, tools, routing, and multi-account JSON. Save writes to the gateway config.`,feishuQrStarting:`Starting…`,feishuQrScanHint:`Scan this QR code with Feishu/Lark on your phone.`,feishuQrEncoding:`Generating QR…`,feishuQrImageError:`Could not generate QR image.`,feishuQrOpenLink:`Open link in browser`,feishuQrRegenerate:`Regenerate QR`,feishuQrSetupSuccess:`Feishu app created and configured.`,agentRoutingTitle:`Agent routing`,agentRoutingHint:"Maps each channel account to an agent via config `bindings`. Inbound messages use a session key for that agent.",agentRoutingAccountLabel:`Account`,agentRoutingAgentLabel:`Agent`,jsonObjectAccounts:`Accounts must be a JSON object`,jsonInvalid:`Invalid JSON`,copy:`Copy`,copied:`Copied`,show:`Show`,hide:`Hide`,webhookTitle:`Webhook settings`,verificationToken:`Verification token`,verificationTokenDesc:`From Feishu event subscription settings (webhook mode).`,encryptKey:`Encrypt key`,encryptKeyDesc:`From Feishu event subscription settings (webhook mode).`,webhookHost:`Webhook host`,webhookPort:`Webhook port`,webhookPath:`Webhook path`,webhookPathDesc:`Request URL path configured in Feishu event subscription.`,feishuToolsTitle:`Feishu tools`,feishuToolsDesc:`Enable only what you need. Each tool may require additional app scopes.`,feishuToolDoc:`Doc (feishu_doc)`,feishuToolWiki:`Wiki (feishu_wiki)`,feishuToolDrive:`Drive (feishu_drive)`,feishuToolPerm:`Permissions (feishu_perm)`,feishuToolBitable:`Bitable (feishu_bitable_*)`,feishuToolScopes:`Scopes check (feishu_app_scopes)`,feishuActionsTitle:`Feishu actions`,feishuActionReactions:`Enable reaction actions`,policy:{dm:{pairing:`Pairing`,allowlist:`Allowlist`,open:`Open`,disabled:`Disabled`},group:{open:`Open`,disabled:`Disabled`,allowlist:`Allowlist`},reply:{off:`Off`,first:`First`,all:`All`},stream:{off:`Off`,partial:`Partial`,block:`Block`}}},voiceSettings:{needToken:`Save a gateway token to edit voice settings.`,subtitle:`Speech-to-text and text-to-speech for channels. Keys can also be set via environment variables.`,docsLink:`Voice documentation`,loadError:`Failed to load voice settings`,loading:`Loading…`,save:`Save`,discard:`Discard`,saving:`Saving…`,saved:`Saved`,saveError:`Failed to save`,retry:`Retry`,unsavedHint:`You have unsaved changes.`,apiKeyMaskedHelp:`Saved keys are hidden. Click the eye to load the key from your config file (not from environment variables).`,apiKeyCopy:`Copy`,apiKeyCopied:`Copied`,apiKeyShow:`Show`,apiKeyHide:`Hide`,apiKeyNotInConfigFile:`No key stored in the config file for this provider (check environment variables).`,apiKeyRevealFailed:`Could not load key from config.`,stt:{title:`Speech-to-text (STT)`,description:`Transcribe inbound voice using Alibaba DashScope or OpenAI Whisper.`,enable:`Enable STT`,enableDesc:`When on, voice messages can be transcribed for the agent.`,provider:`STT provider`,alibaba:`Alibaba DashScope`,openai:`OpenAI`,apiKey:`API key`,apiKeyDesc:`Optional if the key is already in the environment.`,model:`Model`,fallback:`Fallback between providers`,fallbackDesc:`Try the other provider if the primary request fails.`},tts:{title:`Text-to-speech (TTS)`,description:`Synthesize assistant replies as audio when enabled.`,enable:`Enable TTS`,enableDesc:`When on, TTS runs according to the trigger mode below.`,trigger:`Trigger`,triggerOff:`Off`,triggerAlways:`Always`,triggerInbound:`Inbound voice only`,triggerTagged:`Tagged ([[tts]])`,triggerDescOff:`TTS is completely disabled.`,triggerDescAlways:`Apply TTS to all assistant messages.`,triggerDescInbound:`Only reply with voice when the user sends voice.`,triggerDescTagged:`Only when the [[tts]] directive is used.`,provider:`TTS provider`,providerOpenai:`OpenAI TTS`,providerEdge:`Microsoft Edge (free)`,providerLocalCli:`Local CLI (offline)`,voice:`Voice`,edgeHint:`Microsoft Edge TTS — no API key required.`,localCli:{command:`CLI command`,commandDesc:`Shell template; placeholders: {{Text}}, {{OutputBase}}.`,commandPlaceholder:`mlx_audio.tts.generate --text "{{Text}}" --file_prefix {{OutputBase}}`,cwd:`Working directory`,cwdDesc:`Optional. Defaults to the gateway working directory.`,outputFormat:`Output format`,outputFormatDesc:`File extension produced by the CLI (mp3, wav, opus, …).`,timeoutMs:`Timeout (ms)`,timeoutMsDesc:`Per-call timeout override; leave blank to inherit the TTS default.`,hint:"Provided by the bundled `tts-local-cli` extension. Enable the extension and configure the binary on PATH."}},notes:{title:`Note`,duration:`Long audio is split automatically; quality depends on provider and model.`,envVars:`Environment variables: DASHSCOPE_API_KEY, OPENAI_API_KEY (when not set in this form).`}},gatewaySettings:{needToken:`Save a gateway token to load and edit gateway options.`,subtitle:`HTTP API access token and listen address. Values are stored in the gateway config file.`,tabsAriaLabel:`Gateway settings categories`,tabNetwork:`Network`,tabAccess:`Access`,tabUpdates:`Updates`,tabSecurity:`Security`,tabAdvanced:`Advanced`,networkTabHint:`Configure listen address, port, and allowed CORS origins.`,accessTabHint:`Configure token, password, trusted proxy, and failed-auth rate limiting.`,updatesTabHint:`Configure release channel, startup checks, and automatic update policy.`,docsLink:`Gateway documentation`,loadError:`Failed to load gateway settings`,loading:`Loading…`,save:`Save`,discard:`Discard`,saving:`Saving…`,saved:`Saved`,saveError:`Failed to save`,retry:`Retry`,unsavedHint:`You have unsaved changes.`,tokenExpired:`Your session token was rejected. Update the client token or fix the access token in config.`,updateToken:`Update client token`,changeToken:`Open token dialog`,accessToken:`Gateway access token`,tokenPlaceholder:`Token stored in config (optional if using env)`,tokenHelp:`Used to authenticate HTTP/WebSocket API requests. You can also set XOPC_GATEWAY_TOKEN.`,copy:`Copy`,copied:`Copied`,show:`Show`,hide:`Hide`,listenHost:`Listen address`,bindMode:`Bind mode`,bindLoopback:`Loopback (127.0.0.1)`,bindLan:`LAN (0.0.0.0)`,bindAuto:`Auto`,bindCustom:`Custom IPv4`,bindTailnet:`Tailnet (Tailscale IP)`,customBindHost:`Custom bind address`,customBindHostPlaceholder:`192.168.1.10`,listenPort:`Port`,listenHint:`Bind mode controls which network interfaces the gateway listens on. Auto: binds to 0.0.0.0 inside containers, 127.0.0.1 on host machines. Use LAN only with token auth and explicit CORS origins. Restart after saving.`,restartHint:`Changes to listen address, authentication, or CORS require a gateway restart.`,restartGatewayButton:`Restart Gateway`,restartGatewayConfirm:`Restarting the gateway will interrupt all active connections. Continue?`,restartGatewayFailed:`Restart failed`,authMode:`Authentication mode`,authModeToken:`Token`,authModePassword:`Password`,authModeTrustedProxy:`Trusted proxy`,authModeNoneLabel:`None`,authModeNone:`Auth mode is set to none — API requests are not authenticated.`,authModeTrustedProxyHint:`Reverse proxy handles login and forwards user identity headers. Configure trusted proxy CIDRs and headers below. Restart after saving.`,authPassword:`Gateway password`,authPasswordPlaceholder:`Password stored in config (optional if using env)`,authPasswordHelp:`Used when auth mode is password. You can also set XOPC_GATEWAY_PASSWORD.`,rateLimitTitle:`Failed authentication rate limit`,rateLimitHint:`Limits repeated failed auth attempts per client IP.`,rateLimitEnabled:`Enable rate limiting`,rateLimitExemptLoopback:`Exempt loopback clients (127.0.0.1)`,rateLimitMaxAttempts:`Max attempts`,rateLimitWindowMinutes:`Window (minutes)`,rateLimitBlockMinutes:`Block duration (minutes)`,updateChannel:`Update channel`,channelStable:`Stable`,channelBeta:`Beta`,channelDev:`Dev`,updateChannelHint:`Beta and dev receive builds earlier; stable is recommended for daily use.`,updateAutoSection:`Automatic updates`,updateAutoSectionHint:`Controls npm/CLI update checks on gateway start and background auto-update scheduling.`,updateCheckOnStart:`Check for updates on start`,updateCheckOnStartHint:`When enabled, the gateway checks for newer packages when it starts.`,updateAutoEnabled:`Enable automatic updates`,updateAutoEnabledHint:`When enabled, eligible stable/beta builds may be applied automatically after the delay below.`,updateAutoStableDelayHours:`Stable delay (hours)`,updateAutoStableDelayHoursHint:`Minimum hours after a stable release before auto-update may run.`,updateAutoStableJitterHours:`Stable jitter (hours)`,updateAutoStableJitterHoursHint:`Random extra wait up to this many hours to spread update load.`,updateAutoBetaCheckIntervalHours:`Beta check interval (hours)`,updateAutoBetaCheckIntervalHoursHint:`How often to poll for beta builds when on the beta channel.`,corsOrigins:`CORS allowed origins`,corsOriginsHint:`Exact browser origins (scheme + host + port), e.g. http://localhost:5173. Leave empty to use built-in localhost defaults. Restart the gateway after saving.`,corsOriginsEmpty:`No custom origins — gateway uses localhost defaults for this port and Vite dev (3000).`,corsOriginsPlaceholder:`Add origin and press Enter`,corsOriginsWildcardWarning:`Wildcard "*" allows any website to call the API from a browser. Use only if you understand the risk.`,securitySection:`Network security`,securitySectionHint:`OpenClaw-aligned guards for LAN and reverse-proxy deployments. Restart after saving.`,securityStrict:`Strict security mode`,securityStrictHint:`When enabled, network-accessible binds require explicit failed-auth rate limiting configuration.`,dangerouslyAllowHostHeaderOriginFallback:`Allow Host-header origin fallback`,dangerouslyAllowHostHeaderOriginFallbackHint:`Dangerous: treat the HTTP Host header as an allowed browser origin when not listed in CORS. Prefer explicit corsOrigins.`,dangerouslyAllowHostHeaderOriginFallbackWarning:`Host-header fallback weakens browser origin checks. Use only behind a trusted reverse proxy with strict Host validation.`,trustedProxies:`Trusted proxy CIDRs`,trustedProxiesHint:`IP addresses or CIDR ranges of reverse proxies allowed to terminate trusted-proxy auth (e.g. 127.0.0.1/32, 10.0.0.0/8). Required on network binds.`,trustedProxiesEmpty:`No trusted proxies configured.`,trustedProxiesPlaceholder:`CIDR or IP and press Enter`,allowRealIpFallback:`Allow X-Real-IP fallback`,allowRealIpFallbackHint:`When X-Forwarded-For parsing fails, fall back to X-Real-IP. Default is fail-closed (disabled).`,trustedProxyUserHeader:`User identity header`,trustedProxyUserHeaderPlaceholder:`X-Forwarded-User`,trustedProxyUserHeaderHint:`HTTP header set by the reverse proxy with the authenticated user identity.`,trustedProxyRequiredHeaders:`Required proxy headers`,trustedProxyRequiredHeadersHint:`Additional headers that must be present on every request (e.g. X-Proxy-Auth).`,trustedProxyAllowUsers:`Allowed users`,trustedProxyAllowUsersHint:`When non-empty, only these user identities are accepted. Leave empty to allow any non-empty user header value.`,trustedProxyAllowLoopback:`Allow loopback proxy source`,trustedProxyAllowLoopbackHint:`Accept trusted-proxy auth when the TCP connection comes from 127.0.0.1 (same-host reverse proxy).`,validationErrorNetworkAuth:`Network-accessible gateway requires authentication.`,validationErrorTrustedProxies:`Trusted-proxy auth requires at least one trusted proxy CIDR on network binds.`,validationErrorUserHeader:`Trusted-proxy auth requires a user identity header name.`,validationErrorCors:`Network-accessible gateway requires CORS origins or Host-header fallback.`,validationErrorCorsWildcard:`CORS wildcard is not allowed on network binds.`,validationErrorCustomBind:`Custom bind mode requires a bind address.`,securityAuditTitle:`Security audit`,securityAuditSubtitle:`Live check of saved gateway configuration (same as xopc doctor --security).`,securityAuditSavedConfigHint:`Reflects the config file on disk. Save form changes and restart the gateway to update results.`,securityAuditRefresh:`Refresh`,securityAuditLoading:`Running security audit…`,securityAuditLoadError:`Security audit failed`,securityAuditStatusPass:`No critical issues`,securityAuditStatusWarn:`Recommendations`,securityAuditStatusFail:`Critical issues`,securityAuditStatusSkip:`Audit skipped`,securityAuditNoFindings:`No structured findings; configuration passes gateway security guards.`,securityAuditHintsTitle:`Additional notes`,securityAuditRemediation:`Fix:`,advancedSection:`Advanced`,advancedSectionHint:`Runtime limits and channel startup ordering. Restart the gateway after saving.`,maxSseConnections:`Max SSE connections`,maxSseConnectionsHint:"Upper bound for concurrent Server-Sent Events clients (`GET /api/events` and similar). Default 100.",channelConnectDeferMode:`Channel connect defer`,channelConnectDeferModeAuto:`Auto (plugin default)`,channelConnectDeferModeOff:`Off (start all channels before listen)`,channelConnectDeferModeExplicit:`Explicit list`,channelConnectDeferModeHint:"Controls when outbound-heavy channels call `start()` relative to HTTP listen. Auto defers plugins that opt in (e.g. Telegram, Weixin, Feishu).",channelConnectDeferIds:`Defer channel ids`,channelConnectDeferIdsHint:`Used when mode is Explicit. These plugin ids start after HTTP listen (max 24). Empty means defer none.`,channelConnectDeferSkipIds:`Skip defer ids`,channelConnectDeferSkipIdsHint:`Removed from the defer set after auto or explicit resolution (max 24). Example: keep Telegram on phase 1 but defer others.`,channelIdListPlaceholder:`Channel id and press Enter (e.g. telegram)`,channelIdListEmpty:`No ids configured.`},heartbeatSettings:{needToken:`Save a gateway token to load and edit heartbeat options.`,subtitle:`Periodic agent wake, optional delivery to a channel, and HEARTBEAT.md under the default agent's profile directory. Stored in the gateway config file and agents/<id>/profile/.`,docsLink:`Heartbeat documentation`,loadError:`Failed to load heartbeat settings`,loading:`Loading…`,saveConfig:`Save`,discard:`Discard`,savingConfig:`Saving…`,savedConfig:`Configuration saved`,saveConfigError:`Failed to save configuration`,triggerNow:`Run now`,triggering:`Queuing…`,triggered:`Heartbeat queued`,triggerError:`Failed to trigger heartbeat`,triggerHint:`Queues one heartbeat run (same as the timer). Skipped if HEARTBEAT.md is empty, outside active hours, or heartbeat is disabled.`,saveDoc:`Save`,savingDoc:`Saving…`,savedDoc:`Document saved`,saveDocError:`Failed to save HEARTBEAT.md`,retry:`Retry`,unsavedConfig:`You have unsaved configuration changes.`,unsavedDoc:`You have unsaved changes to HEARTBEAT.md.`,workspaceLabel:`Workspace`,tabsAriaLabel:`Heartbeat settings categories`,tabSchedule:`Schedule`,tabDelivery:`Delivery`,tabPrompt:`Prompt`,tabDocument:`HEARTBEAT.md`,scheduleTabHint:`Control whether heartbeat runs, how often it runs, and active hours.`,deliveryTabHint:`Choose the channel and conversation to deliver replies to; leave empty to only log them.`,promptTabHint:`Tune the heartbeat system prompt, silent-reply threshold, and session isolation.`,documentTabHint:`Maintain the tasks and reminders read on each heartbeat.`,configSection:`Heartbeat configuration`,docSection:`HEARTBEAT.md`,docHint:`Tasks and reminders read by the agent on each heartbeat. Leave empty or comment-only to skip LLM calls and save tokens.`,enable:`Enable heartbeat`,includeSystemPromptSection:`Include heartbeat instructions in chat system prompt`,includeSystemPromptSectionHint:`When off, heartbeat instructions are only sent during scheduled heartbeat turns (saves tokens in normal chat).`,interval:`Interval`,intervalHint:`Minimum 1 second. Saved to the gateway as milliseconds.`,intervalHintPreset:`Quick preset or type seconds in the field.`,intervalSecondsLabel:`Seconds`,intervalPresets:{custom:`Custom`,every30s:`Every 30 seconds`,every1min:`Every 1 minute`,every5min:`Every 5 minutes`,every10min:`Every 10 minutes`,every15min:`Every 15 minutes`,every30min:`Every 30 minutes`,every1h:`Every 1 hour`,every2h:`Every 2 hours`},deliveryTitle:`Delivery (optional)`,channelNone:`— None —`,customChannelSuffix:`custom`,deliveryHint:`Both channel and chat id are required to send non-silent replies somewhere. Otherwise the reply is only logged.`,prompt:`Custom system prompt (optional)`,promptPlaceholder:`Override the default heartbeat instruction…`,promptHint:`Leave empty to use the built-in default prompt.`,ackMaxChars:`Max reply length before treating as silent (ackMaxChars)`,ackMaxCharsHint:`Leave empty for server default (300).`,ackDefaultPlaceholder:`Default`,isolatedSession:`Use a fresh session key each run`,isolatedSessionHint:`Avoids mixing heartbeat context with the main chat session.`,activeHoursTitle:`Active hours (optional)`,activeStart:`Start`,activeEnd:`End`,activeTimezone:`Timezone (IANA)`,activeHoursHint:`Restrict heartbeats to this window. Clear to run any time.`,addActiveHours:`Add active hours`,clearActiveHours:`Clear active hours`},webSearchSettings:{title:`Web search`,subtitle:`Configure region and search providers for the web_search tool. Without API keys, a built-in HTML fallback is used.`,docsLink:`Gateway documentation`,needToken:`Save a gateway token to edit web search settings.`,loading:`Loading…`,loadError:`Failed to load web search settings`,save:`Save`,discard:`Discard`,saving:`Saving…`,saved:`Saved`,saveError:`Failed to save`,unsavedHint:`You have unsaved changes.`,sectionRegion:`Region`,sectionRegionHint:`Controls which zero-config HTML fallback is used when no API provider succeeds (China → Bing; otherwise DuckDuckGo).`,sectionSearch:`Search providers`,sectionSearchHint:`Providers are tried in order. Keys are stored in the gateway config file. Leave the list empty to use only the HTML fallback.`,sectionBlocklist:`Domain blocklist`,sectionBlocklistHint:`When enabled, web_search and web_extract skip URLs whose host matches these domains (exact or suffix match).`,blocklistEnabled:`Enable domain blocklist`,blocklistEnabledDesc:`Blocks matching hosts before fetch; useful for privacy or compliance.`,blocklistDomains:`Blocked domains`,blocklistDomainsDesc:`One domain per line (e.g. example.com). Subdomains of listed domains are also blocked.`,blocklistDomainsPlaceholder:`example.com
2
+ ads.example.net`,regionLabel:`Fallback region`,regionDesc:`Auto uses your system timezone. Override if you are on a VPN or need a specific fallback.`,regionAuto:`Auto (timezone)`,regionCn:`China (Bing HTML fallback)`,regionGlobal:`Global (DuckDuckGo HTML fallback)`,maxResultsLabel:`Default max results`,maxResultsDesc:`Used when the model does not pass a count (1–50).`,providersTitle:`Providers (ordered)`,addProvider:`Add provider`,apiKeyLabel:`API key`,apiKeyDesc:`Optional for some setups. Leave masked to keep the saved value.`,urlLabel:`Instance URL`,urlDesc:`SearXNG base URL (e.g. http://localhost:8080). No trailing slash required.`,keyPlaceholder:`API key or env var name`,keyPlaceholderMasked:`•••••••• (unchanged)`,disabled:`Skip`,footerHint:`HTML fallbacks depend on third-party pages and may change. For production, use a supported search API (Brave, Tavily, Bing, or self-hosted SearXNG).`,providerTypes:{brave:`Brave Search API`,tavily:`Tavily`,bing:`Bing Web Search API`,searxng:`SearXNG`}}},Te={chat:JSON.parse(`{"typeMessage":"Type a message…","sendMessage":"Send","abort":"Abort","needToken":"Save a gateway token to chat.","loading":"Loading conversation…","model":"Model","modelPlaceholder":"Select a model…","agent":"Agent","agentPlaceholder":"Select an agent…","agentSearchPlaceholder":"Search agents…","agentNoMatches":"No matching agents","thinkingLevel":"Thinking","newSession":"New chat","welcomeTitle":"Welcome to xopc","welcomeDescription":"Send a message to get started","welcomeSpotlight":{"headline":"Your personal AI assistant, ready to help","tagline":"Just tell me what you need — I'll break it down, look things up, and get it done.","categories":[{"id":"work","icon":"documents","title":"Work & productivity","description":"Emails, reports, meeting notes","scenarios":[{"prompt":"Help me write a professional reply to an email declining a meeting invitation politely while suggesting an alternative time."},{"prompt":"Draft a concise weekly status update covering what I accomplished, what's in progress, and any blockers — keep it under 200 words."},{"prompt":"I have a meeting in 30 minutes. Help me prepare 5 key talking points and 3 questions I should ask about project timeline risks."}]},{"id":"research","icon":"globe","title":"Research & learning","description":"News, explanations, decisions","scenarios":[{"prompt":"What are the biggest tech news stories this week? Give me a quick summary of the top 3 with why they matter."},{"prompt":"Explain how RAG (Retrieval-Augmented Generation) works in simple terms, as if I'm explaining it to a non-technical manager."},{"prompt":"I'm choosing between Notion and Obsidian for personal note-taking. Compare them on features, pricing, and offline use, then recommend one for my case."}]},{"id":"content","icon":"content","title":"Writing & creation","description":"Posts, copy, translation","scenarios":[{"prompt":"Turn this idea into a LinkedIn post: AI tools are making individual contributors as productive as small teams. Keep it engaging and under 150 words."},{"prompt":"Rewrite the following paragraph to be more concise and punchy, suitable for a product landing page hero section."},{"prompt":"Translate this text to English and adjust the tone to sound natural for a global audience, not just a literal translation."}]},{"id":"data","icon":"folder","title":"Data & files","description":"Organize, analyze, automate","scenarios":[{"prompt":"Look at my Downloads folder and suggest how to organize it — group files by type and tell me what's safe to delete."},{"prompt":"I have a CSV with sales data. Help me find the top 5 products by revenue and spot any month-over-month trends."},{"prompt":"Create a simple daily planning template in Markdown: sections for top 3 priorities, meetings, notes, and end-of-day reflection."}]}]},"you":"You","assistant":"Assistant","tool":"Tool","thinkingLabel":"thinking…","thoughts":"Thoughts","thoughtsStreaming":"Thinking…","thoughtsExpandHint":"Expand to view model thoughts","thinkingLevelLabel":"Thinking","thinkingLevels":{"off":"Off","minimal":"Minimal","low":"Low","medium":"Medium","high":"High","xhigh":"X-High","adaptive":"Adaptive"},"toolInput":"Input","toolOutput":"Output","noOutput":"(no output)","viewSteps_one":"View {{count}} step","viewSteps_other":"View {{count}} steps","stepSearchedWeb":"Searched web","stepReadFile":"Read file","stepDetails":"Details","stepRunCommand":"Run command","stepListDirectory":"Browse folder","stepWriteFile":"Save file","stepEditFile":"Edit file","stepOpenUrl":"Open link","stepFetchUrl":"Fetch webpage","stepUnknownTool":"Running {{name}}","stepsClusterDone":{"search_one":"Searched the web","search_other":"Searched the web {{count}} times","readFile_one":"Read 1 file","readFile_other":"Read {{count}} files","editFile_one":"Edited 1 file","editFile_other":"Edited {{count}} files","writeFile_one":"Saved 1 file","writeFile_other":"Saved {{count}} files","runCommand_one":"Ran 1 command","runCommand_other":"Ran {{count}} commands","listDir_one":"Browsed 1 folder","listDir_other":"Browsed {{count}} folders","openUrl_one":"Opened 1 link","openUrl_other":"Opened {{count}} links","fetchUrl_one":"Fetched 1 page","fetchUrl_other":"Fetched {{count}} pages","other_one":"Ran 1 tool","other_other":"Ran {{count}} tools"},"stepsClusterIng":{"thinking":"Thinking…","search":"Searching the web…","readFile":"Reading files…","editFile":"Editing files…","writeFile":"Saving files…","runCommand":"Running command…","listDir":"Browsing folder…","openUrl":"Opening link…","fetchUrl":"Fetching page…","other":"Working…","mixed":"Working on it…"},"stepsClusterJoin":", ","stepsClusterJoinFinal":" and ","stepsClusterMoreSuffix":" and more","toolCard":{"copyPath":"Copy path","copyCommand":"Copy command","copied":"Copied","viewDiff":"View changes","hideDiff":"Hide changes","viewOutput":"View output","hideOutput":"Hide output","viewContent":"View content","hideContent":"Hide content","linesBadge":"{{count}} lines","linesPartial":"Loaded {{shown}} of {{total}} lines","diffStats":"+{{added}} −{{removed}}","sizeBadge":"{{size}}","exitCodeOk":"Exit 0","exitCodeNonZero":"Exit {{code}}","exitCodeUnknown":"Unfinished","timedOut":"Timed out","truncatedBadge":"Output truncated","noOutput":"No output","openInWorkspace":"Open in workspace","rawDetails":"Raw details (developer)"},"composerRunStatusSending":"Sending…","composerRunStatusDefault":"Working…","composerRunningTool":"Running {{name}}","composerStageThinking":"Thinking…","composerStageSearching":"Searching…","composerStageReading":"Reading…","composerStageWriting":"Writing…","composerStageExecuting":"Executing…","composerStageAnalyzing":"Analyzing…","attachFile":"Attach file","moreActions":"More actions","fileReference":{"externalBadge":"External","externalDescription":"This file is outside the current workspace, so it cannot be edited in the workspace editor.","offWorkspaceBaseDescription":"This file is outside the current session workspace and cannot be opened in the workspace editor.","browserOffWorkspaceDescription":"This file is outside the current session workspace. Copy the path and open it from your system or desktop app.","locationKind":{"agent-profile":"Agent profile","xopc-skills":"Skills","xopc-config":"App config","xopc-agents":"Agent data","xopc-sessions":"Session data","host":"On this computer"},"openInSettings":"Open in settings","browserExternalDescription":"This file is outside the current workspace. In the browser, copy the path and open it from your system.","missingDescription":"This file is currently unavailable. It may have been moved, deleted, or created in another runtime environment.","invalidDescription":"This file path could not be resolved.","openExternal":"Open","revealInFolder":"Show in folder","copyPath":"Copy path","importToWorkspace":"Import to workspace","importInProgress":"Importing…","importDialogTitle":"Copy this file into the workspace?","importDialogSourceLabel":"Source","importDialogDestinationLabel":"Destination (workspace-relative)","importDialogConfirm":"Import","importDialogCancel":"Cancel","importSuccessToast":"Imported to {{path}}","importErrors":{"IMPORT_NOT_ALLOWED":"This file cannot be imported into the workspace.","SOURCE_NOT_FOUND":"The source file is no longer available.","SOURCE_NOT_FILE":"Only regular files can be imported.","SOURCE_TOO_LARGE":"File exceeds the import size limit.","INVALID_DESTINATION":"Invalid destination path.","DESTINATION_BLOCKED":"The destination path is protected. Try a different name.","DESTINATION_EXISTS":"A file already exists at the destination.","SAME_LOCATION":"Source and destination are the same.","FILE_REF_EXPIRED":"This file reference has expired. Try again.","FILE_REF_FORBIDDEN":"This file reference does not belong to the current session.","OVERWRITE_DISABLED":"Overwrite is disabled by configuration.","IMPORT_FAILED":"Import failed. Please try again.","UNKNOWN":"Import failed."}},"workingDirectory":{"selectWorkingDirectory":"Select working directory","chooseFolder":"Choose folder…","selectPath":"Select folder…","recentDirectories":"Recent directories","noRecent":"No recent folders","notSet":"Default workspace","defaultWorkspace":"Session workspace","copyPath":"Copy path","selectionOnlyAtNewChat":"Workspace can only be chosen before the first message.","lockedTapTitle":"Workspace is locked for this chat","lockedTapBody":"To pick a folder for the agent, open New chat and click this control before you send the first message. You can also set a default workspace under Settings → Agents.","clickToCopyFullPath":"Click to copy full path","tooltipAgentWorkspace":"Agent workspace","tooltipOpenProjectFiles":"Click to open or close project files in the sidebar.","copied":"Copied","openWorkspaceMenu":"Workspace options","folderPickerRequiresDesktop":"Folder selection requires the desktop app (Electron). Open xopc from the desktop app, or configure the path another way.","applyErrorTitle":"Could not set working directory","applyErrorClose":"Close","pathModalTitle":"Working directory","pathModalDescription":"Enter an absolute path on the machine running the gateway (folder for the session workspace).","pathInputPlaceholder":"/absolute/path/to/folder","pathModalConfirm":"Apply","pathModalCancel":"Cancel","pickerHostHint":"Directories on gateway host: {{hostname}}","pickerLoading":"Loading…","pickerUp":"Up","pickerUseThisFolder":"Use this folder","pickerManualPath":"Or type an absolute path","pickerApplyManual":"Apply path","pickerListError":"Could not read this location.","pickerEmptyFolder":"Empty folder","pickerDrives":"Drives"},"maxAttachmentsReached":"Maximum {{max}} files per message. Remove some to add more.","maxAttachmentsTruncated":"{{dropped}} file(s) not added (limit {{max}} per message).","attachmentFileTooLarge":"File \\"{{name}}\\" is too large (max {{maxSize}} per file).","attachmentLoadFailed":"Failed to load attachment: {{name}}","clipboardFileTypeUnsupported":"Clipboard file type not supported for chat attachments","inputPlaceholder":"Ask anything — @ for files, / for skills & commands","currentModel":"Model used for this conversation","modelSearchPlaceholder":"Search by name, provider, or ID…","modelNoMatches":"No models match your search","contextWindowHoverShort":"{{percent}}% context","contextWindowHoverNoLimit":"~{{used}} context","contextWindowAriaSummary":"Context usage about {{used}} of {{limit}} tokens","contextWindowAriaSummaryNoLimit":"Estimated context usage about {{used}} tokens","modelProviderSettingsLink":"Configure providers…","dropFiles":"Drop files here to attach","voiceRecording":"Record voice","voiceRecordingStop":"Stop recording","voiceInput":"Voice input","voiceRecordingStatus":"Recording","voiceInputCancel":"Cancel recording","voiceInputConfirm":"Transcribe to text","voiceTranscribing":"Transcribing…","voiceTranscribeEmpty":"No speech detected.","voiceTranscribeFailed":"Transcription failed. Try again.","voiceSttNotConfigured":"Speech-to-text is not configured. Enable STT under Settings → Voice.","voiceMicDenied":"Microphone access denied or unavailable.","inputPlaceholderSteering":"Follow-up: Enter queues a row; click a row to edit here","inputPlaceholderSteeringEdit":"Editing queued follow-up — Enter saves, Esc discards changes","steeringInterruptSend":"Stop and send now (⌘↵ or Ctrl+↵)","followUpQueueAria":"Follow-up queue (sent after this reply, in order)","followUpQueueHeading":"Follow-ups","followUpQueueClickToEdit":"Edit in composer","followUpQueueAttachmentOnly":"(attachment)","followUpQueueEmptyPreview":"(empty)","followUpQueueDrag":"Drag to reorder","followUpQueueMoveUp":"Move up","followUpQueueMoveDown":"Move down","followUpQueueSteerNow":"Inject as steering (tool boundary)","followUpQueueRemove":"Remove from queue","followUpQueueAttachmentsNote":"Rows with attachments cannot use ✨ steer; they send as full messages in order.","followUpQueueMaxReached":"Follow-up queue is full (max {{max}}). Remove one or wait for the run to finish.","clarifyRegionAria":"Assistant clarification","clarifyResumeHint":"Your answer continues the current assistant turn.","clarifyServerTimeout":"This prompt expires on the server after about {{minutes}} minutes.","clarifyDefaultTimeoutNote":"If it expires before you answer, the assistant may use the suggested default.","clarifySkipNote":"Skip sends an empty reply so the run can continue.","clarifyChoicesGroupAria":"Suggested answers","clarifyCustomLabel":"Or type your own answer","clarifyPlaceholder":"Your answer…","clarifySend":"Send","clarifyUseDefault":"Use default","clarifyDefaultChoice":"Default: {{text}}","clarifySkip":"Skip","clarifyTimeRemaining":"Time left (approx.): {{time}}","browserSetupRequiredTitle":"Browser setup needed","browserSetupRequiredCta":"Configure browser","browserSetupRequiredDetailToggle":"View diagnostic detail","browserSetupRequiredReasons":{"generic":"The configured browser backend isn't ready yet. Finish setup in Settings → Browser to continue.","extension_not_installed":"The xopc browser extension isn't installed yet. Install it from Settings → Browser to enable the agent to drive Chrome.","extension_bridge_offline":"The extension bridge isn't listening. Start it from Settings → Browser, then keep Chrome open.","extension_not_connected":"The bridge is up but Chrome hasn't connected yet. Open Chrome and enable the xopc extension.","local_chromium_missing":"Local Chromium isn't installed. Install it from Settings → Browser (one-click) before using the local backend.","cloakbrowser_not_installed":"CloakBrowser binary isn't downloaded yet. Install it from Settings → Browser.","cdp_unreachable":"The configured CDP endpoint isn't reachable. Verify the URL in Settings → Browser and make sure Chrome is running with --remote-debugging-port.","cloud_api_key_missing":"Cloud browser API key is missing. Add it in Settings → Browser."},"voicePlay":"Play voice","voicePause":"Pause","voiceLoading":"Loading audio…","voiceAriaRegion":"Voice playback","voiceAwaitingMeta":"Measuring clip length","voiceMessage":"Voice","loadOlder":"Loading older messages…","scrollToBottom":"Scroll to bottom","attachmentPreviewClose":"Close","attachmentPreviewDownload":"Download","attachmentPreviewRemove":"Remove","attachmentPreviewLoading":"Loading file…","attachmentPreviewText":"Text","attachmentPreviewPdf":"PDF","attachmentPreviewDocument":"Document","attachmentPreviewPresentation":"Presentation","attachmentPreviewSpreadsheet":"Spreadsheet","attachmentPreviewNoText":"No text content available","attachmentPreviewMissingData":"Missing file data","attachmentPreviewLoadError":"Error loading file","attachmentPreviewMissingAuth":"Missing authentication","attachmentPreviewFailedPdf":"Failed to load PDF","attachmentPreviewFailedDocx":"Failed to load document","attachmentPreviewFailedExcel":"Failed to load spreadsheet","attachmentPreviewPdfRendering":"Rendering PDF…","attachmentPreviewPdfLoadMore":"Scroll to load more pages","attachmentPreviewExcelTruncated":"Preview limited to {rows} rows × {cols} columns. Download the file to see the full sheet.","attachmentPreviewPptxTruncated":"Text preview truncated for performance. Download the file to see the full deck.","attachmentPreviewPptxSlide":"Slide {n}","attachmentPreviewPptxEmptySlide":"(No text on this slide)","attachmentPreviewOpenElsewhereHint":"Download the file to open it in another application on your computer.","attachmentPreviewOpenElsewhereTruncated":"Only part of this file is shown here. Download the full file to open it elsewhere.","attachmentPreviewDownloadFull":"Download file","attachmentPreviewImage":"Preview image","attachmentPreviewFullscreen":"Full screen preview","attachmentPreviewExitFullscreen":"Exit full screen","messageArtifactsHeading":"Message output","stepTimelineThinkingStreaming":"Thinking…","stepTimelineThinkingDone":"Thinking complete","stepTimelineToolSearchRunning":"Searching the web…","stepTimelineToolSearchComplete":"Web search complete","stepTimelineToolSearchError":"Web search failed","stepTimelineToolGenericRunning":"{{name}}…","stepTimelineToolGenericComplete":"{{name}} complete","stepTimelineToolGenericError":"{{name}} failed","searchSourcesHeading":"Search sources · {{count}}","executionDrawerTitle":"Execution","executionDrawerClose":"Close","executionDrawerEmpty":"No steps for this reply yet.","executionProgressDone":"Thinking complete","executionProgressRunning":"Thinking & tools…","executionElapsedTitle":"Elapsed time for this run","messageCopyPlainText":"Copy plain text","messageCopyMarkdown":"Copy Markdown","codeBlockCopy":"Copy","messageCopied":"Copied","userMessageCopy":"Copy message","userMessageRetry":"Retry","userMessageEdit":"Edit in composer","userMessageRetryDisabledHint":"Only your latest message can be retried.","userMessageActionsWait":"Wait until sending or streaming finishes.","userMessageDelete":"Delete this round","userMessageDeleteConfirm":"This will delete both your message and the AI response. Continue?","userMessageDeleteConfirmTitle":"Delete conversation round","userMessageDeleteCancel":"Cancel","userMessageDeleteOk":"Delete","commandPalette":{"noResults":"No matching commands or skills","placeholder":"Search skills and commands…","skillsSection":"Skills","commandsSection":"Commands","agentsSection":"Agents","currentBadge":"current","queueBadge":"queue","queueFullBadge":"queue full","queueFullTooltip":"Follow-up queue is full","showGroupedMore":"Show {{count}} more"},"goal":{"heading":"Standing goal","turns":"{{used}} / {{max}} turns","checklistHeading":"Criteria","checklistProgress":"{{done}} / {{total}} done","checklistEmpty":"Criteria appear after the first reply (or add your own).","addCriterionPlaceholder":"Add a criterion…","addCriterion":"Add","markDone":"Done","markBlocked":"Blocked","removeItem":"Remove","resetChecklist":"Reset criteria","moreActions":"More","moreHint":"Restart turn budget, clear goal, or view judge details","statusActive":"Active","statusPaused":"Paused","statusDone":"Done","agentRunning":"Agent run in progress…","pause":"Pause","resume":"Resume","clear":"Clear goal","restart":"Restart budget","detailsToggle":"Judge details","lastVerdict":"Last verdict","verdictDone":"Done","verdictContinue":"Continue","verdictSkipped":"Skipped","verdictDecompose":"Checklist ready","lastReason":"Reason","loadFailed":"Could not load goal state.","collapseAria":"Collapse goal bar","expandAria":"Expand standing goal","pillTitle":"{{status}} · {{turns}} — click to expand","elapsedLabel":"Run time","runHistory":"Run history","runHistoryEmpty":"No runs recorded yet. Runs appear after each assistant reply while the goal is active.","runHistoryLoading":"Loading…","runHistoryLoadFailed":"Could not load run history.","runHistoryTurns":"{{used}} / {{max}} turns","runHistoryContinue":"Continues","runHistoryStop":"Stops","verdictInactive":"Inactive","missionHeading":"Goal mission","phaseAgentRunning":"Agent running","phasePaused":"Goal paused","phaseDone":"Goal done","phaseJudged":"Judge updated","lastJudgementTitle":"Last judgement","showDetails":"Expand","hideDetails":"Collapse","pausedReason":"Paused reason","judgeModel":"Judge model","parseFailures":"Parse failures","judgeGenerated":"Judge generated","userAdded":"User added","evidenceLabel":"Evidence","pendingGroup":"Pending","completedGroup":"Completed","impossibleGroup":"Impossible","latestRunTitle":"Latest run","nextStepContinue":"Continue","nextStepStop":"Stop"},"atMention":{"noResults":"No matches","placeholder":"Search files…","searchError":"Failed to search workspace","files":"Files","folders":"Folders","recentFiles":"Recent","recentBadge":"Recent","shiftHint":"Shift+Enter or Shift+click: add another @ mention."}}`)},Ee={cron:JSON.parse('{"title":"Scheduled Tasks","subtitle":"Tasks run automatically on schedule and can be triggered manually anytime. Describe what you want to do regularly in any chat to create one quickly.","needToken":"Save a gateway token to manage scheduled tasks.","globals":{"title":"Global settings","hint":"Cron scheduler limits and defaults for all jobs. Restart may be required for some changes.","loading":"Loading…","enabled":"Enable cron scheduler","maxConcurrent":"Max concurrent jobs","timezone":"Default timezone (IANA)","retentionDays":"Run history retention (days)","metrics":"Enable cron metrics","save":"Save","discard":"Discard","saving":"Saving…","saved":"Saved","saveError":"Failed to save cron settings"},"statsRegion":"Overview","tabMyTasks":"My Scheduled Tasks","tabSystemTasks":"System","tabRunHistory":"Run History","systemTasksIntro":"Built-in schedules maintained by the gateway (memory consolidation) and the heartbeat timer. Change behavior in the linked settings pages.","systemHeartbeatTitle":"Gateway heartbeat","systemHeartbeatHint":"Runs on a wall-clock interval inside the gateway process (not a cron row). Uses HEARTBEAT.md when present.","systemHeartbeatSettingsLink":"Heartbeat settings","systemHeartbeatStatus":"Status","systemHeartbeatInterval":"Cadence","systemHeartbeatEvery":"About every {{value}}.","systemDreamingTitle":"Memory consolidation (dreaming)","systemDreamingHint":"Three-phase background jobs that promote short-term signals into long-term memory. Schedules follow agent memory settings.","systemDreamingSettingsLink":"Memory & dreams settings","systemDreamingEmpty":"No dreaming cron jobs are registered (dreaming may be disabled or not reconciled yet).","wakeBanner":"Scheduled tasks only run while this device is awake. When the system or display sleeps, runs may be skipped.","keepAwake":"Keep screen awake","wakeLockUnavailable":"Screen wake lock is not available in this browser or context.","sortCreatedDesc":"Created (newest first)","sortCreatedAsc":"Created (oldest first)","historyRangeDay":"Day","historyRangeWeek":"Week","historyRangeMonth":"Month","filterAllTasks":"All tasks","filterAllStatuses":"All statuses","emptyHistoryTitle":"No execution records","emptyHistoryHint":"Records will appear here once scheduled tasks start running.","jobCardMenuAria":"Task actions","scheduleBadge":{"everyMinute":"Every minute","everyNMinutes":"Every {{n}} minutes","everyNHours":"Every {{n}} hours","hourly":"Hourly","dailyAt":"Daily, {{time}}","weekdaysAt":"Weekdays, {{time}}","weeklyOn":"{{day}}, {{time}}","cronExpr":"{{expr}}"},"jobsHeading":"Scheduled jobs","addJob":"New task","editJob":"Edit task","name":"Name *","namePlaceholder":"My scheduled task","nameRequired":"Name is required","schedule":"Schedule (cron expression) *","message":"Message *","messagePlaceholder":"What should the assistant do?","messageEdit":"Edit","messagePreview":"Preview","messageMarkdownHint":"Supports Markdown (headings, lists, code blocks, links, …).","create":"Create Job","runNow":"Run Now","delete":"Delete","edit":"Edit","enabled":"Enabled","disabled":"Disabled","running":"Running","nextRun":"Next Run","status":"Status","runHistoryTitle":"Run History","runHistoryHint":"Completed runs are stored on disk (state/cron/runs). Use Refresh to update.","detailRunHistory":"Recent runs","colStarted":"Started","colJob":"Job","colDuration":"Duration","colDetail":"Result","colChat":"Chat","openChat":"Open","openChatTitle":"Open this run in chat (isolated agent sessions only)","execStatusRunning":"Running","execStatusSuccess":"Success","execStatusFailed":"Failed","execStatusCancelled":"Skipped","noRunsYet":"No executions in this range.","confirmDelete":"Are you sure you want to delete this cron job?","confirmRun":"Run this cron job now?","scheduleLabel":"Schedule","messageLabel":"Message","totalJobs":"Total jobs","emptyStateCta":"Create your first job","channel":"Channel","channelLocal":"Local (no outbound)","deliveryTargetLocalChannel":"Local channel — transcript or message stays on this machine","recipient":"Recipient *","recipientPlaceholder":"Telegram: numeric id, or pick from recent sessions","refreshList":"Refresh","refreshRecipientHint":"Reload list from recent sessions","selectRecipient":"— Select —","noRecentChatsOption":"No recent sessions","deliveryTarget":"Delivery","scheduleHintPreset":"Select a preset or enter custom cron expression","schedulePicker":{"scheduleTimeLabel":"Scheduled time","modeNoRepeat":"Does not repeat (yearly date)","modeInterval":"Interval","intervalKindMinutes":"Minutes","intervalKindHours":"Hours","modeHourly":"Every hour","modeDaily":"Daily","modeWeekly":"Weekly","modeMonthly":"Monthly","modeCustom":"Custom (cron)","minuteUnit":"min","minuteAtHour":"Minute","intervalMinutes":"Interval in minutes","intervalHours":"Interval in hours","hourUnit":"h","dayOfMonth":"Day of month","customCronHint":"Five-field cron: minute hour day-of-month month day-of-week","weekdays":["Mo","Tu","We","Th","Fr","Sa","Su"]},"mode":"Mode","modeDirect":"Send message directly to the channel without AI processing","modeAgent":"Use AI agent to process the message, then send the response","modeDirectOption":"Direct (send message directly)","modeAgentOption":"AI Agent (process with AI then send)","agentLocalOnly":"Local only (save transcript, no channel send)","agentLocalOnlyHint":"Runs the agent on this machine. The transcript is stored as a cron session under the default or selected agent (the job id is part of the session key); no Telegram or CLI delivery.","deliveryLocalOnly":"Local only — transcript saved as a cron session under that agent","agentProfile":"Agent","agentProfileHint":"Only applies when mode is AI Agent. Leave as default to use the gateway default agent profile.","agentProfileDefault":"Default agent","workingDirectoryLabel":"Workspace","workingDirectoryHint":"Optional. Absolute path on the gateway host; leave unset to use this agent\'s default workspace.","workingDirectoryReset":"Use agent default","model":"Model","save":"Save","failedToLoadJobs":"Failed to load jobs","scheduleRequired":"Schedule and message are required","chatIdRequired":"Chat ID is required","failedToCreateJob":"Failed to create job","failedToUpdateJob":"Failed to save job","failedToToggleJob":"Failed to toggle job","actionFailed":"Action failed","enterManuallyOrSelect":"Enter manually or select from recent chats","noRecentChats":"No recent chats found. Enter chat ID manually (e.g., 123456789 for Telegram)","refresh":"Refresh","close":"Close","cancel":"Cancel","loading":"Loading…","schedulePresets":{"custom":"-- Custom (enter below) --","everyMinute":"Every minute","every5Minutes":"Every 5 minutes (default)","every10Minutes":"Every 10 minutes","every15Minutes":"Every 15 minutes","every30Minutes":"Every 30 minutes","everyHour":"Every hour","every2Hours":"Every 2 hours","every4Hours":"Every 4 hours","every6Hours":"Every 6 hours","every12Hours":"Every 12 hours","everyDayMidnight":"Every day at midnight","everyDay9AM":"Every day at 9:00 AM","everyDay9PM":"Every day at 9:00 PM"},"timeLabels":{"overdue":"Overdue","lessThanMinute":"Less than a minute","minutes":"{{count}} min","hours":"{{count}} hours"},"lastActiveLabels":{"justNow":"just now","minutesAgo":"{{count}}m ago","hoursAgo":"{{count}}h ago","daysAgo":"{{count}}d ago"},"templateFilterAll":"All","fromTemplate":"From template","templatesEmptyHint":"No templates match this filter.","templateCategories":{"daily":"Daily","monitoring":"Monitoring","reports":"Reports","automation":"Automation"},"templates":{"morning_briefing":{"title":"Morning briefing","description":"Weather-style day snapshot, headlines in your topics, and top priorities—edit the topic list in the prompt.","prompt":"Build a **morning briefing** I can read in a few minutes.\\n- **Weather / day shape**: if you cannot access a real forecast API, say so and give **one** practical clothing or commute tip based only on season/region I name below, or skip this bullet.\\n- **Headlines**: topics I care about (edit): **(e.g. local news, macro, tech policy, sports)**—if web search works, 4–6 bullets from the last ~24h with source type; if not, give a **manual check order** instead of inventing stories.\\n- **Top 3 priorities today** from workspace notes/todos if visible; else ask me to paste them once.\\n- **No fake URLs or quotes**."},"standup_prep":{"title":"Standup prep","description":"Draft a standup-style update from recent git activity and notable file changes in the workspace.","prompt":"Prepare a **standup update** for me:\\n- If Git is available: **yesterday / since last standup** themes from `git log` (no wall of SHAs), risky paths if obvious from messages.\\n- If not: give **commands** I should run locally next time.\\n- **Files touched**: infer from workspace if you can (recent edits, open PR-style hints); mark uncertain.\\n- **Blockers**: max 3, honest \\"unknown\\" allowed.\\n- **Today intent**: one sentence.\\n- Keep it speakable aloud in under ~90 seconds."},"end_of_day_wrap_up":{"title":"End-of-day wrap-up","description":"Summarize progress, open items, and tomorrow\'s priorities from workspace context when possible.","prompt":"**End-of-day wrap** (weekday):\\n- **Done**: up to 5 bullets (mark inferred items).\\n- **Open / parked**: up to 4 bullets.\\n- **Tomorrow**: first concrete task after login—single bullet.\\n- Pull from task docs, changelogs, or notes in the workspace when present; otherwise say what is missing.\\n- Neutral tone, no guilt."},"inbox_triage":{"title":"Inbox triage","description":"Surface urgent follow-ups first—uses any mail/export notes in the workspace; no mailbox access implied.","prompt":"Help me **triage inbox-style work** (no live email unless I paste content):\\n- If I have exported snippets, `*.eml`, or notes about mail in the workspace, summarize **urgent follow-ups first** with suggested next action each.\\n- If nothing mail-related exists, output a **5-step triage routine** (folders/labels, oldest-first, VIP senders I list below) and ask me to paste 3 subject lines next run.\\n- **VIP / domains to watch** (edit): **(add yours)**.\\n- Do not claim you read my real inbox."},"competitor_watch":{"title":"Competitor watch","description":"Track competitor news, product updates, and pricing signals you name—web search when available.","prompt":"Competitors or alternatives to watch (edit names/topics): **(list here)**.\\n- If web search works: summarize **news, product/changelog moves, pricing or packaging signals** from roughly the past week; separate **fact** vs **rumor**.\\n- If search is unavailable: give **official domains + what to check** (pricing page, changelog, press) without fabricating updates.\\n- **Never invent press quotes, numbers, or URLs**."},"trending_topics_monitor":{"title":"Trending topics","description":"Track trending discussions and news in industries or communities you list.","prompt":"Industries, communities, or hashtags I track (edit): **(e.g. fintech, indie games, city subreddit, AI tools)**.\\n- If web search works: **5–7** bullets on what is **trending or unusually active** this week; note platform (news, Reddit-style, HN-style) at a high level.\\n- If not: suggest **where to look** and **search phrases**—no made-up threads.\\n- Flag **controversy or misinformation risk** briefly when relevant."},"tech_radar_stack":{"title":"Tech radar","description":"Monitor new releases and security advisories for stacks you name (frameworks, runtimes, cloud).","prompt":"Stacks I use (edit): **(e.g. Node LTS, Postgres, AWS service X, Android SDK)**.\\n- List **notable releases or deprecations** from the past ~14 days using **official blogs, registries, or changelogs** only.\\n- Security: point to **official advisory channels**; **do not invent CVE IDs**.\\n- If the workspace has lockfiles, you may mention ecosystem at a high level; if unsure, say what file you need."},"dependency_check_audit":{"title":"Dependency check","description":"Audit-style nudge for outdated packages and known issues—suggests commands, does not fabricate CVEs.","prompt":"From the repo in the workspace, infer package managers (`package.json`, `go.mod`, `pyproject.toml`, etc.).\\n- Suggest **one concrete audit command** per ecosystem if documented (npm/pnpm audit, pip-audit, etc.).\\n- Summarize **what I should look for** (majors, yanked packages, EOL runtimes) without claiming scan results you did not run.\\n- **Never fabricate CVE numbers** or vulnerable versions."},"weekly_review":{"title":"Weekly review","description":"Summarize the week\'s commits, open items, and next-week priorities.","prompt":"**Weekly review** (assume end of week):\\n- **Shipped themes** from git + workspace notes (or say git unavailable).\\n- **Open items** still worrying (max 6).\\n- **Next week**: 3 headline priorities.\\n- **One thing to stop or delegate** if overload is visible.\\n- Short, executive-summary tone."},"code_quality_report":{"title":"Code quality report","description":"Outline how to run lint/type-check and what to look for in output—does not pretend CI already ran.","prompt":"Inspect the workspace for **lint / typecheck / format** scripts (package.json, Makefile, CI YAML).\\n- Propose **commands** I should run locally and in what order.\\n- Describe **how to skim output**: error categories, flaky tests, type debt hotspots—without inventing numbers.\\n- If no scripts found, suggest a **minimal** starter for the detected language with caveats."},"git_activity_summary":{"title":"Git activity summary","description":"Summarize recent commits, active branches, and hotspot files when git is available.","prompt":"Summarize **recent Git activity** (last ~7 days if possible):\\n- Commit **themes**, **active branches** worth naming, **hotspot files** touched often.\\n- If git is not callable here, output **commands** to reproduce the summary locally.\\n- Avoid dumping hashes; keep it scannable."},"user_feedback_digest":{"title":"User feedback digest","description":"Summarize recurring feedback and pain points from notes, issues exports, or docs you keep in the workspace.","prompt":"I store feedback in (edit paths or patterns): **`feedback/`, issues export, Notion export, etc.`**\\n- From readable workspace text, cluster **recurring themes**, **sentiment (rough)**, and **top pain points** (max 5).\\n- If no material: give a **template** for how I should paste feedback next time.\\n- No PII beyond what is already in files; redact if needed in summary."},"stale_todo_or_issue_sweep":{"title":"Stale todo / issue sweep","description":"Find aging TODOs or issue-like markers in the repo and suggest keep / close / split.","prompt":"Scan the workspace for **TODO/FIXME/HACK** comments or lightweight issue lists in markdown.\\n- List up to **10 stale candidates** (old by file churn or vague wording) with **suggested next action**: close, split, or schedule.\\n- Do not delete anything—recommendations only.\\n- If scan is incomplete, say why."},"release_notes_or_changelog_draft":{"title":"Release notes draft","description":"Draft changelog bullets from recent commits and version files—human must verify before ship.","prompt":"Draft **release notes / changelog** candidate for the **next** version bump:\\n- Read `CHANGELOG`, version in `package.json`/`Cargo.toml`/similar if present.\\n- Summarize **user-visible** changes from recent commits since last tag if inferable; else since last week.\\n- Mark **uncertain** items; I will edit before publishing.\\n- No marketing exaggeration."},"workspace_cleanup_suggestions":{"title":"Workspace cleanup","description":"List large artifacts, caches, or generated files to review before the weekend—never auto-delete.","prompt":"Suggest **workspace cleanup** before the weekend:\\n- Large **build outputs, caches, logs** if discoverable.\\n- Table: path | why it might be safe to trim | risk | suggested action (review only).\\n- **Never delete**; if you cannot see disk usage, say so and give generic patterns."},"smoke_or_ci_health_reminder":{"title":"Smoke / CI health","description":"Remind which smoke tests or CI checks matter this week and how to run them locally.","prompt":"From CI config and package scripts, list **smoke or health checks** worth running this week.\\n- For each: **command**, **expected green signal**, **when to run** (before release, daily, etc.).\\n- If CI files are missing, propose a **minimal** manual smoke path for this repo type.\\n- Do not claim CI passed without evidence."}}}')},De={logs:{title:`Logs`,subtitle:`Runtime diagnostics and history from the gateway.`,needToken:`Save a gateway token to view logs.`,filters:`Filters`,level:`Level`,searchPlaceholder:`Search message or module…`,module:`Module`,allModules:`All modules`,timeRange:`Time range`,from:`From`,to:`To`,clear:`Clear`,refresh:`Refresh`,autoRefresh:`Auto refresh`,pause:`Pause`,liveHint:`Refreshing every 5s`,logFiles:`Log files`,filesEmpty:`No log files on disk`,loadMore:`Load more`,showingCount:`{{count}} entries loaded`,moreAvailable:`Earlier entries may be available`,noLogs:`No matching entries`,noLogsDescription:`Adjust filters or search, or try again later.`,loading:`Loading…`,loadError:`Failed to load logs`,details:`Log details`,close:`Close`,time:`Time`,message:`Message`,metadata:`Metadata`,statsRegion:`Sample (recent files)`,statsHint:`Counts are sampled from recent log files, not totals.`,statsDetailTitle:`Level breakdown`,logDir:`Directory`,requestId:`Request ID`,sessionId:`Session ID`,presetAll:`All`,presetErrors:`Errors`,presetWarnPlus:`Warn+`,presetInfoPlus:`Info+`,presetVerbose:`Debug`,presetOther:`More`,levelPresetAria:`Filter by log level`,refreshModeAria:`Log refresh mode`,refreshManual:`Manual`,refreshLive:`Live`,filtersMore:`More filters`,filtersDialogTitle:`More filters`,filtersDialogDesc:`Time range and custom log levels.`,filtersDone:`Done`,levelCustom:`Custom levels`,levelCustomHint:`Toggle to include or exclude. No selection means all levels.`,copyMessage:`Copy message`,copyJson:`Copy JSON`,copied:`Copied`,levelNames:{trace:`trace`,debug:`debug`,info:`info`,warn:`warn`,error:`error`,fatal:`fatal`}}},Oe={onboarding:{title:`Welcome to xopc`,subtitle:`Let's get your AI assistant set up in 3 quick steps.`,step1Title:`Choose an AI Provider`,step1Subtitle:`Select the AI service you'd like to use.`,step2Title:`Enter your API key`,step2Subtitle:`Your key is stored locally in your xopc config file.`,step2Placeholder:`Paste your API key here`,step2SecurityNote:`🔒 Keys never leave your machine.`,step3Title:`Choose a default model`,step3Subtitle:`You can change this anytime in settings.`,back:`Back`,continue:`Continue`,startChatting:`Start chatting`,skipSetup:`Skip — I'll set this up later`,setupComplete:`You're all set! Start chatting below.`,stepOf:`Step {{current}} of {{total}}`,providerRecommended:`Recommended`}},ke={providersSettings:{subtitle:`Provider API keys and OAuth. Keys you save here go to the gateway credential store.`,intro:`Search or open a group, expand a provider, paste a new key, then Save. OAuth opens in your browser when you choose it.`,quickStartIntro:`Pick a provider to get started — paste your API key in the row that opens.`,docsLink:`Model & provider docs`,modelsLink:`Custom providers (models.json)`,rotateHint:`Rotating a key: expand the provider, paste the new secret, Save — no restart needed.`,needToken:`Save a gateway token to manage provider credentials.`,loadError:`Failed to load providers`,save:`Save`,saving:`Saving…`,saved:`Saved`,noChangesSaved:`No new keys to save.`,saveError:`Failed to save`,empty:`No providers available.`,searchPlaceholder:`Search OpenAI, Claude, Gemini…`,getApiKey:`Get API Key`,getApiKeyIntl:`Get API Key (International)`,getApiKeyCn:`Get API Key (China)`,savedModelsAvailable:`models available`,savedNoModels:`Configured — no models listed yet`,envVarAlt:`Or set via environment variable`,moreOptions:`More options`,unconfiguredOnly:`Unconfigured only`,noMatches:`No providers match your filters.`,clearFilters:`Clear filters`,discard:`Discard`,unsavedHint:`You have unsaved changes.`,runtimeLabelPrefix:`Runtime credential:`,sourceAgent:`agent private profile`,sourceGateway:`saved in gateway (this console)`,sourceOauth:`OAuth token`,sourceEnv:`environment variable`,sourceModelsJson:`models.json`,sourceExtension:`extension provider`,sourceNone:`none`,testKey:`Test value`,testingKey:`Testing…`,testOkLiteral:`Value accepted (direct key or text).`,testOkEnv:`Environment variable resolves.`,testOkCommand:`Command resolved successfully.`,testFailed:`Check failed.`,revokeFailed:`Revoke failed.`,expandRowDetails:`Show credential fields`,categories:{common:`Common providers`,specialty:`Specialty providers`,enterprise:`Enterprise / cloud`,oauth:`OAuth only`,extension:`Extensions`},configuredCount:`{{count}} configured`,metaMasked:`Credential on file — enter a new key to replace.`,metaWillSave:`API key will be saved when you click Save.`,metaNotConfigured:`Not configured.`,placeholderKey:`API key`,placeholderKeep:`Leave empty to keep current`,placeholderOverride:`Enter new key to override`,show:`Show`,hide:`Hide`,copy:`Copy`,copied:`Copied`,oauth:`OAuth`,revoke:`Revoke`,revokeConfirm:`Revoke OAuth credentials for "{{name}}"?`,oauthStarting:`Starting OAuth…`,oauthProcessingCode:`Processing authorization…`,openAuthPage:`Open auth page`,cancelOAuth:`Cancel`,pasteRedirectUrl:`Paste full redirect URL (e.g. http://127.0.0.1:…/oauth-callback?code=…&state=…)`,submitCode:`Submit`,envHint:`API key is set via environment variable. Enter a new key above to override.`,maskedStoredHint:`Stored credential is not shown. Enter a new key above to replace it.`,oauthHint:`Use OAuth for secure authentication, or enter an API key manually.`,removeKey:`Remove key`,removeKeyConfirm:`Remove the stored API key for "{{name}}"? This cannot be undone.`,removeKeySuccess:`API key removed.`,removeKeyFailed:`Failed to remove key.`},modelsSettings:{needToken:`Save a gateway token to edit models.json.`,subtitle:`Custom providers and models (models.json). Changes apply after save; reload picks up disk edits.`,docsLink:`Model & provider docs`,loadError:`Failed to load models.json`,loadFileWarning:`File warning`,filePath:`Path`,addProvider:`Add provider`,validate:`Validate`,validating:`Validating…`,validateError:`Validation request failed`,save:`Save`,discard:`Discard`,saving:`Saving…`,saved:`Saved`,saveError:`Failed to save`,reload:`Reload`,reloading:`Reloading…`,reloadError:`Reload failed`,showJson:`Show JSON`,hideJson:`Hide JSON`,modeGuided:`Guided`,modeExpert:`Expert`,modeGuidedHint:`Add providers and models with forms. Recommended for most users.`,modeExpertHint:`Edit models.json directly. For custom providers and power users.`,statsProviders:`{{count}} providers`,statsModels:`{{count}} models`,unsavedHint:`You have unsaved changes.`,loading:`Loading…`,jsonParseError:`Invalid JSON`,jsonReset:`Reset from editor`,jsonApply:`Apply JSON`,emptyTitle:`No custom providers`,emptyDesc:`Add OpenAI-compatible endpoints (Ollama, LM Studio, OpenRouter, vLLM, etc.) and optional per-model overrides.`,emptyCta:`Add your first provider`,presetOllama:`Ollama`,presetLmStudio:`LM Studio`,presetOpenRouter:`OpenRouter`,presetZhipuCn:`Zhipu GLM (China · Coding API)`,presetZaiGeneral:`Zhipu GLM (International · general API)`,presetLabel:`Preset`,presetCustom:`Custom`,addProviderTitle:`Add provider`,addProviderSubtitle:`Provider id must be unique (e.g. ollama, my-openai).`,providerIdLabel:`Provider ID`,providerIdPlaceholder:`e.g. ollama`,providerIdRequired:`Provider ID is required`,addProviderConfirm:`Add provider`,cancel:`Cancel`,close:`Close`,baseUrl:`Base URL`,apiType:`API type`,apiKey:`API key`,apiKeyPlaceholder:`sk-…, ENV_VAR, or !command`,apiKeyHint:`Literal key, ENV name (uppercase), or shell command prefixed with !`,authHeader:`Send Authorization header automatically`,testKey:`Test`,show:`Show`,hide:`Hide`,badgeShell:`shell`,badgeEnv:`env`,badgeLiteral:`literal`,removeProvider:`Remove provider`,removeProviderConfirm:`Remove provider "{{id}}" and its models?`,modelsSection:`Models`,modelsEmpty:`No custom models; built-in defaults apply where available.`,addModel:`Add model`,editModel:`Edit model`,removeModel:`Remove model`,removeModelConfirm:`Remove model "{{id}}"?`,addModelTitle:`Add model`,editModelTitle:`Edit model`,modelProviderLabel:`Provider`,modelId:`Model ID`,displayName:`Display name`,inputTypes:`Input types`,inputTextOnly:`Text only`,inputTextVision:`Text + vision`,reasoning:`Supports reasoning`,contextWindow:`Context window`,maxOutputTokens:`Max output tokens`,costSection:`Cost (per 1M tokens)`,costInput:`Input`,costOutput:`Output`,modelIdRequired:`Model ID is required`,mustBePositive:`Must be greater than 0`,addModelConfirm:`Add model`,saveModelConfirm:`Save`,validationErrors:`Validation issues`,validationWarnings:`Warnings`,testError:`Error`,testOk:`Resolved`}},Ae={remoteAccess:{pageTitle:`Remote access`,pageSubtitle:`Connect to this gateway from other devices. Pick one method — only one exposure mode should be active at a time.`,docsLink:`Read the remote access guide`,tabsAria:`Remote access methods`,tabs:{guide:`Overview`,tailscale:`Tailscale`,public:`Public internet`,"reverse-proxy":`Reverse proxy`,ssh:`SSH tunnel`,lan:`Local network`},tabIntro:{guide:`Compare options and see what's active on this gateway.`,tailscale:`Best for personal devices on your tailnet. Gateway stays on loopback; Tailscale Serve publishes HTTPS.`,public:`Create a Tunnel Registration Key in the Console and save it here, then start the tunnel for a public URL and pair your mobile app.`,"reverse-proxy":`Front the gateway with your own HTTPS reverse proxy (Caddy / nginx / Cloudflare Tunnel) at a custom domain, then scan to pair your mobile app.`,ssh:`CLI SSH port forwarding when VPN or a public tunnel are unavailable.`,lan:`Reach the gateway on the same Wi‑Fi or LAN via its bind address, then scan to pair your mobile app.`},guide:{pickMethod:`Choose a connection method`,recommended:`Recommended`,configure:`Configure`,statusActive:`Active`,statusOff:`Off`,statusConnecting:`Connecting`,tailscaleCardTitle:`Tailscale Serve`,tailscaleCardDesc:`HTTPS on your tailnet only. No public internet exposure.`,publicCardTitle:`Public tunnel`,publicCardDesc:`Share a public URL for mobile pairing and remote clients.`,reverseProxyCardTitle:`Reverse proxy`,reverseProxyCardDesc:`Use your own HTTPS reverse proxy at a custom domain.`,sshCardTitle:`SSH tunnel`,sshCardDesc:`CLI forwarding when VPN or public tunnel are unavailable.`,sshCardStatus:`CLI`,lanCardTitle:`Same Wi‑Fi / LAN`,lanCardDesc:`Use the gateway bind address on your local network.`,lanCardStatus:`Local`,conflictsTitle:`Configuration conflict`,conflictsHint:`Only one exposure method should be active. Disable the other before switching.`,oneAtATimeHint:`Tailscale Serve and the public tunnel cannot run together. Use Overview to check status before switching.`,needToken:`Sign in to the gateway (valid token) to manage remote access.`,docsLink:`Full guide in the docs`},advanced:{proxyTitle:`Reverse proxy & remote URL`,proxyBody:`When the gateway sits behind nginx, Caddy, or another proxy, configure trusted headers and optional gateway.remote for CLI clients.`,proxyDocs:`Read remote access docs`},lan:{title:`Same network (LAN)`,subtitle:`Reach the gateway from phones or laptops on the same Wi‑Fi without exposing it to the internet.`,body:`Set the gateway bind address to your LAN IP (or 0.0.0.0) and connect using http://<host>:<port>. Keep firewall rules in mind.`,link:`Open Gateway settings`,pairTitle:`Mobile app pairing`,pairSubtitle:`On the same Wi‑Fi, scan to connect your phone. The app exchanges a one-time pairing key for your gateway token.`,pairBlockedNextSteps:`Or use the Public internet tab to pair through a tunnel.`,pairPublicTabLink:`Open Public internet tab`},tailscale:{title:`Tailscale Serve (recommended)`,subtitle:`Expose the gateway on your tailnet over HTTPS while keeping the process bound to loopback.`,statusLabel:`Serve status`,stepInstallBefore:`Install `,stepInstallLink:`Tailscale`,stepInstallAfter:` on this machine and sign in to your tailnet.`,stepEnable:`Enable Serve below to publish HTTPS on your tailnet hostname.`,stepCopy:`Open or copy the HTTPS URL on any device on the same tailnet.`,loading:`Loading Tailscale status…`,statusActive:`Tailscale Serve is active.`,statusOff:`Tailscale Serve is off.`,enableServe:`Enable Serve`,disableServe:`Disable Serve`,copyUrl:`Copy HTTPS URL`,copied:`Copied`,hint:`Requires Tailscale installed and logged in on this machine. API routes still require your gateway token.`,docsLink:`Tailscale Serve docs`,cliMissingIntro:`Tailscale CLI not found on this machine.`,cliMissingDownloadLink:`Download from tailscale.com/download`,cliMissingSuffix:` — install, sign in, then retry.`},ssh:{title:`SSH tunnel (CLI)`,subtitle:`Forward the remote gateway loopback port to your laptop when Tailscale is unavailable.`,hint:`Replace user@your-host with your SSH login. Run on the machine where you want to use the gateway console.`,copy:`Copy command`,copied:`Copied`},reverseProxy:{title:`Reverse proxy (self-hosted HTTPS)`,subtitle:`Front the gateway with your own Caddy / nginx / Cloudflare Tunnel at a custom domain.`,urlLabel:`Public URL`,urlPlaceholder:`https://gateway.example.com`,urlHint:`No trailing path. https required for public hostnames; http is only allowed for RFC1918 / .local.`,probeButton:`Test`,probing:`Testing…`,autoDetectedTitle:`Detected from your current browser address`,autoDetectedHint:`The QR below already uses this URL. Click "Save as default" to persist it so other machines see the same URL.`,saveAsDefault:`Save as default`,saving:`Saving…`,clear:`Clear configured URL`,certWarning:`Mobile clients require a certificate trusted by the system root store (Let's Encrypt / Cloudflare / commercial CA). Self-signed certificates are not supported in v1.`,qrTitle:`Mobile pairing QR`,qrSubtitle:`Scan from the xopc mobile app to pair through your reverse proxy.`,noUrlYet:`Enter your reverse-proxy public URL above to generate the pairing QR.`,mintingSecret:`Minting pairing secret…`,encoding:`Encoding QR…`,refreshQr:`Refresh QR`,copyLink:`Copy deeplink`,copied:`Copied`,probeStatus:{ok:`Reachable`,mobileReady:`mobile pairing ready`,codeUnknown:`Probe failed`,code_TIMEOUT:`Timed out reaching the URL`,code_TLS_INVALID:`TLS / certificate error`,code_DNS_OR_CONN_REFUSED:`DNS or connection refused`,code_NETWORK_ERROR:`Network error`,code_AUTH_BLOCKED:`Reverse proxy returned 401/403 — remove auth in front of /api/tunnel/pair/ping`,code_HTTP_ERROR:`HTTP error from the URL`,code_NOT_XOPC_GATEWAY:`URL did not identify as an xopc gateway`,code_invalid_url:`Invalid URL`,code_invalid_scheme:`Scheme must be http(s)`,code_has_userinfo:`URL must not contain userinfo`,code_has_path:`URL must not contain a path`,code_has_query_or_fragment:`URL must not contain query or fragment`,code_requires_https:`Public hostnames require https`,code_INVALID_JSON:`Invalid JSON body`}}}},je={sessions:{title:`Sessions`,needToken:`Save a gateway token to manage sessions.`,searchPlaceholder:`Search sessions…`,filterAll:`All`,filterActive:`Active`,filterPinned:`Pinned`,filterArchived:`Archived`,filterChannelAll:`All channels`,filterChannelLabel:`Channel`,totalSessions:`Total`,activeSessions:`Active`,pinnedSessions:`Pinned`,archivedSessions:`Archived`,sessionCount:`{{count}} shown`,loadMore:`Load more`,noSessions:`No sessions yet`,noSessionsDescription:`Start a conversation in Chat; sessions will appear here.`,startNewChat:`Start New Chat`,continueChat:`Continue in chat`,archive:`Archive`,unarchive:`Unarchive`,pin:`Pin`,unpin:`Unpin`,export:`Export JSON`,delete:`Delete`,deleteSessionTitle:`Delete session?`,deleteSessionMessage:`Delete “{{name}}”? This cannot be undone.`,cancel:`Cancel`,loading:`Loading…`,loadError:`Failed to load sessions`,gridView:`Grid`,listView:`List`,layoutToggleGroup:`Session layout`,detailLoading:`Loading session…`,detailMessages:`Messages`,detailExport:`Export`,close:`Close`,config:{title:`Session storage`,hint:`How direct-message sessions are keyed and when old session metadata is pruned.`,save:`Save`,discard:`Discard`,saving:`Saving…`,saveError:`Failed to save session settings`,dmScope:`DM session scope`,dmScopeHint:`Controls how session keys are derived for direct messages across channels and accounts.`,dmScopeMain:`Main (single DM session)`,dmScopePerPeer:`Per peer`,dmScopePerChannelPeer:`Per channel + peer`,dmScopePerAccountChannelPeer:`Per account + channel + peer`,pruneAfterDays:`Prune after (days)`,maxEntries:`Max session entries`,unsetPlaceholder:`Leave empty for default`}}},Me={settingsSections:{overview:`System status`,appearance:`Preferences`,agent:`Agent`,"agent-defaults":`Agent settings`,"agent-chat":`Default configuration`,"agent-workspace":`Workspace`,"agent-browser":`Browser`,"agent-runtime":`Turn limits`,"agent-context":`Context`,"agent-memory":`Memory`,"agent-tools":`Tools`,"agent-skills":`Default skill allowlist`,"agent-mcp":`External tools (MCP)`,"agent-system-prompt":`System prompt`,providers:`LLM providers`,credentials:`Models & credentials`,models:`Models`,"image-models":`Images`,channels:`Channels`,voice:`Voice`,gateway:`Gateway`,heartbeat:`Heartbeat`,tunnel:`Remote access`,"remote-access":`Remote access`,shares:`File sharing`,search:`Web search`,dreams:`Background reflection`,goals:`Goal mode`,agents:`Agents`,system:`System permissions`,"app-management":`App management`,cron:`Scheduled tasks`,skills:`Skills`},settingsPage:{comingSoon:`Settings · {{title}} (coming soon).`},modelsHub:{subtitle:`Provider keys, models, image generation, voice, and web search.`,docsLink:`Read the docs`,tabsAria:`Models & credentials sections`,saveBar:{title:`Unsaved changes summary`,cleanSummary:`All sections saved.`,dirtySummary:`{{count}} section(s) have unsaved changes.`,savedSummary:`All changes saved.`,failuresSummary:`{{count}} section(s) failed to save.`,saveAll:`Save all`,discardAll:`Discard all`},providersHint:`Set or rotate API keys (and OAuth) for every LLM provider xopc knows about.`,modelsHint:`Configured models registry — defaults, fallbacks, and manual additions.`,imageHint:`Image understanding (vision) and image generation defaults plus per-provider credentials.`,voiceHint:`Text-to-speech and speech-to-text providers, triggers, and refine settings.`,searchHint:"Web-search providers used by the `web_search` tool. Region and domain blocklist live here too."},setupStatus:{title:`System status`,subtitle:`See what's configured and finish setup to start chatting.`,refresh:`Refresh`,loading:`Loading status…`,loadError:`Could not load system status. Check your gateway connection and try again.`,summaryTitle:`At a glance`,summarySubtitle:`Core services needed for chat.`,summaryGateway:`Gateway`,summaryProviders:`Providers`,summaryModel:`Default model`,statusOnline:`Online`,statusOffline:`Offline`,requiredCompleteMessage:`Required setup is complete — you're ready to chat.`,requiredIncompleteMessage:`Complete the required steps below to start chatting.`,checklistTitle:`Setup checklist`,checklistSubtitle:`Tap a step to open its settings. Optional steps enhance channels and skills.`,optionalBadge:`Optional`,labels:{gatewayOnline:`Connected to gateway`,gatewayOffline:`Not connected — check token and gateway`,providersConfigured:`{{count}} provider(s) configured`,providersMetaReady:`{{configured}} / {{total}} providers ready`,providersMissing:`No provider configured`,modelConfigured:`{{model}}`,modelMissing:`No default model selected`,channelConfigured:`At least one channel connected`,channelMissing:`No channel configured yet`,skillsConfigured:`{{count}} skill(s) available`,skillsMissing:`No skills installed yet`,presetsConfigured:`{{count}} agent(s) configured`,presetsMissing:`Only the default agent — add preset personas`},items:{gateway:{title:`Connect gateway`,description:`Verify the Web console can reach your xopc gateway.`},provider:{title:`Configure LLM provider`,description:`Add at least one AI provider API key or OAuth token.`},defaultModel:{title:`Choose default model`,description:`Set the model used for new conversations.`},channel:{title:`Connect a channel`,description:`Link Telegram, Weixin, or Feishu to chat from messaging apps.`},skill:{title:`Install a skill`,description:`Browse the marketplace or catalog to extend agent capabilities.`},presets:{title:`Add preset agents`,description:`Create specialized agents (Coder, Writer, etc.) for different tasks.`}},scenarios:{title:`Quick setup scenarios`,subtitle:`Pick a path that matches how you plan to use xopc — each step opens the right settings.`,dismiss:`Hide`,steps:{stepProviders:`Configure LLM provider keys`,stepDefaultModel:`Choose default chat model`,stepChannel:`Connect a messaging channel`,stepPresets:`Add specialized agents`,stepCron:`Set up scheduled tasks`,stepSkills:`Install skills from the catalog`},presets:{lightChat:{title:`Light chat`,description:`Talk to your assistant in the web console with one provider and a default model.`},multiChannel:{title:`Multi-channel assistant`,description:`Reply from Telegram or other channels with dedicated agents for different contexts.`},automation:{title:`Automation workflow`,description:`Combine skills and cron jobs for recurring background work.`}}}},credentialsHub:{title:`Credentials hub`,subtitle:`One place to see API keys and OAuth status across chat, search, images, and voice.`,refresh:`Refresh`,loading:`Loading credentials…`,loadError:`Could not load credential status. Check your gateway connection and try again.`,domainsTitle:`Credential domains`,domainsSubtitle:`Manage keys on each detail page — values stay in your gateway config.`,footerHint:`LLM keys live under Providers. Image, voice, and web-search keys may also appear in environment variables — the gateway shows only what is stored in config.`,status:{ready:`Ready`,partial:`Partial`,missing:`Missing`,notNeeded:`Optional`},labels:{llmMetaReady:`{{configured}} / {{total}} LLM providers ready`,llmConfigured:`{{count}} LLM provider(s) configured`,llmMissing:`No LLM provider configured`,webSearchDisabled:`Web search disabled`,webSearchReady:`{{configured}} / {{total}} search provider keys set`,webSearchNoProviders:`No search providers configured`,imageReady:`{{configured}} / {{total}} image providers configured`,imageNoProviders:`No image providers registered`,voiceDisabled:`Speech input/output disabled`,voiceReadyNoKeys:`Speech enabled — no API keys required`,voiceKeysReady:`{{configured}} / {{total}} speech API keys set`,voiceMissing:`Speech not configured`},domains:{llm:{title:`LLM providers`,description:`API keys and OAuth for chat models.`},webSearch:{title:`Web search`,description:`Brave, Tavily, and other search API keys.`},image:{title:`Image generation`,description:`Keys for vision and image-generation providers.`},voice:{title:`Voice (STT / TTS)`,description:`Speech recognition and text-to-speech credentials.`}}},dreamingSettings:{title:`Dreams`,subtitle:`Inspect and maintain the background memory promotion sweep.`,tabsAriaLabel:`Dreams settings categories`,tabConfig:`Configuration`,tabRuntime:`Runtime`,tabInsights:`Preview & logs`,tabMaintenance:`Maintenance`,configTabHint:`Tune the dreaming switch, global schedule, and Light / Deep / REM phase parameters.`,runtimeTabHint:`Review effective schedules, promotion lock, short-term recall store, and latest run output.`,insightsTabHint:`Preview promotion candidates and inspect phase audit logs.`,maintenanceTabHint:`Reset the short-term store or clear a stuck promotion lock; MEMORY.md is not edited.`,refresh:`Refresh`,runNow:`Run now`,runPhaseLabel:`Phase`,runNowHint:`Trigger the managed cron job immediately.`,runQueued:`Run queued.`,actionOk:`Done.`,configSaved:`Configuration saved.`,configTitle:`Configuration`,configHint:`Edits agents.defaults.memory.dreaming and writes back to the gateway config file.`,configLoading:`Loading configuration…`,saveConfig:`Save`,resetConfig:`Reset`,configEnabled:`Enable dreaming`,configFrequency:`Global fallback schedule`,configTimezone:`Timezone (IANA)`,configPhaseLight:`Light Sleep`,configPhaseLightHint:`Lightweight deduplication sweep (every 6h by default).`,configPhaseDeep:`Deep Sleep`,configPhaseDeepHint:`Full promotion sweep with scoring and time decay (daily at 3 AM).`,configPhaseRem:`REM Sleep`,configPhaseRemHint:`Cross-entry pattern clustering and dream diary (weekly on Sunday 5 AM).`,configPhaseEnabled:`Enabled`,configPhaseCron:`Cron schedule`,configLightLookbackDays:`Lookback (days)`,configLightLimit:`Limit`,configLightDedupe:`Dedupe similarity`,configDeepMinScore:`Min score`,configDeepMinRecallCount:`Min recall count`,configDeepLimit:`Limit`,configDeepHalfLife:`Recency half-life (days)`,configDeepMaxAge:`Max age (days)`,configRemLookbackDays:`Lookback (days)`,configRemLimit:`Limit`,configRemMinStrength:`Min pattern strength`,previewTitle:`Preview (dry-run)`,previewHint:`Shows the top candidates after rehydration, contamination filtering, and marker/hash dedupe checks. No files are written.`,previewLoad:`Load preview`,previewNotLoaded:`Preview not loaded yet.`,previewEmpty:`No eligible candidates found.`,previewEligible:`eligible`,runtimeTitle:`Runtime`,runtimeHint:`Read-only: effective settings from the gateway, the recall store, and the latest sweep output.`,subsectionSchedule:`Schedule & lock`,subsectionStore:`Short-term store`,subsectionPhases:`Phases (live)`,subsectionDeep:`Deep gate (live)`,subsectionLastRun:`Last sweep (deep)`,subsectionLightLastRun:`Last sweep (light)`,subsectionRemLastRun:`Last sweep (REM)`,lastRunBlockHint:`Data file: memory/.dreams/last-run.json`,phaseLastRunEmpty:`No runs recorded yet.`,phaseLastRunOk:`OK`,phaseLastRunFailed:`Failed`,lockValueLocked:`Locked`,lockValueUnlocked:`Unlocked`,statusTitle:`Status`,statusHint:`This reads the store under your configured workspace (memory/.dreams).`,enabled:`Enabled`,on:`On`,off:`Off`,schedule:`Schedule`,timezone:`Timezone`,lock:`Promotion lock`,storeEntries:`Store entries`,storePromoted:`Promoted entries`,storeUpdatedAt:`Store updated`,storeLastPromotedAt:`Last promoted`,deepGate:`Deep gate:`,deepGateValue:`minScore={{minScore}}, minRecallCount={{minRecallCount}}, limit={{limit}}`,lastRunTitle:`Last run`,lastRunHint:`memory/.dreams/last-run.json: timing, deep gate config snapshot, ranked/applied counts, and skip reasons. Raw JSON is below for debugging.`,lastRunEmpty:`No runs recorded yet.`,lastRunDuration:`Duration`,lastRunStatus:`Result`,lastRunSuccess:`OK`,lastRunFailure:`Failed`,lastRunReason:`Reason`,lastRunError:`Error`,lastRunRanked:`Ranked candidates`,lastRunApplied:`Applied to MEMORY.md`,lastRunSkipped:`Skipped (counts)`,lastRunSkipKey:`Key already in MEMORY`,lastRunSkipRehydrate:`Rehydrate failed`,lastRunSkipContaminated:`Contaminated`,lastRunSkipHash:`Hash duplicate`,lastRunParseError:`Could not parse last-run file`,lastRunRaw:`Raw JSON`,eventsTitle:`Event log`,eventsHint:`Audit trail of dreaming phase runs (memory/.dreams/events.jsonl).`,eventsLoad:`Load events`,eventsNotLoaded:`Event log not loaded yet.`,eventsEmpty:`No events recorded yet.`,maintenanceTitle:`Maintenance`,maintenanceHint:`These actions only affect the store/lock files. They do not edit MEMORY.md.`,resetStore:`Reset store`,clearLock:`Clear lock`,confirmResetStore:`Reset the dreaming store? This clears short-term recall signals.`,confirmClearLock:`Clear the promotion lock file? Only do this if a sweep got stuck.`},systemSettings:{title:`System permissions`,behaviorGroup:`App behavior`,desktopOnlyTitle:`Desktop app only`,desktopOnlyBody:`System integration is available in the xopc Electron app. In the browser, use your OS settings instead.`,toggles:{openAtLogin:`Open at login`,openAtLoginDesc:`Start xopc when you sign in to this user account.`,keepAwake:`Keep system awake`,keepAwakeDesc:`While enabled, the app requests that the system stay awake (agent work may not be interrupted by idle sleep).`,notifyDesktop:`Desktop notifications`,notifyDesktopDesc:`Show native notifications when the app is in the background (updates, toasts, and agent errors).`,notifySound:`Sound notifications`,notifySoundDesc:`Play a short sound with each desktop notification.`},permissionsTitle:`System permissions`,permissionsHint:`Status is best-effort. After changing system settings, refresh or revisit this page.`,permissionsHintDarwin:`macOS privacy (TCC) and media status are best-effort. Use Refresh after you change System Settings.`,permissionsHintDevDarwin:`Development builds (electron:dev) appear as Electron in System Settings, not xopc. Test permissions with a packaged .app for accurate naming.`,permissionsHintWin:`On Windows, microphone and (where reported) screen access follow system-wide toggles. Each link opens a relevant page in the Settings app.`,permissionsHintLinux:`Linux does not report these states here. We try to open your desktop’s Settings; otherwise a documentation page opens. Grant access in your distro, Flatpak, or portal as needed.`,status:{granted:`Allowed`,denied:`Not allowed`,unknown:`Unknown`},openSettings:`Open settings`,refresh:`Refresh status`,refreshing:`Refreshing…`,refreshDone:`Permission status updated.`,openSettingsDone:`Opened system settings.`,openSettingsFailed:`Could not open system settings. Find the matching page manually.`,requestAccess:`Request access`,permFeedback:{granted:`Microphone access is granted.`,alreadyGranted:`Microphone was already granted.`,openedSettings:`Opened Microphone in System Settings — enable xopc, then tap Refresh status.`,denied:`Microphone access is denied. Enable xopc in System Settings.`,rendererDenied:`The app could not access the microphone. Check OS privacy settings.`,prompted:`If a system prompt appears, allow microphone access.`},screenFeedback:{granted:`Screen recording access is granted.`,alreadyGranted:`Screen recording was already granted.`,openedSettings:`Opened Screen Recording in System Settings — enable xopc, then tap Refresh status.`,denied:`Screen recording is denied. Enable xopc in System Settings.`,prompted:`If a system prompt appears, allow screen recording for xopc.`},accessibilityFeedback:{granted:`Accessibility access is granted.`,alreadyGranted:`Accessibility was already granted.`,openedSettings:`Opened Accessibility in System Settings — enable xopc, then tap Refresh status.`,denied:`Accessibility is not granted. Enable xopc in System Settings.`},notificationsFeedback:{granted:`Notification permission is granted.`,alreadyGranted:`Notifications were already allowed.`,openedSettings:`Opened Notifications in System Settings — enable xopc, then tap Refresh status.`,denied:`Notification permission was denied. Enable xopc in System Settings.`,prompted:`If a system prompt appears, allow notifications for xopc.`,default:`Notification permission was not granted. Try again or enable it in System Settings.`,unsupported:`System notifications are not supported in this environment.`},desktopNotify:{testTitle:`Desktop notifications enabled`,testBody:`You will see alerts here when xopc is in the background.`,testShown:`Test notification sent. Allow notifications in System Settings if you did not see it.`,denied:`Notification permission was denied. Enable notifications for xopc, then try again.`,agentErrorTitle:`Agent run failed`,agentErrorBody:`Open xopc to see details.`},perm:{fullDisk:{title:`Files & storage`,desc:`Read and write workspace and user data when the OS or sandbox allows (wording and paths vary by system).`},screen:{title:`Screen Recording`,desc:`Capture the screen for vision features outside the in-app browser.`},microphone:{title:`Microphone`,desc:`Record voice in chat and voice features.`},accessibility:{title:`Accessibility`,desc:`Use global shortcuts and accessibility-related integrations.`},automation:{title:`Automation & app integration`,desc:`Control or integrate with other apps and services (e.g. Apple Events on macOS, default apps on Windows, or desktop portals on Linux).`},notifications:{title:`Notifications`,desc:`Allow the app in your OS notification settings so alerts can appear.`},location:{title:`Location`,desc:`Location-based tasks when the product uses location.`}},permUnknown:{fullDisk:{darwin:`macOS does not report this until access is attempted. Grant Full Disk Access if workspace reads fail.`,win32:`Windows does not report this here. Open Storage settings if file access fails.`,linux:`Grant file access in your distro, Flatpak, or desktop portal if reads fail.`},screen:{darwin:`Grant Screen Recording for xopc if screen capture tools fail.`,win32:`Enable screen capture for desktop apps in Settings if capture fails.`,linux:`Use your desktop portal or compositor settings if screen capture fails.`},microphone:{darwin:`Use Request access or open Microphone settings if voice input fails.`,win32:`Use Request access or open Microphone privacy settings if voice input fails.`,linux:`Grant microphone access in your desktop or Flatpak settings if voice input fails.`},accessibility:{darwin:`Required for global shortcuts. Use Request access, then enable xopc under Accessibility.`,win32:`Open Accessibility settings if global shortcuts or integrations fail.`,linux:`Grant accessibility permissions in your desktop environment if shortcuts fail.`},automation:{darwin:`Grant Automation (Apple Events) if controlling other apps fails.`,win32:`Configure default apps and automation in Windows Settings if integrations fail.`,linux:`Use desktop portal or session settings for app integration if automation fails.`},notifications:{darwin:`Use Request access, then allow notifications for xopc in System Settings.`,win32:`Use Request access, then allow notifications for xopc in Settings.`,linux:`Allow notifications in your desktop environment or Flatpak permissions.`},location:{darwin:`Grant Location Services for xopc if location features fail.`,win32:`Enable location for desktop apps in Settings if location features fail.`,linux:`Grant location in your desktop portal if location features fail.`}},appManagement:{title:`App management`,loading:`Loading…`,devOnlyTitle:`Development build`,devOnlyBody:`Clear data and uninstall are only available in the packaged desktop app. Paths below are for reference.`,appPath:`Install location`,dataPath:`Local data`,dataSize:`Data size`,dataSizeUnknown:`—`,copyPath:`Copy`,copied:`Copied`,copyFailed:`Could not copy to the clipboard. Select the path and copy manually.`,cliDataWarning:`Separate CLI data was found at ~/.xopc. Clearing local data here does not remove it.`,openCliData:`Open CLI data folder`,pendingUpdateBlocked:`Finish or cancel the pending update before clearing data or uninstalling.`,clearData:`Clear local data`,clearDataDesc:`Remove config, sessions, workspace, and caches. The app will restart with default settings.`,clearDataConfirmTitle:`Clear local data?`,clearDataConfirmDesc:`This permanently deletes API keys, sessions, transcripts, and workspace files stored by the desktop app. This cannot be undone.`,clearDataConfirmCheckbox:`I understand this cannot be undone`,clearDataConfirmPhrase:`confirm delete`,clearDataConfirmLabel:`Type "confirm delete" to continue`,clearDataConfirmHint:`The clear button stays disabled until the phrase matches exactly.`,uninstall:`Uninstall app`,uninstallDescDarwin:`Opens Finder with xopc selected, then quits the app. Drag xopc.app to the Trash to finish uninstalling.`,uninstallDescWin:`Opens the Windows uninstall wizard and quits xopc.`,uninstallDescLinuxAppImage:`Opens the folder containing the AppImage, then quits xopc. Delete the AppImage file to uninstall.`,uninstallDescLinuxDeb:`Quits xopc and opens the install folder. Remove the package with: sudo dpkg -r {{package}} (or use your distro software center).`,uninstallDescLinuxUnknown:`Opens the install location, then quits xopc. Remove the app binary or package using your distro tools.`,uninstallConfirmTitle:`Uninstall xopc?`,removeUserDataCheckbox:`Also clear local data before uninstalling`,confirmClear:`Clear data`,confirmUninstall:`Uninstall`,cancel:`Cancel`,errors:{pendingUpdate:`A downloaded update is waiting to install. Restart to update or wait before uninstalling.`,uninstallerNotFound:`Could not find the uninstaller. Remove xopc from Settings → Apps → Installed apps.`,notPackaged:`This action is not available in development mode. Use the packaged desktop app.`,generic:`Operation failed. Try again or use your system settings to uninstall.`}}},settingsNavGroups:{general:`General`,system:`System settings`,credentials:`Credentials & models`,agent:`Agent settings`,connection:`Connection`,automation:`Automation`,diagnostics:`Diagnostics`,extensions:`Extensions`},cronSettingsPage:{title:`Scheduled tasks`,subtitle:`Global scheduler limits and defaults for all cron jobs.`,tasksLink:`Manage tasks and run history →`},goalsSettingsPage:{title:`Goal judge`,subtitle:`Default settings for persistent /goal tasks and checklist judging.`},imageModelsSettings:{title:`Images`,subtitle:`Vision (understanding) and image-generation defaults, runtime options, and registered image providers.`,refresh:`Refresh`,crossLinkHint:`Primary chat model and sampling are on the Chat tab; text model fallbacks are on the Models tab (same group). This page and Agent defaults together edit vision (understanding) and image-generation fields in agents.defaults.`,timeoutLabel:`Timeout (ms)`,timeoutHint:`Hard cap for one generation attempt; leave empty for the gateway default (120000 ms).`,autoFallbackLabel:`Auto-fallback to any configured provider`,autoFallbackHint:`After the primary chain fails, sweep every other configured provider before giving up.`,save:`Save`,discard:`Discard`,saving:`Saving…`,saved:`Saved.`,fallbackChainsTitle:`Fallback chains`,runtimeTuningTitle:`Runtime tuning`,providersTitle:`Registered providers`,providersEmpty:`No image-generation providers registered.`,configured:`Configured`,missingKey:`Missing API key`,unsavedChanges:`Unsaved`,expandProvider:`Expand provider settings`,collapseProvider:`Collapse provider settings`,defaultModel:`Default`,modelsLabel:`Models`,modelCountOne:`1 model`,modelCountMany:`{count} models`,credentialsIntro:`Set API keys and optional endpoints here. Values are written to config as providers.<id> (same as environment variables). Keys are never returned in full from the gateway.`,apiKeyLabel:`API key`,regionLabel:`Region`,regionHint:`DashScope: pick a region on its card to set region and the official image endpoint (Custom lets you type both).`,endpointPresetsHint:`When a card shows endpoint or cluster presets, pick one or use Custom — values are saved as providers.<id>.baseUrl.`,baseUrlLabel:`Base URL`,imageBaseUrlLabel:`Image base URL`,optionalPlaceholder:`Optional`,saveCredentials:`Save keys`,savingCredentials:`Saving…`,credentialsSaved:`Keys saved.`,discardCredentials:`Discard keys`,credentialsSaveError:`Could not save provider keys.`,credentialsNothingToSave:`No credential changes to save.`,regionPresetDefault:`Default (gateway chooses)`,regionPresetCustom:`Custom region / endpoint`,baseUrlPresetDefault:`Default (vendor official)`,baseUrlPresetCustom:`Custom URL`,openExtensionSettings:`Extension page`,openImageModelsPage:`Open Images settings`,extensionSettingsLinkTitle:`Open this provider’s extension settings`,imageModelsLinkTitle:`Open Images settings for all providers`,imageBaseUrlPresetHint:`Filled from the region preset; switch to “Custom” to edit.`,dashscopeRegion_beijing:`China (Beijing)`,dashscopeRegion_singapore:`International (Singapore)`,dashscopeRegion_us:`United States (Virginia)`,apiKeyMaskedHelp:`Saved keys are hidden. Click the eye to load the key from your config file (providers.<id>.apiKey only — not from environment variables).`,apiKeyCopy:`Copy`,apiKeyCopied:`Copied`,apiKeyShow:`Show key`,apiKeyHide:`Hide key`,apiKeyNotInConfigFile:`No API key in the config file for this provider (it may come only from an environment variable).`,apiKeyRevealFailed:`Could not load key from the gateway.`,minimaxClusterLabel:`MiniMax cluster (API host)`,minimaxClusterHint:`MiniMax chooses China vs international by hostname, not a separate region code. The gateway stores that host as providers.minimax.baseUrl (what the runtime reads). DashScope uses providers.dashscope.region plus an image endpoint URL.`,falQueueBaseLabel:`Fal queue / API base`,falQueueBaseHint:"Fal image calls are rooted at a queue URL (default `https://queue.fal.run`). This maps to `providers.fal.baseUrl`."},extensionImageGen:{banner:`API keys and endpoints are stored globally as providers.<id> (same as Settings → Images). Use either page — they stay in sync.`,openImageModels:`Open Images settings (all providers)`},extensionSttMedia:{banner:`STT credentials are stored in tools.media.audio.providers.<id> (same as Settings → Voice). Use either page — they stay in sync.`,openVoice:`Open Voice settings (all STT providers)`,credentialsTitle:`STT credentials`,credentialsHint:`Edits tools.media.audio.providers.{providerId} and enables STT when you save.`,configured:`Configured`,notConfigured:`Not configured`},appearanceSettings:{pageTitle:`Preferences`,subtitle:`Language, appearance, and text size for daily use. Stored in this browser only.`,languageTitle:`Language`,languageDescription:`Choose the interface language.`,themeTitle:`Theme`,themeDescription:`Light, dark, or follow your system setting.`,colorSchemeTitle:`Color scheme`,colorSchemeDescription:`Visual style of the interface.`,colorSchemeDefault:`Default`,colorSchemeLightGreen:`Light green`,colorSchemeModernMono:`Mono`,colorSchemeClay:`Clay`,fontScaleTitle:`Conversation text size`,fontScaleDescription:`Adjust text size in chat and reading areas.`,fontScaleCompact:`Small`,fontScaleDefault:`Medium`,fontScaleLarge:`Large`,langOptionEn:`English`,langOptionZh:`中文`,themeOptionLight:`Light`,themeOptionDark:`Dark`,themeOptionSystem:`System`,openFullPreferences:`Open all settings`,quickMenuHint:`Language, theme, and text size`,aboutApp:`About`,developerGroupTitle:`Developer`,developerGroupDescription:`Affects how tool-call results are displayed in chat.`,showRawToolDataTitle:`Show tool debugging data`,showRawToolDataDescription:`Reveal raw JSON input and output inside tool-call steps to help diagnose issues.`},mcpSettings:{title:`External tools (MCP)`,subtitle:`Configure outbound MCP servers (stdio or HTTP) for embedded agent runs. Disable all MCP tools with tools.disable: ["bundle-mcp"] on an agent.`,loading:`Loading MCP configuration…`,saved:`MCP configuration saved.`,save:`Save`,discard:`Discard`,saving:`Saving…`,globalTitle:`Runtime`,globalHint:`Session idle TTL controls when unused MCP client runtimes are evicted (0 = never).`,idleTtlLabel:`Session idle TTL (minutes)`,idleTtlHint:`Default is 10 minutes when unset. Set 0 to disable idle eviction.`,idleTtlPlaceholder:`10`,serversTitle:`Servers`,serversHint:`Each server id becomes the prefix in tool names (server__tool). Extension .mcp.json files merge in automatically.`,serversEmpty:`No MCP servers configured yet.`,addServer:`Add server`,removeServer:`Remove`,serverIdPlaceholder:`server-id`,serverIdLabel:`Server name`,serverCardTitle:`MCP server`,cardUntitled:`Untitled server`,cardExpandAria:`Expand server settings`,cardCollapseAria:`Collapse server settings`,transportLabel:`Server type`,commandLabel:`Command`,argsLabel:`Arguments`,argsHint:`Space-separated args (no shell quoting).`,cwdLabel:`Working directory`,envLabel:`Environment (JSON object)`,envHint:"Values may reference ${ENV_VAR}. Dangerous host env keys are filtered at startup.",urlLabel:`Server URL`,headersLabel:`Headers`,optionalSuffix:`(optional)`,headersHint:`Bearer tokens and custom headers for remote MCP servers.`,addHeader:`Add header`,removeHeader:`Remove header`,pasteHeaders:`Paste`,pasteHeadersFailed:`Could not parse headers. Paste a JSON object or lines like "Authorization: Bearer token".`,headerKeyPlaceholder:`Authorization`,headerValuePlaceholder:`Bearer your-token`,timeoutLabel:`Timeout (optional)`,timeoutHint:`Connection, tool list, and tool call timeout in seconds (1–600). Leave empty for the default (30 s).`,timeoutPlaceholder:`30`,testConnection:`Test`,toolsTitle:`MCP tools ({{count}})`,toolsSummary:`{{count}} tools discovered`,toolsLoading:`Fetching tool list…`,toolsEmpty:`No tools returned from this server.`,viewAllTools:`View all`,toolsDialogTitle:`MCP tool list`,toolsDialogSubtitle:`{{serverId}} · {{count}} tools`,toolsDialogSearchPlaceholder:`Search by name or description…`,toolsDialogSearchEmpty:`No tools match your search.`,toolsDialogClose:`Close`,disableHint:`To block MCP tools for an agent, add bundle-mcp to tools.disable on Agent defaults or a specific agent.`,transportLabels:{stdio:`stdio`,sse:`SSE`,"streamable-http":`Streamable HTTP`}}},Ne={appBrand:`XOPC`,sidebarCollapse:`Collapse sidebar`,sidebarExpand:`Expand sidebar`,titleBarCommandPalette:`Command palette`,historyBack:`Back`,historyForward:`Forward`,closeMenu:`Close menu`,openMenu:`Open menu`,appBarPreferences:`Language and theme`,nav:{chat:`Chat`,settings:`Settings`,sessions:`Session management`,cron:`Scheduled Tasks`,skills:`Skills`,channels:`Channels`,agents:`Agents`,apps:`Apps`,logs:`Diagnostic logs`,settingsAppearance:`Preferences`,settingsOverview:`System status`,settingsCredentials:`Credentials hub`,settingsProviders:`LLM providers`,settingsModels:`Models`,settingsImageModels:`Images`,settingsChannels:`Channels`,settingsVoice:`Voice`,settingsGateway:`Gateway`,settingsHeartbeat:`Heartbeat`,settingsTunnel:`Remote access`,settingsShares:`File sharing`,settingsSearch:`Web search`,settingsDreams:`Dreams`,settingsCron:`Scheduled tasks`,settingsGoals:`Goal judge`,settingsAgentDefaults:`Agent settings`,settingsAgentChat:`Default configuration`,settingsAgentWorkspace:`Workspace`,settingsAgentBrowser:`Browser`,settingsAgentRuntime:`Turn limits`,settingsAgentContext:`Context`,settingsAgentMemory:`Memory`,settingsAgentTools:`Tools`,settingsAgentSkills:`Default skill allowlist`,settingsAgentMcp:`External tools (MCP)`,settingsAgentSystemPrompt:`System prompt`,settingsAgents:`Agents`,settingsSystem:`System permissions`,settingsAppManagement:`App management`},token:{title:`Authentication required`,description:`Enter your gateway token to continue.`,gatewayUrl:`Gateway URL`,tokenLabel:`Token`,placeholder:`Gateway token (e.g. ea4c67bf…)`,save:`Save`,show:`Show`,hide:`Hide`},gatewayLanding:{headline:`Connect to this gateway`,subline:`The Web console needs the same token your server uses. Get it from setup or your config file, then paste it below.`,sessionExpired:`Your session expired or the token was rejected. Enter a valid gateway token to continue.`,stepOnboard:`Run xopc onboard (or onboard --gateway) and enable the Web console — the token is printed there.`,stepPaste:`Paste the token here and save. You can also open a link that ends with ?token=… from onboarding.`,stepUrlHint:`Opening a bookmark with ?token= in the URL saves it automatically (the address bar is cleaned afterward).`,docsGatewayLink:`Gateway guide`},electron:{setupBannerTitle:`Finish setup to start chatting`,setupBannerBody:`Add at least one model provider API key and choose a default model. You can change this anytime in Settings.`,setupBannerLinkProviders:`Provider keys`,setupBannerLinkModels:`Default model`,setupBannerDismiss:`Don't show again`,gatewayExitTitle:`Local gateway stopped`,gatewayExitBody:`The assistant backend exited unexpectedly. Restart the app to continue.`},connection:{connecting:`Connecting…`,online:`Online`,reconnecting:`Reconnecting…`,offline:`Offline`,error:`Connection error`,reconnect:`Reconnect`},api:{errorBadGateway:`Bad gateway (502)`,errorServiceUnavailable:`Service unavailable (503)`,errorGatewayTimeout:`Gateway timeout (504)`,errorInternal:`Internal server error (500)`,errorServer:`Server error ({{status}})`,errorNotFound:`Not found (404)`,errorForbidden:`Forbidden (403)`,errorRequest:`Request failed ({{status}})`},sidebar:{newTask:`New task`,moreApps:`More apps`,moreAppsAria:`More apps`,navDragHandle:`Drag to reorder`,tasksHeading:`Tasks`,viewAllSessions:`All sessions`,taskListEmpty:`No chats yet`,taskListNeedToken:`Save a gateway token to load your chats.`,taskListAddToken:`Add token`,taskListStartChat:`Start a chat`,appMenuAria:`App menu and settings`,taskSessionMenuAria:`Session actions`,taskSessionAgentRunning:`Assistant is still responding`,taskRename:`Rename`,taskCopyChatId:`Copy chat ID`,taskChatIdCopied:`Chat ID copied`,taskDeleteTask:`Delete task`,taskRenameTitle:`Rename task`,taskRenamePlaceholder:`Session name`,taskRenameSave:`Save`,taskRenameCancel:`Cancel`,backToApp:`Back to app`,backToAgents:`Back to agents`,back:`Back`,helpDocs:`Documentation`,sessionChannelFilterAria:`Filter tasks: web app or channels`,sessionTasksTab:`Tasks`,sessionChannelsTab:`Channels`,resizeHandleAria:`Resize sidebar`},aboutDialog:{windowTitle:`About this application`,close:`Close`,versionLabel:`Version`,commitLabel:`Commit`,buildDateLabel:`Date`,gatewayVersionLabel:`Gateway`,consoleBuildHint:`Console UI build (this browser bundle). Gateway is the running xopc service.`,checkUpdates:`Check for updates`,checkUpdatesChecking:`Checking...`,checkUpdatesUpToDate:`You're up to date`,checkUpdatesAvailable:`Update available: v{version}`,checkUpdatesDownloading:`Downloading... {percent}%`,checkUpdatesDownloaded:`Ready to install: v{version}`,checkUpdatesError:`Check failed`,gatewayUnavailable:`—`,openSourceLead:`This software is made possible by `,openSourceLink:`open source software`,copyright:`Copyright © {year} xopcai`},updatePanel:{restartToUpdate:`Restart to update`,dismissAria:`Dismiss`,dismissHint:`Do not show this reminder again for this version`,reminderElectronReady:`Update v{{version}} is ready. Restart the app to install.`,reminderDownloading:`Downloading update… {{percent}}%`,reminderElectronUpdateError:`Desktop update failed: {{detail}}`,reminderNpm:`A new version v{{version}} is available for the gateway.`,updateNow:`Update now`,updateRunning:`Updating…`,updateSuccess:`Update installed`,updateSuccessDetail:`Restart the gateway to use the new version (for example: xopc gateway restart).`,updateErrorGit:`One-click update unavailable`,updateErrorBusy:`An update is already in progress`,updateErrorFailed:`Update failed`,restartRequired:`v{{version}} installed. Restart the gateway to use the new version.`,restartGateway:`Restart gateway`,restartPolling:`Gateway is restarting, waiting for it to come back…`,restartPollTimeout:`Gateway did not respond in time. It may still be starting.`,restartPollRetry:`Retry`},commandPalette:{groups:{navigate:`Navigate`,quickSettings:`Quick Settings`,extensions:`Extensions`,sessions:`Sessions`,files:`Files`,commands:`Commands`,skills:`Skills`,actions:`Actions`},routes:{chatSubtitle:`Open chat`,agentsSubtitle:`Manage agents`,appsSubtitle:`Extension apps`,sessionsSubtitle:`Manage and search sessions`,logsSubtitle:`Gateway diagnostic logs`,skillsSubtitle:`Manage skills`,channelsSubtitle:`Channel settings`,cronSubtitle:`Cron jobs and schedules`,cronSettingsSubtitle:`Cron scheduler global settings`,goalsSettingsSubtitle:`Goal judge defaults for /goal`,dreamsSettingsSubtitle:`Memory consolidation schedules`,settingsSubtitle:`Open settings`,credentialsSubtitle:`API keys across chat, search, images, and voice`,providersSubtitle:`LLM provider keys and OAuth`,modelsSubtitle:`Model configuration`,voiceSubtitle:`Voice settings`,gatewaySubtitle:`Gateway settings`,agentDefaultsSubtitle:`Default agent configuration`},quickSettings:{switchModel:`Switch model`,switchModelSubtitle:`Change the default AI model`,switchAgent:`Switch agent`,switchAgentSubtitle:`Change the agent for new chats`,themeLight:`Switch to light theme`,themeDark:`Switch to dark theme`,themeSystem:`Use system theme`,appearanceSubtitle:`Appearance`,languageSubtitle:`Language`,languageEn:`Switch to English`,languageZh:`Switch to 中文`},actions:{createCron:`Create scheduled task`,createCronSubtitle:`Open scheduled tasks (create)`,manageCron:`Manage scheduled tasks`,manageCronSubtitle:`View and edit cron jobs`,manageSkills:`Manage skills`,manageSkillsSubtitle:`View, enable, or disable skills`,reloadSkills:`Reload skills`,reloadSkillsSubtitle:`Reload all skills from disk`}},clipboard:{copy:`Copy`,copied:`Copied!`,copyFailed:`Could not copy to the clipboard. The text is selected — press Ctrl/Cmd+C to copy manually.`}},Pe={sharesSettings:{title:`File sharing`,subtitle:`Manage temporary public download links for workspace files.`,tabShares:`Shares`,tabPolicy:`Policy`,tabsAria:`File sharing settings tabs`,needToken:`Sign in to the gateway to manage file shares.`,emptyState:`No shares yet. Create one from the file tree or via the API.`,createTitle:`Create share`,createHint:`Pick a workspace file or directory to generate a shareable link.`,pathLabel:`File / Directory`,pathPlaceholder:`e.g. reports/monthly.pdf`,pathBrowse:`Browse…`,pathBrowseChange:`Change`,pathPickedFile:`Selected file`,pathPickedDirectory:`Selected directory`,pickerTitle:`Pick something to share`,pickerConfirm:`Pick`,pickerAgentLabel:`Agent`,pickerHintNone:`Click a file or directory, then confirm`,pickerHintNeedsFile:`Please pick a file`,pickerHintNeedsDirectory:`Please pick a directory`,directoryModeLabel:`Directory mode`,directoryModeBrowse:`Browsable`,directoryModeZipOnly:`ZIP only`,ttlLabel:`Expires after`,ttlOptions:{"1h":`1 hour`,"6h":`6 hours`,"24h":`24 hours`,"3d":`3 days`,"7d":`7 days`},maxViewsLabel:`Max downloads`,maxViewsUnlimited:`Unlimited`,descriptionLabel:`Description (optional)`,descriptionPlaceholder:`Brief note for the recipient`,createButton:`Create link`,creating:`Creating…`,shareCreated:`Share link created`,copyUrl:`Copy link`,copy:`Copy`,publicUrlLabel:`Public (FRP)`,lanUrlLabel:`LAN`,localUrlLabel:`Local only`,expiresLabel:`Expires`,copied:`Copied!`,copyFailed:`Could not copy to the clipboard. Select the link and copy manually.`,listTitle:`Active shares`,allSharesTitle:`All shares`,showExpired:`Show expired / revoked`,hideExpired:`Hide expired / revoked`,fileName:`File`,status:`Status`,statusActive:`Active`,statusExpired:`Expired`,statusRevoked:`Revoked`,statusFileGone:`File missing`,views:`Downloads`,viewsOf:`of`,expiresAt:`Expires`,createdAt:`Created`,revoke:`Revoke`,revokeConfirmTitle:`Revoke share?`,revokeConfirmBody:`This link will stop working immediately. This cannot be undone.`,revokeConfirmLabel:`Revoke`,batchRevoke:`Revoke selected`,cleanExpired:`Clean all expired`,cleanExpiredConfirmTitle:`Remove expired shares?`,cleanExpiredConfirmBody:`This will revoke all expired and already-revoked shares permanently.`,cleanExpiredConfirmLabel:`Clean up`,extend:`Extend`,extendTitle:`Extend share`,extendBy:`Extend by`,reachability:`Reachability`,reachPublic:`Public (tunnel active)`,reachLan:`LAN only`,reachLocal:`Local only`,reachLocalHint:`Start the tunnel in Remote Access settings to make shares publicly accessible.`,noShareUrl:`Not reachable externally`,openTunnel:`Open Remote Access`,loading:`Loading shares…`,error:`Failed to load shares`,retry:`Retry`,cancel:`Cancel`,policyTitle:`Share policy`,policyHint:`Limits and defaults for temporary file download links (gateway.share).`,policyEnabled:`Enable file sharing`,policyDefaultTtlHours:`Default expiry (hours)`,policyDefaultTtlHint:`Default TTL for new shares (1–168 hours).`,policyMaxTtlDays:`Maximum expiry (days)`,policyMaxTtlHint:`Upper bound when creating or extending shares (1–30 days).`,policyMaxActiveShares:`Max active shares`,policyMaxActiveSharesHint:`Concurrent non-expired shares allowed (1–10,000).`,policyMaxFileSizeMb:`Max file size (MB)`,policyMaxFileSizeHint:`Per-file limit for share creation (1 MB–10 GB).`,policyInlinePreviewMimes:`Inline preview MIME types`,policyInlinePreviewMimesHint:`MIME types allowed for ?inline=1 browser preview.`,policyMimePlaceholder:`MIME type and press Enter (e.g. image/png)`,policySave:`Save policy`,policyDiscard:`Discard`,policySaving:`Saving…`,policySaved:`Policy saved`,policySaveError:`Failed to save share policy`,policyUnsaved:`You have unsaved policy changes.`,policyRestartHint:`Policy changes require a gateway restart.`,policyLoading:`Loading share policy…`}},Fe={tunnelSettings:{title:`Remote access`,subtitle:`Expose this gateway on the internet so the mobile app can connect from anywhere. Off by default for your security.`,needToken:`Sign in to the gateway (valid token) to manage remote access.`,riskBannerTitle:`Security notice`,riskBannerBody:`Remote access exposes your gateway on the public internet. Only enable when you understand the risks.`,emptyStateTitle:`Get a public HTTPS URL`,emptyStateBody:`Start remote access to reach this gateway from your phone or anywhere on the internet.`,publicUrlLabel:`Public URL`,showOptions:`More options`,hideOptions:`Hide options`,showAdvanced:`Advanced settings`,hideAdvanced:`Hide advanced settings`,pairWaitingForTunnel:`Start remote access above, then scan the QR code here to pair your mobile app.`,consentExpiredBanner:`The remote access security notice was updated. Re-confirm before starting the tunnel or enabling auto-start.`,statusTitle:`Status`,loading:`Loading tunnel status…`,statusConnected:`Connected`,statusConnecting:`Connecting…`,statusReconnecting:`Reconnecting…`,statusPreparingFrpc:`Preparing frpc…`,statusRegistering:`Registering tunnel…`,statusProvisioningTls:`Provisioning HTTPS…`,statusStartingFrpc:`Connecting to frp…`,statusError:`Error`,statusOff:`Off`,frpcDownloading:`Downloading frpc…`,frpcDownloadingPercent:`Downloading frpc… {{percent}}%`,frpcDownloadingBytes:`Downloading frpc… {{received}}`,frpcDownloadingUrlLabel:`Download URL`,frpcExtracting:`Extracting frpc…`,startProgressTitle:`Startup progress`,startProgressHint:`First start can take 2–4 minutes (DNS propagation + HTTPS). DNS validation retries once automatically. The public URL appears before the tunnel is fully ready.`,startProgressElapsed:`Current step: {{elapsed}}`,publicUrlPendingNotice:`Public URL is assigned. Finish the remaining steps before using it remotely.`,stepPrepareFrpc:`Prepare frpc client`,stepRegister:`Register with broker`,stepRegisterDetail:`Public URL assigned — HTTPS and frp connection still in progress`,stepTls:`Provision HTTPS certificate`,stepTlsDetail:`Requesting TLS certificate for your subdomain`,stepTlsChecking:`Checking existing certificate`,stepTlsDnsChallenge:`Publishing DNS validation record`,stepTlsDnsPropagation:`Waiting for DNS on all public resolvers (can take 2–4 minutes)`,stepTlsCaValidation:`Waiting for certificate authority validation`,stepTlsIssuing:`Issuing certificate`,stepFrpcLogin:`Connect frpc to frp server`,stepFrpcDetail:`Waiting for frpc login (up to 60 seconds)`,stepReconnectDetail:`Reconnecting frpc after interruption`,uptime:`Uptime`,lanHint:`For LAN + tunnel QR, set gateway host to 0.0.0.0 in Gateway settings.`,pairTitle:`Mobile app pairing`,pairSubtitle:`Scan with your mobile app. The app exchanges a one-time pairing key for your gateway token.`,pairTunnelActive:`Remote access is on. The QR includes your tunnel URL, LAN address when available, and a one-time pairing key.`,pairBaseUrlLabel:`Gateway URL for pairing`,pairBaseUrlHint:`Use an address reachable from your phone (for example LAN IP and port). This may differ from the address in your desktop browser.`,pairBaseUrlPlaceholder:`http://192.168.x.x:28790`,pairBlockedTitle:`Pairing is not ready on localhost`,pairBlockedLoopbackBody:`Your gateway is only listening on this computer (127.0.0.1). Phones cannot reach that address. Use a LAN IP after exposing the gateway on your network, or start remote access below.`,pairBlockedNextSteps:`Or enable remote access below for tunnel pairing.`,pairEnableLanButton:`Enable LAN pairing`,pairEnableLanConfirmTitle:`Expose gateway on your LAN?`,pairEnableLanConfirmBody:`This sets gateway bind to LAN (0.0.0.0) and restarts the gateway. Anyone on your local network who obtains the pairing QR or token could access your assistant. Only continue on networks you trust.`,pairEnableLanEnabling:`Enabling LAN pairing…`,pairEnableLanSecurityAuditLink:`Review gateway security audit`,pairSuggestedLanLabel:`Suggested LAN address on this machine`,pairUseSuggestedUrl:`Use suggested address`,pairCandidatesTitle:`Detected LAN addresses`,pairSelectCandidateTitle:`Choose a LAN address`,pairSelectCandidateHint:`Pick the address your phone can reach on this network. The mobile app can probe each URL with GET /api/tunnel/pair/ping before pairing.`,pairMobileProbeHint:`Mobile apps: validate manual URLs with POST /api/tunnel/pair/validate-url, probe with GET /api/tunnel/pair/ping, then exchange ps via POST /api/tunnel/exchange-token.`,pairQrDisabled:`Scanning is disabled until the gateway is reachable from your phone.`,pairLocalhostWarning:`This URL looks like localhost. Phones on the network cannot reach your machine unless you expose the gateway (for example bind to LAN and use http://<this-machine-ip>:<port>).`,pairSecurityNote:`The QR contains a one-time pairing key (valid 5 minutes, single use). Only show it where you trust the people and cameras around you.`,pairEncoding:`Generating QR…`,pairImageError:`Could not generate a QR image. Copy the pairing link instead.`,pairCopyLink:`Copy pairing link`,pairCopied:`Copied pairing link`,pairSchemeHint:`Format registered by apps: xopc://gateway/mobile-connect?baseUrl=…&ps=… (exchange ps for token via POST /api/tunnel/exchange-token)`,pairInvalidBaseUrl:`Enter an absolute gateway URL starting with http:// or https:// (no path required).`,pairTunnelPublicUrl:`Tunnel URL`,pairTunnelLanUrl:`LAN URL (in QR)`,start:`Start remote access`,stop:`Disconnect`,release:`Release public URL`,releaseHint:`Revokes the subdomain on the broker. Your next start will get a new public URL.`,releaseConfirmTitle:`Release public URL?`,releaseConfirmBody:`This deregisters the tunnel on frp.xopc.ai and clears saved credentials. You will get a new subdomain when you start remote access again.`,releaseConfirmLabel:`Release`,copyUrl:`Copy public URL`,copied:`Copied`,refreshQr:`Refresh QR`,optionsTitle:`Options`,autoStart:`Start tunnel when gateway launches`,autoStartHint:`Available after you start remote access once and accept the security notice.`,autoStartConfirmTitle:`Start tunnel on every gateway launch?`,autoStartConfirmBody:`Your gateway will be reachable from the internet whenever it runs. Only enable if you accept that risk.`,autoStartConfirmLabel:`Enable auto-start`,consentTitle:`Enable remote access`,consentIntro:`Read carefully before exposing your gateway:`,consentBullet1:`A public URL lets anyone who obtains it use your gateway Bearer token.`,consentBullet2:`Traffic is proxied via frp.xopc.ai (third-party infrastructure).`,consentBullet3:`Use a strong token; stop the tunnel when you do not need remote access.`,consentCheckbox:`I understand these risks and want to enable remote access`,consentConfirm:`Accept and start`,consentReconfirm:`Accept and continue`,consentCancel:`Cancel`,deeplinkTitle:`Deep link payload`,brokerNote:`Traffic is proxied via frp.xopc.ai. Keep your gateway token private.`,brokerDocsLink:`Public tunnel security docs`,brokerSecretTitle:`Tunnel Registration Key`,brokerSecretStepTitle:`Step 1 · Tunnel Registration Key`,brokerSecretHint:`Create a Tunnel Registration Key in the xopc Console, paste it below, and save. The key registers with frp.xopc.ai via the X-Registration-Secret header and is stored in xopc.json on this machine.`,brokerSecretConsoleLink:`Create Tunnel Registration Key in Console`,brokerSecretEnvHint:`The legacy environment variable XOPC_TUNNEL_REGISTRATION_SECRET is set (it overrides the value below). Create a new key in the Console, save it here, then remove the env var.`,brokerSecretMaskedHelp:`A key is saved in local config. You can view, copy, or replace it.`,brokerSecretPlaceholder:`Paste Tunnel Registration Key`,brokerSecretPlaceholderKeep:`Paste a new Tunnel Registration Key`,brokerSecretMissingHint:`Create a key in the Console first, then paste it here and save.`,brokerSecretRequiredBeforeStart:`Save a Tunnel Registration Key above before starting remote access.`,brokerSecretSave:`Save key`,brokerSecretSaveAndContinue:`Save and continue`,brokerSecretClear:`Clear saved key`,brokerSecretSaved:`Tunnel Registration Key saved`,brokerSecretCleared:`Saved Tunnel Registration Key cleared`,brokerSecretReadyTitle:`Tunnel Registration Key configured`,brokerSecretReadyHint:`You can start remote access below. Use Reconfigure to replace the key.`,brokerSecretReconfigure:`Reconfigure`,brokerSecretCancelReconfigure:`Cancel`,brokerSecretRevealFailed:`Could not load the saved key`,brokerSecretNotInConfigFile:`Key is not in the config file; plaintext cannot be shown.`,copyKey:`Copy key`,showKey:`Show key`,hideKey:`Hide key`,flowStepStart:`Step 2 · Start remote access`}},Ie={skills:{title:`Skills`,needToken:`Save a gateway token to manage skills.`,tagline:`Install and manage skills to extend XOPC in conversation.`,refresh:`Refresh list`,reloadRuntime:`Reload from disk`,reloadDiskAria:`Reload skills from disk`,skillsNavAria:`Skill sources`,tabBuiltin:`Built-in`,tabUser:`Installed`,tabMarketplace:`Marketplace`,marketplacePlaceholder:`The skill marketplace is coming soon.`,sectionMarketplace:`Skill store`,marketplaceBrowseSkillhub:`SkillHub`,marketplaceBrowseClawhub:`ClawHub`,marketplaceBrowseStore:`XOPC Store`,marketplaceBrowseSwitchAria:`Skills marketplace source`,marketplaceResultsTabsAria:`Search result source`,marketplaceResultsTabAll:`All`,marketplaceSortLabel:`Sort`,marketplaceSortDownloads:`Most downloads`,marketplaceSortNewest:`Newest`,marketplaceCategoryAll:`All`,marketplaceCategoriesAria:`Marketplace categories`,marketplaceCategoriesFailed:`Could not load categories`,marketplaceSearchPackages:`Search skill name, description, tags…`,marketplaceStars:`Stars`,marketplaceSource:`Source`,marketplaceLoadFailed:`Failed to load marketplace`,marketplaceEmpty:`No packages match your search.`,marketplaceEmptySearch:`No skills match "{{query}}".`,marketplaceEmptySearchTryProvider:`Search in {{provider}}`,marketplaceEmptySearchClear:`Clear search`,marketplaceInstall:`Install`,previewUseInChat:`Use in chat`,previewUseInChatBusy:`Installing…`,marketplaceReinstall:`Reinstall`,marketplaceInstalled:`Installed`,marketplaceReinstallConfirm:`This skill is already installed. Replace it with the version from the store?`,marketplacePagePrev:`Previous page`,marketplacePageNext:`Next page`,marketplacePageStatus:`Page {{page}} of {{totalPages}} · {{total}} packages`,marketplaceAuthor:`Author`,marketplaceOpenOnSkillhub:`Open on SkillHub`,marketplaceOpenOnSkillhubAria:`Open this skill on skillhub.cn in a new tab`,marketplaceOpenExternal:`Open on registry`,marketplaceOpenExternalAria:`Open this skill on its registry page in a new tab`,marketplaceDownloads:`Downloads`,marketplaceVersion:`Latest`,sectionBuiltinList:`Built-in skills`,categoryLabel:{business:`Business`,creative:`Creative & Design`,documents:`Documents`,engineering:`Engineering`,tools:`Tools & Utilities`},filterAll:`All`,filterDisabledOnly:`Disabled only ({{count}})`,filterDisabledOnlyAria:`Show only disabled skills`,statusDisabled:`Disabled`,statusEnabled:`Enabled`,noDisabledSkills:`No disabled skills in this list.`,filterGlobal:`Global`,filterWorkspace:`Workspace`,filterExtra:`Extra`,sectionUser:`Your skills`,installCta:`Install skill`,installModalTitle:`Install skill`,installModalDropHint:`Drop a .zip or SKILL.md file, or click to choose.`,installModalReqTitle:`Requirements`,installModalReq1:`A .zip archive that contains SKILL.md`,installModalReq2:`Or drop a SKILL.md file directly`,installAction:`Install`,installClose:`Close`,searchPlaceholder:`Search skills`,noSearchResults:`No skills match your search.`,uploading:`Uploading…`,loading:`Loading…`,empty:`No skills loaded.`,loadFailed:`Failed to load skills`,reloadFailed:`Failed to reload skills`,skillToggleFailed:`Failed to update skill`,uploadFailed:`Upload failed`,installSuccess:`Skill installed.`,zipOnly:`Please choose a .zip file`,invalidFile:`Choose a .zip or SKILL.md file`,delete:`Delete`,deleteTitle:`Delete skill`,deleteMessage:`Remove folder "{{id}}" from managed skills? This cannot be undone.`,deleteConfirm:`Delete`,deleteFailed:`Failed to delete skill`,yes:`Yes`,no:`No`,cancel:`Cancel`,source:{builtin:`Bundled`,workspace:`Workspace`,global:`Global`,extra:`Extra`},col:{name:`Name`,description:`Description`,source:`Source`,managed:`Managed`,actions:`Actions`},detailModalBanner:`Metadata comes from SKILL.md YAML frontmatter; the instruction body below excludes that block.`,detailModalBannerStore:`Preview below is the markdown published with this package on the skill store (same content as the package readme).`,detailSummaryHeading:`Summary`,detailInstructionsHeading:`Instructions`,detailNoInstructionsBody:`No instruction body after frontmatter.`,detailHomepageLabel:`Homepage`,detailPlatformsLabel:`Platforms`,detailRequiresLabel:`Requirements`,detailRequiresBins:`Binaries`,detailRequiresEnv:`Environment variables`,detailRequiresAnyBins:`Any of these binaries`,detailInstallLabel:`Install steps`,detailToolGatingLabel:`Tool visibility`,detailToolsRequiresList:`Requires tools`,detailToolsetsRequiresList:`Requires toolsets`,detailToolsFallbackList:`Fallback tools`,detailToolsetsFallbackList:`Fallback toolsets`,detailEnvVarsLabel:`Session environment variables`,detailNotInjectedNote:`This skill is not injected into model context (disable-model-invocation).`,marketplaceNoReadme:`No readme text is available for this package.`,detailModalEnable:`Enable`,detailModalDisable:`Disable`,useRequiresEnabled:`Enable this skill before using it in chat`,detailLoadFailed:`Failed to load SKILL.md`,detailCloseAria:`Close`,hubRemote:`Remote`,hubKindGit:`git`,hubKindArchive:`archive`},skillsMarketplaceSettings:{title:`Marketplace source`,hint:`Default provider and store API base URL for the Skills marketplace tab.`,save:`Save`,discard:`Discard`,saving:`Saving…`,saveError:`Failed to save marketplace settings`,provider:`Provider`,providerHint:`Which catalog to browse by default (store, skillhub, clawhub).`,storeBaseUrl:`Store base URL`,storeBaseUrlHint:`REST base for package listings. Override with XOPC_SKILLS_STORE_URL env if needed.`}},Le={workspace:{title:`Project Files`,currentWorkspace:`Current Workspace`,openFiles:`Project Files`,preview:`Preview`,download:`Download`,copyPath:`Copy Path`,pathCopied:`Path copied`,edit:`Edit`,viewing:`Viewing`,saved:`Saved`,saving:`Saving…`,emptyDir:`No files`,loadError:`Failed to load`,close:`Close`,resizeHandleAria:`Resize project files panel`,lastModified:`Modified`,openElsewhereHint:`Preview may be limited or unavailable. Download the file or open it with another app.`,cannotPreviewType:`This file type can't be previewed here.`,openSystemApp:`Open with default app`,revealInFolder:`Show in folder`,shareLink:`Share link`,sharing:`Creating share…`,shareFailed:`Failed to create share link`}},Re={agentSettings:JSON.parse('{"subtitle":"模型、工作区、采样与输出方式的默认配置。","sectionDesc":"修改将写入网关配置文件;部分项在下一轮对话或新会话中生效。","needToken":"请先保存网关访问令牌后再加载或修改智能体默认项。","loadError":"加载设置失败","save":"保存","discard":"放弃","saving":"保存中…","saved":"已保存","saveError":"保存失败","routeIntro":{"chat":"主模型、采样参数与界面展示方式。保存到网关配置中的 agents.defaults。","workspace":"智能体工作目录与图像工具加载入站图片的体积上限。","browser":"让智能体通过 browser_use 操作网页。启用工具、选择连接方式,再在下方完成就绪配置。","runtime":"单轮耗时、工具调用轮数、请求重试与连续工具失败上限。保存到 agents.defaults。","context":"上下文压缩与工具结果裁剪,控制送入模型的历史体积。","memory":"记忆快照、session_search 摘要模型与可选的后台审阅。","tools":"可选工具(网页抽取、子任务委托、沙箱执行代码)、全局禁用内置工具,以及扩展用 Params(JSON)。技能白名单见「技能」页。","skills":"技能市场来源(在该区块内单独保存)与全部智能体的默认技能白名单(使用页头保存)。在「技能库」安装技能;按工具开关见「工具」页。","systemPrompt":"可选覆盖默认系统提示;与条目级合并(条目优先)。保存到 agents.defaults。"},"defaultsTabs":{"chat":"模型与对话","workspace":"工作区","browser":"浏览器","runtime":"单轮限制","context":"上下文","memory":"记忆","tools":"工具","skills":"技能","system-prompt":"系统提示词"},"defaultsTabsAria":"智能体默认配置分区","browserTabs":{"overview":"概览","extension":"Chrome 扩展","local":"本地 Chromium","cloakbrowser":"CloakBrowser","cdp":"CDP","cloud":"云端"},"browserTabsAria":"浏览器设置分区","cardModelsTitle":"模型","cardModelsSubtitle":"对话、视觉与图像生成默认模型","cardWorkspaceTitle":"工作区与附件","cardWorkspaceSubtitle":"工作目录与入站媒体大小限制","cardBrowserTitle":"浏览器自动化","cardBrowserSubtitle":"browser_use — 导航、快照、点击、截图、流水线等(后端可选 Chrome 扩展、Playwright、CloakBrowser…)","browserEnabledOn":"启用浏览器工具","browserHeadlessOn":"无头模式(不显示浏览器窗口)","browserAllowPrivateOn":"允许内网/私有 URL","browserDialogPolicyMustRespond":"智能体必须响应","browserDialogPolicyAutoDismiss":"自动关闭","browserDialogPolicyAutoAccept":"自动接受","browserBackendLocal":"本地(Playwright)","browserBackendCdp":"CDP(远程)","browserBackendCloud":"云端服务","browserBackendExtension":"Chrome 扩展","browserBackendCloakBrowser":"CloakBrowser","browserCloudProviderLocal":"本地(Playwright)","browserCloudProviderBrowserbase":"Browserbase","browserCloudProviderBrowserUse":"Browser Use","browserExtensionConnected":"已连接","browserExtensionDisconnected":"未连接","browserExtensionWaiting":"等待连接…","browserExtensionServerOff":"服务未启动","browserPlaywrightGuideTitle":"本地 Playwright 需要先安装 Chromium","browserPlaywrightGuideDesc":"选择本地(Playwright)时,Chromium 需要安装在网关所在机器。可以点击安装,也可以登录网关机器手动执行安装命令。","browserPlaywrightInstall":"安装","browserPlaywrightInstalling":"安装中…","browserPlaywrightInstalled":"Chromium 已安装","browserPlaywrightInstallFailed":"Chromium 安装失败","browserPlaywrightManualInstall":"手动安装命令","browserCloakGuideTitle":"首次使用前请先下载 CloakBrowser","browserCloakGuideDesc":"CloakBrowser 会提供反指纹 Chromium。保存后,网关会按配置使用它;也可以先在终端执行安装命令完成下载。","browserCloakDownload":"下载","browserCloakInstalling":"下载中…","browserCloakInstalled":"CloakBrowser 已下载","browserCloakInstallFailed":"CloakBrowser 下载失败","browserCloakOpen":"打开浏览器","browserCloakOpening":"正在打开…","browserCloakOpenReused":"已连接到运行中的浏览器 · 端口 {{port}}","browserCloakOpenLaunched":"已打开 · 端口 {{port}}","browserCloakProfileLabel":"用户资料","browserCloakProfileAgentHint":"使用已保存配置中的 profile,与智能体运行时一致。修改路径或 profile 选项后请先保存。","browserCloakRuntimeRunning":"运行中 · 端口 {{port}}","browserCloakRuntimeOff":"未运行","browserCloakTemporaryProfileHint":"已启用临时资料 — 每次启动使用新的 profile","browserInstallPhaseStarting":"准备中…","browserInstallPhaseDownloading":"下载中…","browserInstallPhaseDownloadingPercent":"下载中… {{percent}}%","browserInstallPhaseVerifying":"校验 SHA-256…","browserInstallPhaseExtracting":"解压中…","browserInstallPhaseRunning":"安装中…","browserInstallPhaseReady":"即将完成…","browserInstallCancel":"取消","browserInstallCancelling":"取消中…","browserInstallCancelled":"安装已取消","browserCloakKeepOpenOn":"任务之间保持浏览器常驻","browserCloakTemporaryProfileOn":"每次使用临时用户资料","browserHumanizeOn":"模拟更自然的鼠标、键盘与滚动","browserHumanPresetCareful":"更稳妥(推荐)","browserHumanPresetDefault":"标准","browserModeLocalShort":"本地 Chromium","browserModeCloakShort":"CloakBrowser","browserModeCdpShort":"CDP","browserModeCloudShort":"云端","browserModeExtShort":"扩展","browserModeLocalTagline":"网关机器自带的 Playwright Chromium","browserModeCloakTagline":"反指纹 Chromium,适合隐身自动化","browserModeCdpTagline":"驱动本机一个可调试 Chrome","browserModeCloudTagline":"Browserbase / Browser Use 远程浏览器","browserModeExtTagline":"桥接真实用户的 Chrome 扩展","browserDisabledHint":"启用浏览器工具后,可选择连接方式并配置后端。","browserDocsLink":"浏览器工具文档","browserSetupTitle":"快速开始","browserSetupSubtitle":"选择一种连接方式 — 启用浏览器工具后随时可改。","browserSetupRecommended":"推荐","browserSetupSelect":"使用此方式","browserSetupExtTitle":"Chrome 扩展","browserSetupExtDesc":"桥接日常 Chrome,适合需要已登录会话的网站。","browserSetupLocalTitle":"本地 Playwright","browserSetupLocalDesc":"在网关主机运行 Chromium(可无头)。安装一次后保存即可。","browserSetupCloudTitle":"云端浏览器","browserSetupCloudDesc":"Browserbase 或 Browser Use — 无需在本机安装 Chromium。","browserStatusStripBackend":"当前连接","browserWorkspaceExtSubtitle":"安装扩展、启动桥接,并在 Chrome 中完成连接。","browserWorkspaceLocalSubtitle":"在网关主机安装 Chromium,以本地运行 Playwright。","browserWorkspaceCloakSubtitle":"下载 CloakBrowser 并调整反指纹选项。","browserWorkspaceCdpSubtitle":"启动或通过 CDP 连接可调试的 Chrome。","browserWorkspaceCloudSubtitle":"使用 API 凭证连接 Browserbase 或 Browser Use。","browserBehaviorShow":"运行与交互","browserBehaviorHide":"收起运行与交互","browserBehaviorHint":"无头模式与 JavaScript 对话框处理,对所有后端生效。","browserSecurityShow":"安全与限制","browserSecurityHide":"收起安全与限制","browserSecurityHint":"内网 URL 访问与单命令超时。云元数据端点始终被拦截。","browserPickerTitle":"生效的浏览器","browserPickerSubtitle":"选择智能体运行时使用的后端。各后端的详细配置在对应 Tab 中设置。","browserGoToConfigure":"前往配置","browserConfiguringHeader":"正在配置:{{mode}}","browserSelectedBadge":"已选中","browserStatusReady":"就绪","browserStatusNotInstalled":"未安装","browserStatusChecking":"检测中…","browserStatusUnknown":"未知","browserStatusError":"错误","browserAdvancedShow":"高级设置","browserAdvancedHide":"收起高级设置","browserReinstall":"重新安装","browserConfirmDownloadTitle":"下载外部二进制","browserConfirmDownloadBody":"即将从 {{url}} 下载 CloakBrowser {{version}}(平台 {{platform}}),解压前会做 SHA-256 校验。","browserConfirmDownloadConfirm":"下载并安装","browserConfirmDownloadCancel":"取消","browserCloakSha256Skipped":"当前平台尚未在 manifest 中提供 SHA-256,安装时不会做完整性校验。","browserCloakAdvancedShow":"路径与指纹","browserCloakAdvancedHide":"收起路径与指纹","browserCloakAdvancedHint":"二进制缓存、自定义可执行文件、时区/语言模拟、WebRTC IP 及额外 Chromium 启动参数。","browserCdpLaunchLocal":"在本机启动可调试 Chrome","browserCdpLaunchLocalDesc":"由网关帮你 spawn 一个带 --remote-debugging-port 的 Chrome;窗口会一直保留,直到点击「停止」。","browserCdpLaunching":"启动中…","browserCdpStopLocal":"停止本机 Chrome","browserCdpLaunchedAtPort":"已启动,监听端口 {{port}} — 下方端点已自动填入。","browserCdpTestConnection":"测试连接","browserCdpTesting":"测试中…","browserCdpReachable":"可达 — {{browser}}","browserCdpUnreachable":"不可达:{{error}}","browserCdpLoopbackOnly":"安全起见,只允许 loopback 端点(127.0.0.1 / localhost / ::1)。","browserCdpChromePath":"Chrome 可执行路径(可选)","browserCdpChromePathDesc":"可选项。留空时优先用 Playwright Chromium,再回落到系统 Chrome / Chromium。","browserCloudTestConnection":"测试连接","browserCloudTestOk":"连接成功 ✓","browserCloudTestFailed":"失败:{{error}}","browserBinaryPathWarning":"⚠ 网关会以自身权限执行此路径下的二进制,仅在你信任来源时填写。","browserCacheDirHomeOnly":"必须在用户家目录之下(例如 ~/.xopc/bin)。","browserExtensionDownloadHint":"在真实 Chrome 中加载 xopc 扩展,通过 WebSocket 与网关桥接。","browserExtensionInstall":"安装到本地","browserExtensionInstalling":"安装中…","browserExtensionInstalled":"扩展已复制到","browserExtensionOpenChrome":"打开 chrome://extensions","browserExtensionRevealFolder":"复制路径并打开文件夹","browserExtensionPathCopied":"路径已复制,并已在 Finder/资源管理器中打开文件夹。","browserExtensionFolderOpened":"已在 Finder/资源管理器中打开文件夹。","browserExtensionNeedsChromeReload":"xopc 已更新磁盘上的扩展。请打开 chrome://extensions,在 xopc 扩展上点击「重新加载」。","browserExtensionInstallGuideTitle":"安装清单","browserExtensionChecklistProgress":"已完成 {{done}}/{{total}}","browserExtensionChecklistDone":"已完成:","browserExtensionChecklistPending":"待完成:","browserExtensionInstallStep1":"点击上方「安装到本地」,将扩展复制到本机目录。","browserExtensionInstallStep2":"打开 chrome://extensions → 开启「开发者模式」→ 点击「加载已解压的扩展程序」→ 选择下方文件夹。","browserExtensionInstallStep2FolderLabel":"扩展文件夹","browserExtensionInstallStep3":"点击「启动桥接」,在 Chrome 工具栏的 xopc 扩展弹窗中点击连接。","browserExtensionStartBridge":"启动桥接","browserExtensionStarting":"启动中…","browserExtensionStopBridge":"停止桥接","browserExtensionDisconnect":"断开扩展","browserExtensionPortConflict":"端口 {{port}} 已被占用。若为本网关桥接,请点击「停止桥接」;否则请更换端口或结束占用进程。","browserExtensionStartHint":"立即启动 WebSocket 桥接,无需先保存配置即可完成扩展配对。桥接会一直运行直到你点击「停止」。","cardGenerationTitle":"采样与工具","cardGenerationSubtitle":"输出上限(Token)、随机性与工具调用轮数","cardBehaviorTitle":"推理与输出","cardBehaviorSubtitle":"思考深度、推理可见性与详细程度","label":{"model":"模型","modelFallbacks":"备用模型","imageModel":"图像理解模型","imageModelFallbacks":"图像理解备用模型","imageGenerationModel":"图像生成模型","imageGenerationModelFallbacks":"图像生成备用模型","mediaMaxMb":"图像加载上限 (MB)","workspace":"工作区","browserEnabled":"浏览器工具","browserHeadless":"无头模式","browserAllowPrivateUrls":"允许私有 URL","browserCommandTimeout":"命令超时(秒)","browserBackend":"后端模式","browserCloudProvider":"云端服务商","browserCloudApiKey":"API Key","browserCloudProjectId":"Browserbase 项目 ID","browserCloudRegion":"云端区域","browserCdpUrl":"CDP 端点 URL","browserExtensionPort":"扩展端口","browserExtensionHost":"扩展主机","browserExtensionConnectionTimeout":"连接超时(秒)","browserCloakKeepOpen":"保持常驻","browserCloakTemporaryProfile":"临时资料","browserCloakCacheDir":"下载缓存目录","browserCloakBinaryPath":"浏览器路径","browserCloakTimezone":"时区","browserCloakLocale":"语言区域","browserCloakWebrtcIp":"WebRTC 公网 IP","browserCloakFingerprintPlatform":"指纹平台","browserCloakExtraArgs":"额外 Chromium 参数","browserHumanize":"拟人化操作","browserHumanPreset":"操作节奏","browserDialogPolicy":"对话框处理策略","browserDialogTimeout":"对话框超时(秒)","maxTokens":"最大 Token 数","temperature":"温度","maxToolIterations":"最大工具调用轮数","thinkingDefault":"思考级别","reasoningDefault":"推理可见性","verboseDefault":"详细程度"},"desc":{"model":"新会话的默认模型。","modelFallbacks":"主模型在瞬时重试后仍失败时,按顺序尝试。各服务商均需配置 API Key。","imageModel":"可选,用于图像理解 / 视觉。下列仅展示网关判定为接受图像输入的模型。","imageModelFallbacks":"主视觉模型失败时按顺序尝试。下列仅展示标记为支持图像输入的模型。","imageGenerationModel":"可选,用于 image_generate。下列仅展示网关判定为已配置 API 凭证的图像生成服务商。","imageGenerationModelFallbacks":"主图像生成模型失败时按顺序尝试。下列仅展示已配置凭证的图像生成服务商。","mediaMaxMb":"图像工具加载单张图片时的最大体积。","workspace":"智能体读写文件的工作目录。","browserEnabled":"向模型暴露 browser_use 浏览器自动化工具(具体浏览器由下方「后端模式」决定)。","browserHeadless":"默认关闭:在网关机器上显示 Chromium 窗口。开启后为无头/后台运行(不显示窗口)。","browserAllowPrivateUrls":"跳过导航时的私有 IP 拦截。云元数据端点(169.254.169.254 等)始终被拦截。","browserCommandTimeout":"单条浏览器命令(导航、点击等)的最大秒数。默认 30。","browserBackend":"连接模式:本地 Playwright、远程 CDP、云端服务或 Chrome 扩展桥接。","browserCloudProvider":"云端服务商:Browserbase 或 Browser Use。可在这里直接填写 API Key;也兼容环境变量 BROWSERBASE_API_KEY / BROWSER_USE_API_KEY。","browserCloudApiKey":"保存在网关配置中。留空则使用进程环境变量;已保存的密钥会以掩码显示。","browserCloudProjectId":"Browserbase 可选项目 ID;留空时使用 BROWSERBASE_PROJECT_ID 或服务商默认值。","browserCloudRegion":"可选。服务商支持区域时传入;留空使用默认区域。","browserCdpUrl":"Chrome DevTools Protocol 的 WebSocket 端点(如 ws://localhost:9222)。仅在 CDP 模式下使用。","browserExtensionPort":"Chrome 扩展桥接的 WebSocket 端口。默认 19820。","browserExtensionHost":"Chrome 扩展桥接的主机地址。默认 127.0.0.1。","browserExtensionConnectionTimeout":"网关等待扩展连接的最长时间(秒)。默认 30。","browserCloakKeepOpen":"复用同一个 CloakBrowser 进程,减少后续任务启动时间。默认开启。","browserCloakTemporaryProfile":"每次启动时使用临时用户资料目录,关闭后清理。适合隔离测试。","browserCloakCacheDir":"可选。CloakBrowser 根目录(二进制与 profiles);留空使用 ~/.xopc/bin/cloakbrowser。","browserCloakBinaryPath":"可选。已下载的 CloakBrowser/Chromium 可执行文件路径;通常位于 ~/.xopc/bin,填写后跳过自动下载。","browserCloakTimezone":"可选,模拟的 IANA 时区(如 America/New_York)。","browserCloakLocale":"可选,模拟的语言区域(如 en-US)。","browserCloakWebrtcIp":"可选,用于 WebRTC 泄露防护的公网 IP。","browserCloakFingerprintPlatform":"可选,指纹模拟的平台标识(如 windows、macos)。","browserCloakExtraArgs":"每行一个 Chromium 启动参数。相同 --key= 前缀会覆盖默认值。","browserHumanize":"使用贝塞尔鼠标轨迹、逐字输入和滚动节奏,降低自动化痕迹。","browserHumanPreset":"选择操作节奏;更稳妥会慢一些但更接近真人操作。","browserDialogPolicy":"JS 对话框(alert/confirm/prompt)的处理方式:智能体必须响应、自动关闭或自动接受。","browserDialogTimeout":"未处理的对话框在自动策略下的等待秒数。默认 300。","maxTokens":"模型回复的最大 Token 数。","temperature":"随机性(0–2)。","maxToolIterations":"单条用户消息内最多进行多少轮工具调用。","thinkingDefault":"新会话的默认思考级别。","reasoningDefault":"是否在聊天界面展示模型推理。若会话曾设置 /reasoning 等,会覆盖此默认直至清除会话配置。","verboseDefault":"智能体在日志与工具细节上的详细程度,不控制聊天中的推理/思考区块;若要隐藏推理请使用「推理可见性」。"},"addModelFallback":"添加备用模型","removeModelFallback":"移除备用模型","setDefaultWorkspace":"设为默认","visionRegistryEmpty":"当前已配置的服务商下,没有标记为支持图像输入的模型。可在 models.json 中为模型设置包含 \\"image\\" 的 `input`,或选择上游目录中声明支持图像的模型。","visionOutOfFilterNote":"网关模型目录未将该模型标为支持图像;建议尽量选择带图像能力的模型。","imageGenRegistryEmpty":"当前没有已配置 API 凭证的图像生成服务商。请在配置或环境变量中填写对应密钥(如 OpenAI)后刷新。","imageGenOutOfFilterNote":"该模型所属服务商未配置凭证;在配置完成或改选已配置的服务商之前,image_generate 将无法使用该模型。","reasoning":{"off":"关闭","on":"开启","stream":"流式"},"verbose":{"off":"关闭","on":"开启","full":"完整"},"advanced":{"advancedOptionsShow":"高级选项","advancedOptionsHide":"收起高级选项","cardLimitsTitle":"单轮限制与可靠性","cardLimitsSubtitle":"单轮最大耗时、重试与工具连续失败次数。","maxTaskDurationMs":"单轮最长时间(分钟)","maxTaskDurationMsDesc":"单条用户消息内(模型 + 工具)墙钟上限。留空用服务端默认。范围 1–240 分(1 分–4 小时)。","maxTaskDurationPlaceholder":"如 30(留空为默认)","maxRequestsPerTurn":"每轮最大请求数","maxRequestsPerTurnDesc":"单条用户消息内大模型重试/请求尝试上限(默认 50)。","maxToolFailuresPerTurn":"每轮最大工具失败次数","maxToolFailuresPerTurnDesc":"连续工具错误达到该值后放弃(默认 3)。","goalsCheckLink":"目标检查 (/goal) → 目标评判设置","goalsCheckLinkHint":"清单评判默认值在「设置 → 自动化 → 目标评判」中配置。","cardCompactionTitle":"上下文压缩","cardCompactionSubtitle":"在上下文中按策略压缩较早内容以适配窗口。","compactionEnabled":"启用压缩","compactionEnabledDesc":"关闭后不按策略压缩(可能更占上下文)。","compactionEnabledOn":"启用压缩","compactionMode":"模式","compactionModeDesc":"default:标准;safeguard:更谨慎的启发式。","compactionModeDefault":"default","compactionModeSafeguard":"safeguard","reserveTokens":"保留 token","reserveTokensDesc":"压缩后为目标模型预留的头部空间(默认 8000)。","triggerThreshold":"触发阈值","triggerThresholdDesc":"已用上下文比例达到该值时考虑压缩(0.5–0.95)。","minMessagesBeforeCompact":"最早压缩前消息数","minMessagesBeforeCompactDesc":"达到该条数后才允许开始压缩(默认 10)。","keepRecentMessages":"保留最近消息数","keepRecentMessagesDesc":"尾部始终完整保留的最近轮次(默认 5)。","evictionWindow":"逐出窗口","evictionWindowDesc":"可参与先摘要/逐出策略的历史比例(0.1–0.5)。","retentionWindow":"保留窗口","retentionWindowDesc":"参与保留策略的轮次宽度(3–20)。","cardPruningTitle":"工具结果裁剪","cardPruningSubtitle":"在送入模型前截断过长的工具输出。","pruningEnabled":"启用裁剪","pruningEnabledDesc":"关闭后整段工具结果可能入模型(成本更高)。","pruningEnabledOn":"启用裁剪","maxToolResultChars":"单条工具结果最大字符","maxToolResultCharsDesc":"单条工具结果默认上限(默认 10000)。","headKeepRatio":"保留开头比例","headKeepRatioDesc":"裁剪时从开头保留比例(0–1,默认 0.3)。","tailKeepRatio":"保留结尾比例","tailKeepRatioDesc":"从结尾保留比例(0–1,默认 0.3)。","cardMemoryTitle":"记忆(精选与外部)","cardMemorySubtitle":"系统记忆、USER.md 与可选外部 provider。","memoryEnabled":"记忆功能","memoryEnabledDesc":"总开关:精选记忆快照、工具与外部预取。","memoryEnabledOn":"启用","useEnhancedSystem":"增强 system","useEnhancedSystemDesc":"关闭时仅使用工作区内的角色配置(不附加额外记忆快照)。","useEnhancedSystemOn":"使用增强 system","userProfileEnabled":"包含 USER.md","userProfileEnabledDesc":"在快照中纳入 USER.md。","userProfileEnabledOn":"包含用户侧写","memoryProvider":"外部记忆 provider","memoryProviderDesc":"选 none / stub 或留空视为不设置。","memoryProviderUnset":"(不设置)","injectionFrequency":"外部预取注入","injectionFrequencyDesc":"将预取记忆注入到用户消息上下文的频率。","injectionFrequencyUnset":"(不设置)","injectionEveryTurn":"每轮(配合 cadence)","injectionFirstTurn":"仅首轮","memoryCharLimit":"记忆字符上限","memoryCharLimitDesc":"精选记忆快照最大字符数(可选)。","userCharLimit":"用户侧写字符上限","userCharLimitDesc":"USER.md 区块最大字符数(可选)。","contextCadence":"上下文节奏","contextCadenceDesc":"每轮注入时:在轮次 1、1+N、… 注入(最小 1)。","dialecticCadence":"对话节奏(预留)","dialecticCadenceDesc":"预留,尚未接入。设置时最小为 1。","cardSessionSearchTitle":"会话搜索(转写)","cardSessionSearchSubtitle":"session_search 工具中用于历史会话摘要的模型。","sessionSearchSummaryModel":"摘要模型","sessionSearchSummaryModelDesc":"如 openai/gpt-4o-mini。留空用运行时的默认/启发式。","cardReviewTitle":"后台审阅","cardReviewSubtitle":"成功回合后可选的静默跟进(记忆/技能)。默认关闭。","reviewEnabled":"启用后台审阅","reviewEnabledDesc":"开启后,成功轮次后可能跑静默跟进。","reviewEnabledOn":"启用","memoryNudgeInterval":"记忆审阅节奏(每 N 轮用户消息)","memoryNudgeIntervalDesc":"0 表示关闭该通道。默认 10。","skillNudgeInterval":"技能审阅(无 skill_manage 的轮数)","skillNudgeIntervalDesc":"0 表示关闭。默认 10。","reviewMaxToolRounds":"审阅中最大工具轮数","reviewMaxToolRoundsDesc":"1–32,默认 8。","reviewMaxHistoryMessages":"审阅上下文中最大消息数(尾部)","reviewMaxHistoryMessagesDesc":"10–200,默认 80。","reviewMaxDurationMs":"审阅时间上限(秒)","reviewMaxDurationMsDesc":"单轮审阅墙钟 30–600 秒,默认 120 秒。","cardWebExtractTitle":"web_extract(LLM 提取)","cardWebExtractSubtitle":"网页转 Markdown 提取的可选模型与长度。","webExtractModel":"模型","webExtractModelDesc":"留空用默认提取模型/启发式。","webExtractMaxLength":"最大长度","webExtractMaxLengthDesc":"提取文字最大长度(可选)。","cardDelegateTitle":"子智能体与代码执行","cardDelegateSubtitle":"可选:delegate_task 与沙箱 execute_code。","delegateEnabled":"子任务委托 delegate_task","delegateEnabledDesc":"开启后,若运行环境支持,可使用子智能体。","delegateEnabledOn":"开启","executeCodeEnabled":"execute_code(沙箱)","executeCodeEnabledDesc":"开启后,若运行环境允许,可见沙箱代码工具。","executeCodeEnabledOn":"开启","cardSystemPromptTitle":"系统提示词","cardSystemPromptSubtitle":"可选覆盖默认系统上下文;与智能体级合并,条目级优先。","cardSkillsTitle":"技能白名单","cardSkillsSubtitle":"非空时仅向提示中暴露列表中的 <available_skills>。","systemPromptOverride":"系统提示覆盖","systemPromptOverrideDesc":"可选全量覆盖;与智能体级合并(条目优先)。留空可清除。","systemPromptPlaceholder":"","skillsAllowlist":"技能名白名单","skillsAllowlistDesc":"设置后仅向提示暴露已勾选技能。选「全部技能」表示不过滤;选「仅已选技能」从目录勾选(配置里已有但目录未列出的项仍会显示)。","skillsAllowlistModeAll":"全部技能","skillsAllowlistModeRestrict":"仅已选技能","skillsAllowlistNotInCatalog":"不在目录中","addSkillName":"添加技能名","removeListItem":"移除此行","cardToolsDisableTitle":"工具 — 全局禁用","cardToolsDisableSubtitle":"在 agents.defaults 中禁用内建工具名(如 shell、web_search)。","toolsDisableFieldLabel":"内建工具","toolsDisableHint":"勾选表示默认智能体可使用该工具;取消勾选则全局禁用。与「智能体」中按条目的禁用会合并生效。","toolsDisableLoadingBuiltin":"正在加载内建工具列表…","toolsDisableEmptyBuiltin":"网关未返回任何内建工具。","toolsDisableNotInBuiltin":"不在内建列表中","toolsDisableQuickActionsLabel":"快捷操作","toolsDisableQuickEnableAll":"全部允许","toolsDisableQuickDisableAll":"全部禁用","toolsDisableQuickReadOnlyWorkspace":"工作区只读","toolsDisableQuickHighRiskOff":"关闭高危","toolsDisableQuickNoOutbound":"禁止出站","addToolName":"添加工具名","cardParamsTitle":"Params(JSON)","cardParamsSubtitle":"给扩展的任意键值,必须为 JSON 对象。","paramsJson":"Params 对象","paramsJsonDesc":"如 {\\"myFlag\\": true}。清空可去掉配置文件中的 params。","paramsInvalidJson":"Params 必须是有效 JSON 对象。请检查花括号、引号等。"}}'),agentsSettings:JSON.parse('{"title":"智能体","subtitle":"管理 agents.list:工作区、默认路由与角色配置。","needToken":"请先保存网关访问令牌后再管理智能体。","loadError":"加载智能体列表失败","saveError":"请求失败","loading":"加载中…","tabOverview":"智能体列表","tabDefaults":"智能体默认配置","tabFiles":"角色配置","tabTools":"工具","tabSkills":"技能","tabChannels":"通道","tabCron":"定时","selectAgent":"智能体","selectAgentHint":"选择要编辑的智能体。角色配置文件(SOUL.md、IDENTITY.md 等)从该智能体目录 `agents/<id>/profile/` 读取。","agent":"智能体","defaultBadge":"默认","setDefault":"设为默认","editAgent":"运行配置","editAgentHint":"修改模型、工作区等配置,保存后将更新网关的 agents.list。","inheritance":{"title":"默认配置与本智能体","subtitle":"模型留空时使用全局默认;工作区路径与默认一致时视为继承。","editDefaultsLink":"编辑默认配置","modelLabel":"主模型","workspaceLabel":"工作区","badgeInherit":"继承默认","badgeOverride":"已覆盖","inheritsValue":"默认:{{value}}","unset":"未设置"},"displayName":"名称","agentDescription":"描述","agentDescriptionPlaceholder":"简短说明,会显示在智能体卡片和选择器中(可选)。","workspacePath":"Markdown 工作区","modelPrimary":"模型(主)","modelClear":"清除","save":"保存","discard":"放弃","removeFromConfig":"从配置移除","purgeDisk":"移除并删除数据","addAgent":"添加智能体","addAgentHint":"与 CLI agents add 相同:创建目录并写入角色配置模板。","newAgentLabel":"名称","newAgentIdOptional":"Agent ID(可选)","newAgentIdPlaceholder":"留空则根据显示名称生成","newAgentIdRules":"1–64 个字符:字母、数字、下划线、连字符;须以字母或数字开头。勿使用保留 id(如 main、con)。","newWorkspace":"工作区目录(必填)","newModelOptional":"模型(可选)","create":"创建智能体","addAgentAria":"添加智能体","createModalCancel":"取消","closeDialogAria":"关闭","filesHint":"智能体的身份配置文件(SOUL、IDENTITY 等)。编辑后自动保存,可用「预览」查看渲染效果。","filesLoading":"正在加载文件列表…","filesEmpty":"暂无文件。","pickFile":"请选择要编辑的文件。","saveFile":"保存文件","filesMarkdownEdit":"编辑","filesMarkdownPreview":"预览","filesAutoSaveHint":"编辑后自动保存。","filesSavingStatus":"保存中…","missing":"缺失","confirmDelete":"从配置中移除此智能体?相关路由绑定会被清除。","confirmDeletePurge":"移除此智能体并删除其工作区与 ~/.xopc/agents/<id> 数据?此操作不可恢复。","purgeConfirmLabel":"输入 agentId 以确认","purgeConfirmPlaceholder":"请输入 {{agentId}} 以确认","purgeConfirmHint":"此操作不可恢复。需完整输入 {{agentId}} 才能启用删除。","toolsTitle":"内置工具","toolsHint":"按智能体禁用工具(与 agents.defaults 合并)。已在默认配置中禁用的工具不能在此处单独启用。","toolsSave":"保存工具禁用","toolsClearEntry":"清除本智能体的额外禁用","toolsLockedByDefaults":"已在默认中禁用","toolsDisableGroups":{"unknown":"自定义(不在内置列表)","workspace":"工作区与搜索","execution":"执行","web":"网络","messaging":"通道与出站","memory":"记忆与会话","media":"视觉与生成","extensions":"扩展","mcp":"MCP(bundle)","misc":"其他内置"},"toolDescriptions":{"read_file":"读取工作区内的文本与小文件(路径限制在工作区沙箱内)。","write_file":"在工作区创建新文件或覆盖已有文件。","edit_file":"通过定位替换或补丁式编辑修改已有文件。","list_dir":"列出工作区某目录下的文件与子目录。","grep":"用正则搜索文件内容(类似 ripgrep)。","find":"按文件名或 glob 在工作区内查找文件。","shell":"在与工作区关联的环境中执行 shell 命令,权限高;只读或更保守的智能体可关闭。","web_search":"检索公开网页,获取模型训练截止之后的事实与资料。","web_fetch":"请求 URL 并读取页面文本供模型使用。","send_message":"在已连接的通道上发送出站聊天内容(如 Telegram、CLI、网关等)。","send_media":"通过通道发送图片或其他媒体附件。","memory_search":"搜索为本智能体建立的记忆与笔记索引。","memory_get":"按 ID 读取某条记忆或片段。","curated_memory":"读取或更新智能体主目录下的精选 Markdown 记忆。","session_search":"在已保存的会话记录与按会话摘要中搜索。","image":"分析或描述图片(视觉),可来自工作区或当前对话。","image_generate":"使用已配置的图像 / 文生图模型生成图片。","extensions":"启用扩展注册的工具;关闭则屏蔽所有扩展工具。","bundle-mcp":"从已配置的 MCP 服务器加载工具(全局 mcp.servers 与扩展 .mcp.json)。"},"skillsTitle":"技能白名单","skillsHint":"可选的 <available_skills> 白名单。「继承默认」仅使用 agents.defaults;「自定义」写入本智能体的 skills 数组。","skillsInherit":"继承默认","skillsCustomize":"自定义白名单","skillsSave":"保存技能","skillsCatalogLoading":"正在加载技能目录…","skillsEmptyCatalog":"目录中暂无技能。","skillsNoDescription":"SKILL.md 元数据中暂无描述。","skillsDefaultsLabel":"默认白名单:","skillsEffectiveLabel":"生效白名单:","skillsAllFromCatalog":"(全部目录技能)","channelsTitle":"路由绑定","channelsHint":"指向本智能体的 config.bindings。删除规则会更新网关上的完整 bindings 数组。","channelsLoading":"正在加载绑定…","channelsNone":"没有指向该智能体的绑定。","channelLabel":"通道","peerIdLabel":"对端 ID(可选)","channelsLoadingChannels":"正在加载通道列表…","channelsManualChannelHint":"网关未返回通道列表。请直接填写通道 id(如 telegram、webchat、gateway)。","channelsDisabledSuffix":"(已禁用)","channelsSessionLabel":"匹配范围","channelsRefreshSessions":"刷新","channelsRefreshSessionsHint":"重新加载该通道的近期会话","channelsLoadingSessions":"正在加载会话…","channelsPeerFromSessions":"从会话选择","channelsPeerAny":"该通道上全部入站","channelsNoSessionsHint":"此通道下暂无会话记录。先发一条消息,或在下方填写自定义对端 id。","channelsCustomPeerHint":"若填写,将覆盖上方会话选择;支持 * 通配,详见会话路由说明。","channelsCustomPeerPlaceholder":"例如 12345 或 *","addBinding":"添加绑定","removeBinding":"移除","cronTitle":"定时任务","cronHint":"隔离会话的定时任务可指定 agentId 作为会话键。未指定 agentId 的任务使用默认智能体,并在选中该智能体时显示。","cronLoading":"正在加载定时任务…","cronNone":"没有匹配的任务。","cronColSchedule":"计划","cronColMessage":"消息","cronColSession":"会话","cronColAgent":"智能体","cronAgentDefault":"默认智能体","cronAgentClear":"恢复默认","navIdentity":"智能体身份","navProfile":"关于你","navPersona":"人格","navTools":"工具","navSkills":"技能","navCoreFiles":"角色配置","navAdvanced":"高级","listSearchPlaceholder":"按名称、ID 或工作区搜索","listEmpty":"没有匹配的智能体。","listNoAgentsYet":"暂无智能体,请先创建一个。","listNewAgentCard":"新建智能体","listChatWithAgent":"聊天","defaultMainAgentName":"智能助手","defaultMainAgentDescription":"你的个人智能助手:解答疑问、协助日常事务,并随时与你交流。","editorNavAria":"智能体编辑器分区","skillsLibraryLink":"技能库","personaHint":"通过表单快速设置智能体身份与个性。需要直接编辑文本时请使用「角色配置」。","personaSectionIdentity":"智能体身份","personaSectionIdentityHint":"你的智能体如何介绍自己","personaSectionUser":"关于你","personaSectionUserHint":"帮助你的智能体更好地了解你","personaSectionSoul":"个性与风格","personaSectionSoulHint":"定义你的智能体如何与你交流","personaName":"名字","personaNamePlaceholder":"例如:小助、星辰、晓彤…","personaCreature":"类型","personaCreaturePlaceholder":"自定义类型…","personaVibe":"风格","personaVibePlaceholder":"自定义风格…","personaEmoji":"签名表情","personaEmojiPlaceholder":"例如 🤖 ✨ 🧠","personaAvatar":"头像","personaAvatarPlaceholder":"URL 或工作区路径","avatarPickerTitle":"智能体头像","avatarOpenSettingsAria":"打开智能体头像设置","avatarRowHint":"选择风格或上传自定义图片。","avatarUploadCustom":"上传自定义图片","avatarStyleAdventurer":"冒险家","avatarStyleRobot":"机器人","avatarStyleLorelei":"洛蕾莱","avatarStyleThumbs":"Thumbs","avatarStyleFunEmoji":"趣味表情","avatarMore":"更多","avatarUploading":"上传中…","avatarUploadFailed":"上传失败,请换一张较小的 PNG、JPEG 或 WebP。","avatarInvalidImage":"请使用 PNG、JPEG 或 WebP 图片。","avatarTooLarge":"图片大小不能超过 512 KB。","personaCallName":"怎么称呼你","personaCallNamePlaceholder":"例如:小明","personaPronouns":"称谓","personaPronounsPlaceholder":"例如:先生、女士、同学","personaTimezone":"时区","personaTimezoneDetect":"自动检测","personaTimezoneCustom":"自定义时区…","personaNotes":"备注","personaNotesPlaceholder":"其他你希望智能体了解的信息…","personaSoulTemplate":"个性模板","personaSoulCustomEdit":"编辑个性描述 (Markdown)","personaSoulPreview":"预览","personaSoulEdit":"编辑","personaMemoryNote":"你在对话中分享的偏好(如喜欢的食物、习惯等)会被智能体自动记住,无需在这里添加。","personaSaving":"保存中…","personaSaved":"已保存","footerSaveNotApplicable":"本页内容自动保存,无需手动操作。底部「保存」仅用于智能体身份、工具、技能与角色配置。","presetSetupBadge":"快速设置","presetSetupTitle":"创建预置 Agent 开始使用","presetSetupSubtitle":"选择要创建的 Agent,每个都带有定制化的性格和独立工作空间,创建后可随时修改。","presetSkip":"跳过","presetCreateSelected":"创建 {{count}} 个 Agent","presetCreating":"正在创建…","presetCreatingProgress":"正在创建第 {{current}} 个 / 共 {{total}} 个…","presetSetupComplete":"Agent 创建成功!","presetCreateFailed":"创建 {{name}} 失败:{{message}}"}'),goalsSettings:{title:`目标评判(/goal)`,hint:`持久化目标任务与评判模型评分的默认设置。`,save:`保存`,discard:`放弃`,saving:`保存中…`,saveError:`保存目标设置失败`,maxTurns:`单次运行最大轮数`,judgeModelRef:`评判模型`,judgeModelRefPlaceholder:`使用 Agent 默认模型(可选)`,judgeModelRefHint:`可选。留空时,目标运行将使用 Agent 配置的默认模型。`,judgeModelRefUseDefault:`使用 Agent 默认模型`,checklistMode:`清单模式`,parseFailures:`最大连续解析失败次数`,judgeTimeoutSec:`评判超时(秒)`,checklistHistoryChars:`清单历史字符数`,checklistHistoryCharsHint:`清单模式下发送给评判模型的 transcript 历史最大字符数。`}},ze={appsPage:{title:`应用`,subtitle:`扩展市场、内置扩展;用户扩展由 CLI 或商店安装到 ~/.xopc/extensions。与技能页类似,可用 ?tab=marketplace | builtin | user。`,tabMarketplace:`扩展市场`,tabBuiltin:`内置`,tabUser:`用户安装`,appsNavAria:`应用分区`,emptyBuiltin:`网关未发现任何内置扩展(可检查网关日志与 dist/extensions 下的清单)。`,emptyUser:`未发现用户安装的扩展。请通过扩展市场或 CLI 安装到 ~/.xopc/extensions。`,searchPlaceholder:`搜索应用`,noSearchResults:`没有符合筛选的应用。`,statusEnabled:`已启用`,cardNoDescription:`清单中无描述。`,badgeKindUi:`界面`,badgeKindBackend:`后端`,badgeBundled:`内置`,cardTooltipHasUi:`声明了网关控制台界面(页面或设置)。`,cardTooltipNoUi:`无网关界面;仍可提供工具、钩子或频道等能力。`,badgeSourceGlobal:`全局`,badgeSourceWorkspace:`工作区`,badgeSourceOther:`其他`,detailTitle:`应用详情`,detailBack:`返回`,detailClose:`关闭`,detailProviderPrefix:`来源:`,providerBundled:`内置(随 xopc 分发)`,providerGlobal:`全局安装(~/.xopc/extensions)`,providerWorkspace:`工作区(.extensions)`,providerOther:`其他`,detailSectionFeatures:`应用能力`,detailNoDescription:`该扩展未提供描述。`,restartNote:`部分扩展变更需要重启网关后才会完整生效。`,cliManageHint:`非内置副本需通过 CLI 或文件系统安装、升级与卸载。`,builtinConfigHint:`频道与图片密钥请在「设置 → 频道」「设置 → 图片」中管理。`,builtinRuntimeToggle:`网关运行时`,builtinToggleEnable:`启用`,builtinToggleDisable:`停用`,builtinToggleBusy:`保存中…`,builtinToggleFailed:`无法更新内置扩展。`,builtinToggleRestartHint:`请重启网关后扩展代码才会完整加载或卸载。`,backendOnlyHint:`该扩展无网关控制台界面;启用后工具与钩子仍会运行。`,badgePages:`{{count}} 个页面`,badgeSettings:`{{count}} 个设置`,badgeWidgets:`{{count}} 个聊天挂件`,badgeSidebar:`{{count}} 个侧栏`,open:`打开`,openSettings:`设置`,runStateLive:`运行中`,runStatePendingOn:`配置已启用`,runStatePendingOff:`配置已停用`,runStateOff:`已关闭`,marketplaceSearchPlaceholder:`搜索扩展…`,marketplaceEmpty:`xopc-store 暂无扩展。`,marketplaceLoadFailed:`扩展市场加载失败。`,marketplaceDetailTitle:`扩展详情`,marketplaceDetailLoadFailed:`无法加载包详情。`,marketplaceDetailReadmeHeading:`说明`,marketplaceNoReadme:`该包未提供 readme。`,marketplaceAuthor:`作者`,marketplaceVersion:`版本`,marketplaceDownloads:`下载量`,marketplaceInstall:`安装`,marketplaceReinstall:`重新安装`,marketplaceInstalled:`已安装`,marketplaceUninstall:`卸载`,marketplaceUninstallConfirm:`从磁盘删除该扩展并从配置中移除启用项?若列表未更新请重启网关。`,marketplaceReinstallConfirm:`用商店版本覆盖当前已安装的扩展?`,marketplaceInstallFailed:`安装失败。`,marketplaceUninstallFailed:`卸载失败。`,marketplaceRestartHint:`若涉及频道插件或卸载残留,请重启网关以完全生效。`,marketplaceBuiltin:`内置`,marketplaceBuiltinManageHint:`该扩展已随 xopc 内置分发,无需从商店安装。请在「内置」页打开界面或调整启用状态。`,marketplaceBuiltinGoBuiltin:`前往「内置」`},extensionUi:{permissionTitle:`是否允许「{{name}}」?`,permissionSubtitle:`在扩展界面打开期间,它可能使用以下能力。`,permissionsNone:`清单中未声明额外权限。`,allow:`允许`,deny:`暂不`,deniedHint:`在你批准之前,此浏览器将不显示该扩展的界面。`,reviewPermissions:`查看权限`,loadFailed:`扩展面板加载失败。`,loadFailedConnectionHint:`若内嵌区域提示无法连接 localhost,请先启动 xopc 网关;若用 Vite 单独跑 web/,请确认 web/vite.config.ts 里代理的网关端口与正在运行的网关一致。`,retryLoad:`重新加载`},extensionDebug:{nav:`扩展调试`,title:`扩展调试`,subtitle:`查看网关发现的扩展、声明的权限,以及本机浏览器中对界面授权的存储。`,grantsHeading:`界面授权存储`,grantsHint:"localStorage 键 `xopc.extensionUiGrants.v1` — 已同意的权限列表指纹(按扩展)。",refresh:`刷新`,listHeading:`网关返回的扩展`,colId:`标识`,colName:`名称`,colPermissions:`清单权限`,futureHeading:`后续计划`,futureBody:`后续将支持 postMessage 捕获、按扩展查看存储,以及更细的权限调试。`}},Be={channelsSettings:{needToken:`请先保存网关访问令牌后再编辑消息通道设置。`,subtitle:`连接 Telegram、微信、飞书等消息通道。保存后写入本地网关配置。`,docsLink:`消息通道文档`,refresh:`刷新`,loadError:`加载消息通道设置失败`,loading:`加载中…`,save:`保存`,discard:`放弃`,saving:`保存中…`,saved:`已保存`,saveError:`保存失败`,retry:`重试`,unsavedHint:`有未保存的更改。`,hubConfigureButton:`配置`,hubConnectedBadge:`已连接`,hubStatusRunning:`运行中`,hubStatusOffline:`未连接`,hubStatusDisabled:`已停用`,hubStatusNotConfigured:`未配置`,hubManageButton:`管理通道`,hubSetupButton:`开始配置`,hubFixButton:`检查配置`,hubPairingButton:`处理配对`,hubSummaryDm:`私聊:{{policy}}`,hubSummaryStream:`流式:{{mode}}`,hubSummaryConnection:`连接:{{mode}}`,hubSummaryAccountCount:`{{count}} 个账号`,hubConnectionWebsocket:`WebSocket`,hubConnectionWebhook:`Webhook`,hubViewDocs:`查看文档`,hubExtensionSubtitle:`网关注册的扩展消息通道。`,hubExtensionConfiguredHint:`网关配置中已有该通道配置`,hubExtensionManageHint:`该通道由扩展提供。请在扩展设置或网关配置文件中调整。`,hubExtensionStatusLabel:`状态`,hubExtensionEnabledLabel:`配置已启用`,hubExtensionConnectedLabel:`运行时已连接`,hubExtensionYes:`是`,hubExtensionNo:`否`,enableChannelAria:`启用或停用该通道`,modalCancel:`取消`,telegramTitle:`Telegram`,telegramSubtitle:`配置 Bot Token、访问策略和多账号设置。`,weixinTitle:`微信`,weixinSubtitle:`用微信扫码登录(网页或命令行)后在此启用。凭据保存在运行网关的本机。`,feishuTitle:`飞书 / Lark`,feishuSubtitle:`配置飞书应用凭据、访问策略和多账号设置。`,enableTelegramAria:`启用 Telegram 消息通道`,enableWeixinAria:`启用微信消息通道`,enableFeishuAria:`启用飞书消息通道`,telegramToken:`Bot Token`,telegramTokenDesc:`来自 BotFather,保存在网关配置中。`,feishuAppId:`App ID`,feishuAppIdDesc:`在飞书开发者后台获取(cli_xxx),保存在网关配置中。`,feishuAppSecret:`App Secret`,feishuAppSecretDesc:`在飞书开发者后台获取,保存在网关配置中。`,feishuDomain:`域名`,connectionMode:`连接模式`,connectionModeDesc:`websocket:Socket Mode。webhook:本地 HTTP 接收事件。`,renderMode:`渲染模式`,enableStreaming:`启用流式输出`,requireMention:`群聊中需要 @ 才响应`,reactionNotifications:`表情反应通知`,allowFromDm:`允许私聊(用户 ID)`,allowFromDmDesc:`配置文件中的静态白名单,多个用户 ID 用逗号分隔。通过配对允许的用户会显示在下方列表。`,pairingTitle:`私聊配对`,pairingSubtitle:`私聊策略为「配对」时,新用户向 bot 发消息会收到配对码,在此审批即可,无需命令行。`,pairingSetupHint:`在 Telegram 向 bot 发送任意消息,然后在下方输入 8 位配对码。`,pairingPendingTitle:`待审批`,pairingPendingEmpty:`暂无待审批请求。向 bot 发消息即可发起配对。`,pairingCodePlaceholder:`配对码`,pairingApprove:`批准`,pairingApproving:`批准中…`,pairingApproved:`已批准用户 {{id}}。`,pairingInvalid:`配对码无效或已过期。`,pairingLoadError:`无法加载配对状态。`,pairingRefresh:`刷新`,pairingExpiresHint:`{{time}} 过期`,pairingCodeHint:`配对码后四位 {{suffix}}`,pairedTitle:`已允许的用户`,pairedFromConfig:`配置白名单`,pairedFromCredentials:`已配对`,pairedEmpty:`无`,pairingAccountLabel:`Bot 账号`,pairingAccountNotPairing:`账号「{{account}}」未使用配对私聊策略。请选择其他账号,或在高级 JSON 中修改 dmPolicy。`,pairingRevokeAria:`撤销 {{id}} 的配对`,pairingRevoked:`已撤销 {{id}} 的配对。`,pairingRevokeError:`撤销配对失败。`,hubPairingPendingBadge:`{{count}} 待审批`,telegramSetupStepToken:`1. 保存 Bot Token 并启用 Telegram`,telegramSetupStepPairing:`2. 向 bot 发消息,然后在下方批准配对码`,pairingQuickApprove:`快速批准`,pairingQuickApproveHint:`快速批准无需输入配对码。请仅在确认该用户 ID 确实已向 bot 发送消息时使用。`,pairingDismiss:`忽略`,pairingDismissing:`忽略中…`,pairingDismissed:`已忽略 {{id}} 的待审批请求。`,pairingDismissError:`无法忽略该待审批请求。`,pairingStaleItem:`即将过期`,advancedShow:`高级选项`,advancedHide:`收起高级选项`,apiRoot:`API 根地址`,proxy:`代理`,dmPolicy:`私聊策略`,groupPolicy:`群组策略`,replyToMode:`回复引用模式`,streamMode:`流式模式`,allowFromGroups:`允许群组(ID)`,allowFromGroupsDesc:`逗号分隔的群 chat_id(群策略为白名单时生效)。`,historyLimit:`历史条数上限`,textChunkLimit:`文本分块上限`,telegramDebug:`调试模式`,multiAccountJson:`多账号(JSON)`,multiAccountJsonDesc:`可选。每账号可配置 botToken 或 tokenFile、策略与群组。留空 {} 则仅使用上方单一 Token。`,weixinQuickStartTitle:`最简步骤`,weixinStepLogin:`在本页使用下方「微信扫码登录」,命令行方式请见消息通道文档。`,weixinStepEnable:`下方打开「启用微信」并保存。`,weixinStepPairing:`扫码登录后即可正常收发;仅在需要限制谁可私聊时,将私聊策略改为白名单并配置允许来源。`,weixinAdvancedHint:`可选:白名单、路由标签、流式输出和多账号 JSON。仅在需要时展开。`,weixinAllowFrom:`允许来源`,weixinAllowFromDesc:`私聊策略为白名单时使用,逗号分隔的 wxid / openid。默认配对在扫码后即可与任意联系人私聊。`,weixinRouteTag:`路由标签`,weixinRouteTagDesc:`可选路由标签,可为数字或字符串。`,routeTagPlaceholder:`例如标签名或数字`,weixinDebug:`调试模式`,weixinDebugDesc:`为微信消息通道输出更详细的日志。`,weixinAccountsJson:`账号(JSON)`,weixinAccountsJsonDesc:`分账号名称、CDN 地址、路由标签与策略。`,weixinQrLoginTitle:`网页扫码登录`,weixinQrLoginDesc:`在网关上发起登录,使用微信扫码;成功后本页会自动刷新配置。`,weixinQrLoginButton:`微信扫码登录`,weixinQrLoginBusy:`正在启动…`,weixinQrLoginScanned:`已扫码,请在微信中确认`,weixinQrLoginSuccess:`微信已连接。`,weixinQrLoginCancel:`关闭二维码`,weixinQrImageError:`无法在页面内生成二维码,可在新标签页打开链接完成扫码,或点击「重新生成」重试。`,weixinQrOpenLink:`新标签页打开`,weixinQrEncoding:`正在生成二维码…`,weixinQrModalTitle:`扫码登录`,weixinQrModalSubtitle:`请使用微信扫描下方二维码完成连接`,weixinQrRegenerate:`重新生成`,weixinQrModalCloseAria:`关闭`,feishuQrModalTitle:`扫码创建应用`,feishuQrModalSubtitle:`默认使用国内(飞书)。可在二维码下方切换为国际(Lark)。展开高级选项可手动填写凭证与策略。`,feishuQrCloseAria:`关闭`,feishuRegionSwitchAria:`注册区域`,feishuRegionChina:`国内(飞书)`,feishuRegionInternational:`国际(Lark)`,feishuAdvancedHint:`可选:填写开发者后台的 App ID / Secret、连接模式、Webhook、工具、路由与多账号 JSON。保存后写入网关配置。`,feishuQrStarting:`启动中…`,feishuQrScanHint:`请使用飞书/Lark 扫描此二维码。`,feishuQrEncoding:`正在生成二维码…`,feishuQrImageError:`无法生成二维码图片。`,feishuQrOpenLink:`在浏览器中打开`,feishuQrRegenerate:`重新生成二维码`,feishuQrSetupSuccess:`飞书应用创建并配置完成。`,agentRoutingTitle:`智能体路由`,agentRoutingHint:"在配置 `bindings` 中为每个消息通道账号指定智能体;入站消息会使用对应智能体的会话键。",agentRoutingAccountLabel:`账号`,agentRoutingAgentLabel:`智能体`,jsonObjectAccounts:`账号必须为 JSON 对象`,jsonInvalid:`JSON 无效`,copy:`复制`,copied:`已复制`,show:`显示`,hide:`隐藏`,webhookTitle:`Webhook 配置`,verificationToken:`Verification Token`,verificationTokenDesc:`在飞书事件订阅中获取(webhook 模式)。`,encryptKey:`Encrypt Key`,encryptKeyDesc:`在飞书事件订阅中获取(webhook 模式)。`,webhookHost:`Webhook Host`,webhookPort:`Webhook Port`,webhookPath:`Webhook Path`,webhookPathDesc:`飞书事件订阅里配置的 Request URL 路径。`,feishuToolsTitle:`飞书工具`,feishuToolsDesc:`按需开启。每个工具可能需要额外的应用权限(scopes)。`,feishuToolDoc:`文档(feishu_doc)`,feishuToolWiki:`知识库(feishu_wiki)`,feishuToolDrive:`云盘(feishu_drive)`,feishuToolPerm:`权限管理(feishu_perm)`,feishuToolBitable:`多维表格(feishu_bitable_*)`,feishuToolScopes:`权限诊断(feishu_app_scopes)`,feishuActionsTitle:`飞书动作`,feishuActionReactions:`启用表情反应动作`,policy:{dm:{pairing:`配对`,allowlist:`白名单`,open:`开放`,disabled:`关闭`},group:{open:`开放`,disabled:`关闭`,allowlist:`白名单`},reply:{off:`关闭`,first:`首条`,all:`全部`},stream:{off:`关闭`,partial:`部分`,block:`阻塞`}}},voiceSettings:{needToken:`请先保存网关访问令牌后再编辑语音设置。`,subtitle:`配置消息通道中的语音识别和语音合成。API Key 也可以通过环境变量提供。`,docsLink:`语音文档`,loadError:`加载语音设置失败`,loading:`加载中…`,save:`保存`,discard:`放弃`,saving:`保存中…`,saved:`已保存`,saveError:`保存失败`,retry:`重试`,unsavedHint:`有未保存的更改。`,apiKeyMaskedHelp:`已保存的密钥默认隐藏。点击眼睛图标可从配置文件读取(不含环境变量里的密钥)。`,apiKeyCopy:`复制`,apiKeyCopied:`已复制`,apiKeyShow:`显示`,apiKeyHide:`隐藏`,apiKeyNotInConfigFile:`配置文件中没有该服务商的密钥(请检查环境变量)。`,apiKeyRevealFailed:`无法从配置文件读取密钥。`,stt:{title:`语音转文字(STT)`,description:`使用阿里云 DashScope 或 OpenAI Whisper 将收到的语音转为文字。`,enable:`启用 STT`,enableDesc:`开启后,可将语音消息转写给智能体使用。`,provider:`STT 服务商`,alibaba:`阿里云 DashScope`,openai:`OpenAI`,apiKey:`API Key`,apiKeyDesc:`若环境变量已配置密钥,此处可留空。`,model:`模型`,fallback:`备用服务商`,fallbackDesc:`主服务商失败时尝试备用服务商。`},tts:{title:`文字转语音(TTS)`,description:`在启用时把助手回复合成为语音。`,enable:`启用 TTS`,enableDesc:`开启后,按下方触发模式执行 TTS。`,trigger:`触发`,triggerOff:`关闭`,triggerAlways:`始终`,triggerInbound:`仅入站语音`,triggerTagged:`标签([[tts]])`,triggerDescOff:`完全关闭 TTS。`,triggerDescAlways:`对助手消息尝试使用 TTS。`,triggerDescInbound:`仅当用户发送语音时以语音回复。`,triggerDescTagged:`仅在使用 [[tts]] 指令时。`,provider:`TTS 服务商`,providerOpenai:`OpenAI TTS`,providerEdge:`Microsoft Edge(免费)`,providerLocalCli:`本地 CLI(离线)`,voice:`音色`,edgeHint:`Microsoft Edge TTS — 无需 API Key。`,localCli:{command:`CLI 命令`,commandDesc:`Shell 模板;占位符:{{Text}}、{{OutputBase}}。`,commandPlaceholder:`mlx_audio.tts.generate --text "{{Text}}" --file_prefix {{OutputBase}}`,cwd:`工作目录`,cwdDesc:`可选;默认使用网关工作目录。`,outputFormat:`输出格式`,outputFormatDesc:`CLI 输出的文件扩展名(mp3、wav、opus 等)。`,timeoutMs:`超时(ms)`,timeoutMsDesc:`单次调用超时覆盖;留空则使用 TTS 默认值。`,hint:"由内置扩展 `tts-local-cli` 提供。请先启用该扩展并将二进制加入 PATH。"}},notes:{title:`说明`,duration:`长音频会自动分段;效果取决于服务商与模型。`,envVars:`环境变量:DASHSCOPE_API_KEY、OPENAI_API_KEY(未在表单填写时)。`}},gatewaySettings:{needToken:`请先保存网关访问令牌后再加载或修改网关选项。`,subtitle:`HTTP API 访问令牌与监听地址。配置写入网关配置文件。`,tabsAriaLabel:`网关设置分类`,tabNetwork:`网络`,tabAccess:`访问控制`,tabUpdates:`更新`,tabSecurity:`安全`,tabAdvanced:`高级`,networkTabHint:`配置监听地址、端口与跨域来源。`,accessTabHint:`配置访问令牌、密码、受信任代理和认证失败限流。`,updatesTabHint:`配置更新通道、启动检查和自动更新策略。`,docsLink:`网关文档`,loadError:`加载网关设置失败`,loading:`加载中…`,save:`保存`,discard:`放弃`,saving:`保存中…`,saved:`已保存`,saveError:`保存失败`,retry:`重试`,unsavedHint:`有未保存的更改。`,tokenExpired:`会话访问令牌无效。请在客户端更新访问令牌,或修正配置文件中的访问令牌。`,updateToken:`更新客户端访问令牌`,changeToken:`打开访问令牌对话框`,accessToken:`网关访问令牌`,tokenPlaceholder:`保存在配置中的访问令牌(若使用环境变量可留空)`,tokenHelp:`用于 HTTP/WebSocket API 鉴权。也可通过环境变量 XOPC_GATEWAY_TOKEN 提供。`,copy:`复制`,copied:`已复制`,show:`显示`,hide:`隐藏`,listenHost:`监听地址`,bindMode:`绑定模式`,bindLoopback:`本机回环 (127.0.0.1)`,bindLan:`局域网 (0.0.0.0)`,bindAuto:`自动`,bindCustom:`自定义 IPv4`,bindTailnet:`Tailnet(Tailscale IP)`,customBindHost:`自定义绑定地址`,customBindHostPlaceholder:`192.168.1.10`,listenPort:`端口`,listenHint:`绑定模式决定网关监听哪些网络接口。自动模式:容器内绑定 0.0.0.0,本机绑定 127.0.0.1。仅在已配置 token 与 CORS 来源时使用 LAN。保存后需重启网关。`,restartHint:`监听地址、认证或 CORS 的更改需要重启网关后生效。`,restartGatewayButton:`重启网关`,restartGatewayConfirm:`重启网关会中断所有活跃连接,确定继续吗?`,restartGatewayFailed:`重启失败`,authMode:`认证模式`,authModeToken:`令牌`,authModePassword:`密码`,authModeTrustedProxy:`受信任代理`,authModeNoneLabel:`无`,authModeNone:`当前认证模式为 none — API 请求不进行鉴权。`,authModeTrustedProxyHint:`由反向代理完成登录并转发用户身份头。请在下方配置受信任代理 CIDR 与相关头。保存后需重启网关。`,authPassword:`网关密码`,authPasswordPlaceholder:`保存在配置中的密码(若使用环境变量可留空)`,authPasswordHelp:`认证模式为 password 时使用。也可通过环境变量 XOPC_GATEWAY_PASSWORD 提供。`,rateLimitTitle:`认证失败限流`,rateLimitHint:`限制同一客户端 IP 的重复认证失败次数。`,rateLimitEnabled:`启用限流`,rateLimitExemptLoopback:`豁免本机回环客户端 (127.0.0.1)`,rateLimitMaxAttempts:`最大尝试次数`,rateLimitWindowMinutes:`统计窗口(分钟)`,rateLimitBlockMinutes:`封禁时长(分钟)`,updateChannel:`更新通道`,channelStable:`稳定版`,channelBeta:`测试版`,channelDev:`开发版`,updateChannelHint:`测试版与开发版会较早收到构建;日常使用建议稳定版。`,updateAutoSection:`自动更新`,updateAutoSectionHint:`控制网关启动时的 npm/CLI 更新检查以及后台自动更新调度。`,updateCheckOnStart:`启动时检查更新`,updateCheckOnStartHint:`启用后,网关启动时会检查是否有新版本。`,updateAutoEnabled:`启用自动更新`,updateAutoEnabledHint:`启用后,符合条件的 stable/beta 构建可能在下方延迟后自动应用。`,updateAutoStableDelayHours:`Stable 延迟(小时)`,updateAutoStableDelayHoursHint:`stable 发布后至少等待多少小时才允许自动更新。`,updateAutoStableJitterHours:`Stable 抖动(小时)`,updateAutoStableJitterHoursHint:`额外随机等待上限,用于分散更新负载。`,updateAutoBetaCheckIntervalHours:`Beta 检查间隔(小时)`,updateAutoBetaCheckIntervalHoursHint:`使用 beta 通道时,轮询新构建的频率。`,corsOrigins:`CORS 允许的来源`,corsOriginsHint:`填写完整浏览器来源(协议 + 主机 + 端口),例如 http://localhost:5173。留空则使用网关内置的 localhost 默认值。保存后需重启网关生效。`,corsOriginsEmpty:`未配置自定义来源 — 网关将对此端口及 Vite 开发端口(3000)使用 localhost 默认值。`,corsOriginsPlaceholder:`输入来源后按 Enter 添加`,corsOriginsWildcardWarning:`通配符 "*" 允许任意网站从浏览器调用 API,请确认风险后再使用。`,securitySection:`网络安全`,securitySectionHint:`适用于局域网和反向代理部署的安全策略。保存后需要重启网关。`,securityStrict:`严格安全模式`,securityStrictHint:`启用后,非本机回环绑定必须显式配置认证失败限流。`,dangerouslyAllowHostHeaderOriginFallback:`允许 Host 头来源回退`,dangerouslyAllowHostHeaderOriginFallbackHint:`危险:未列入 CORS 时,将 HTTP Host 头视为允许的浏览器来源。建议优先配置 corsOrigins。`,dangerouslyAllowHostHeaderOriginFallbackWarning:`Host 头回退会削弱浏览器来源校验。仅在受信任且严格校验 Host 的反向代理后使用。`,trustedProxies:`受信任代理 CIDR`,trustedProxiesHint:`允许终止 trusted-proxy 鉴权的反向代理 IP 或 CIDR(如 127.0.0.1/32、10.0.0.0/8)。网络绑定下必填。`,trustedProxiesEmpty:`未配置受信任代理。`,trustedProxiesPlaceholder:`输入 CIDR 或 IP 后按 Enter`,allowRealIpFallback:`允许 X-Real-IP 回退`,allowRealIpFallbackHint:`X-Forwarded-For 解析失败时回退到 X-Real-IP。默认关闭(fail-closed)。`,trustedProxyUserHeader:`用户身份头`,trustedProxyUserHeaderPlaceholder:`X-Forwarded-User`,trustedProxyUserHeaderHint:`反向代理设置的 HTTP 头,携带已认证用户身份。`,trustedProxyRequiredHeaders:`必需的代理头`,trustedProxyRequiredHeadersHint:`每个请求必须携带的额外头(如 X-Proxy-Auth)。`,trustedProxyAllowUsers:`允许的用户`,trustedProxyAllowUsersHint:`非空时仅接受列表中的用户身份。留空则接受任意非空用户头值。`,trustedProxyAllowLoopback:`允许本机回环代理来源`,trustedProxyAllowLoopbackHint:`TCP 连接来自 127.0.0.1 时仍接受 trusted-proxy 鉴权(同机反向代理)。`,validationErrorNetworkAuth:`网络可访问的网关必须启用鉴权。`,validationErrorTrustedProxies:`网络绑定下的 trusted-proxy 鉴权至少需要一个受信任代理 CIDR。`,validationErrorUserHeader:`trusted-proxy 鉴权必须配置用户身份头名称。`,validationErrorCors:`网络可访问的网关必须配置 CORS 来源或启用 Host 头回退。`,validationErrorCorsWildcard:`网络绑定下不允许 CORS 通配符。`,validationErrorCustomBind:`自定义绑定模式必须填写绑定地址。`,securityAuditTitle:`安全审计`,securityAuditSubtitle:`对当前已保存的网关配置进行实时检查(等同 xopc doctor --security)。`,securityAuditSavedConfigHint:`反映磁盘上的配置文件。保存表单更改并重启网关后结果才会更新。`,securityAuditRefresh:`刷新`,securityAuditLoading:`正在运行安全审计…`,securityAuditLoadError:`安全审计失败`,securityAuditStatusPass:`无严重问题`,securityAuditStatusWarn:`存在建议项`,securityAuditStatusFail:`存在严重问题`,securityAuditStatusSkip:`审计已跳过`,securityAuditNoFindings:`无结构化发现项;配置通过网关安全守卫检查。`,securityAuditHintsTitle:`补充说明`,securityAuditRemediation:`修复:`,advancedSection:`高级`,advancedSectionHint:`运行时限制与频道启动顺序。保存后需重启网关生效。`,maxSseConnections:`最大 SSE 连接数`,maxSseConnectionsHint:"并发 Server-Sent Events 客户端上限(如 `GET /api/events`)。默认 100。",channelConnectDeferMode:`频道连接延后`,channelConnectDeferModeAuto:`自动(按插件默认)`,channelConnectDeferModeOff:`关闭(监听前先启动全部频道)`,channelConnectDeferModeExplicit:`显式列表`,channelConnectDeferModeHint:"控制 outbound 较重的频道何时调用 `start()`。自动模式下会延后声明了 opt-in 的插件(如 Telegram、Weixin、飞书)。",channelConnectDeferIds:`延后启动的频道 id`,channelConnectDeferIdsHint:`模式为「显式列表」时使用。这些插件 id 在 HTTP 监听绑定后再 start(最多 24 个)。留空表示不延后任何频道。`,channelConnectDeferSkipIds:`跳过延后的频道 id`,channelConnectDeferSkipIdsHint:`在自动或显式解析后从延后集合中移除(最多 24 个)。例如:Telegram 仍在 phase 1 启动,其余延后。`,channelIdListPlaceholder:`输入频道 id 后按 Enter(如 telegram)`,channelIdListEmpty:`未配置 id。`},heartbeatSettings:{needToken:`请先保存网关访问令牌后再加载或修改心跳选项。`,subtitle:"定时唤醒智能体、可选投递到消息通道,以及默认智能体 `profile/` 目录下的 HEARTBEAT.md。配置写入网关配置文件与 `agents/<id>/profile/`。",docsLink:`心跳机制文档`,loadError:`加载心跳设置失败`,loading:`加载中…`,saveConfig:`保存`,discard:`放弃`,savingConfig:`保存中…`,savedConfig:`配置已保存`,saveConfigError:`保存配置失败`,triggerNow:`立即触发`,triggering:`排队中…`,triggered:`已加入心跳队列`,triggerError:`触发心跳失败`,triggerHint:`与定时器相同的一次心跳(会受 HEARTBEAT.md、活跃时段与是否启用心跳影响)。`,saveDoc:`保存`,savingDoc:`保存中…`,savedDoc:`文档已保存`,saveDocError:`保存 HEARTBEAT.md 失败`,retry:`重试`,unsavedConfig:`有未保存的配置更改。`,unsavedDoc:`HEARTBEAT.md 有未保存的更改。`,workspaceLabel:`工作区`,tabsAriaLabel:`心跳设置分类`,tabSchedule:`计划`,tabDelivery:`投递`,tabPrompt:`提示词`,tabDocument:`HEARTBEAT.md`,scheduleTabHint:`设置心跳是否启用、运行间隔和活跃时段。`,deliveryTabHint:`选择要投递的消息通道和会话;留空则只记录日志。`,promptTabHint:`调整心跳轮次的系统提示、静默阈值和会话隔离策略。`,documentTabHint:`维护每次心跳读取的任务与提醒内容。`,configSection:`心跳配置`,docSection:`HEARTBEAT.md`,docHint:`每次心跳时智能体会读取的任务与提醒。若留空或仅有注释,将跳过 LLM 调用以节省用量。`,enable:`启用心跳`,includeSystemPromptSection:`在聊天 system prompt 中包含心跳指令`,includeSystemPromptSectionHint:`关闭时,心跳指令仅在定时心跳轮次中发送(可减少普通聊天 token 消耗)。`,interval:`间隔`,intervalHint:`最短 1 秒;保存到网关配置时为毫秒。`,intervalHintPreset:`快速选择,或在左侧输入秒数。`,intervalSecondsLabel:`秒`,intervalPresets:{custom:`自定义`,every30s:`每 30 秒`,every1min:`每 1 分钟`,every5min:`每 5 分钟`,every10min:`每 10 分钟`,every15min:`每 15 分钟`,every30min:`每 30 分钟`,every1h:`每 1 小时`,every2h:`每 2 小时`},deliveryTitle:`投递(可选)`,channelNone:`— 无 —`,customChannelSuffix:`自定义`,deliveryHint:`需同时填写消息通道与会话 ID 才会发送非静默回复;否则仅记录日志。`,prompt:`自定义系统提示(可选)`,promptPlaceholder:`覆盖默认心跳指令…`,promptHint:`留空则使用内置默认提示。`,ackMaxChars:`视为静默前的最大回复长度(ackMaxChars)`,ackMaxCharsHint:`留空则使用服务端默认值(300)。`,ackDefaultPlaceholder:`默认`,isolatedSession:`每次使用新的会话键`,isolatedSessionHint:`避免与主对话会话混淆上下文。`,activeHoursTitle:`活跃时段(可选)`,activeStart:`开始`,activeEnd:`结束`,activeTimezone:`时区(IANA)`,activeHoursHint:`仅在该时间窗口内运行心跳。清除则不限时段。`,addActiveHours:`添加活跃时段`,clearActiveHours:`清除活跃时段`},webSearchSettings:{title:`网络搜索`,subtitle:`为 web_search 工具配置地区与搜索提供方。未配置 API 时将使用内置 HTML 兜底。`,docsLink:`网关文档`,needToken:`请先保存网关访问令牌后再编辑网络搜索。`,loading:`加载中…`,loadError:`加载网络搜索设置失败`,save:`保存`,discard:`放弃`,saving:`保存中…`,saved:`已保存`,saveError:`保存失败`,unsavedHint:`有未保存的更改。`,sectionRegion:`地区`,sectionRegionHint:`在无可用 API 时,用于选择内置 HTML 兜底(国内优先必应,否则 DuckDuckGo)。`,sectionSearch:`搜索提供方`,sectionSearchHint:`按列表顺序依次尝试。密钥写在网关配置文件中。列表为空则仅使用 HTML 兜底。`,sectionBlocklist:`域名黑名单`,sectionBlocklistHint:`启用后,web_search 与 web_extract 会跳过主机名匹配下列域名的 URL(精确或后缀匹配)。`,blocklistEnabled:`启用域名黑名单`,blocklistEnabledDesc:`在抓取前拦截匹配主机,适用于隐私或合规场景。`,blocklistDomains:`屏蔽域名`,blocklistDomainsDesc:`每行一个域名(如 example.com)。所列域名的子域名也会被屏蔽。`,blocklistDomainsPlaceholder:`example.com
3
+ ads.example.net`,regionLabel:`兜底地区`,regionDesc:`自动根据系统时区判断。若使用代理或需固定策略,可手动覆盖。`,regionAuto:`自动(时区)`,regionCn:`中国(必应 HTML 兜底)`,regionGlobal:`全球(DuckDuckGo HTML 兜底)`,maxResultsLabel:`默认结果条数`,maxResultsDesc:`模型未指定 count 时使用(1–50)。`,providersTitle:`提供方(按顺序)`,addProvider:`添加提供方`,apiKeyLabel:`API 密钥`,apiKeyDesc:`部分场景可选。留空且显示为已掩码时保留原值。`,urlLabel:`实例地址`,urlDesc:`SearXNG 根地址(如 http://localhost:8080),无需末尾斜杠。`,keyPlaceholder:`密钥或环境变量名`,keyPlaceholderMasked:`••••••••(未修改)`,disabled:`跳过`,footerHint:`HTML 兜底依赖第三方页面,可能随站点改版变化。生产环境建议使用正式搜索 API(Brave、Tavily、必应或自建 SearXNG)。`,providerTypes:{brave:`Brave Search API`,tavily:`Tavily`,bing:`Bing Web Search API`,searxng:`SearXNG`}}},Ve={chat:JSON.parse(`{"typeMessage":"输入消息…","sendMessage":"发送","abort":"停止","needToken":"请先保存网关访问令牌后再对话。","loading":"加载对话中…","model":"模型","modelPlaceholder":"选择模型…","agent":"智能体","agentPlaceholder":"选择智能体…","agentSearchPlaceholder":"搜索智能体…","agentNoMatches":"没有匹配的智能体","thinkingLevel":"思考级别","newSession":"新对话","welcomeTitle":"今天想让 xopc 帮你做什么?","welcomeDescription":"输入问题、任务或文件处理需求,开始对话。","welcomeSpotlight":{"headline":"有任务,直接交给 xopc","tagline":"告诉我目标,我可以帮你拆解步骤、查找信息并执行操作。","categories":[{"id":"work","icon":"documents","title":"高效办公","description":"邮件、汇报、会议准备","scenarios":[{"prompt":"帮我写一封礼貌的邮件,婉拒这次会议邀请,同时建议另一个时间。"},{"prompt":"帮我写一份简短的周报:本周完成了什么、进行中的事项、遇到的阻塞,控制在 200 字以内。"},{"prompt":"我 30 分钟后要开会,帮我准备 5 个核心讨论要点和 3 个我应该追问的关于项目进度风险的问题。"}]},{"id":"research","icon":"globe","title":"搜索与学习","description":"热点资讯、概念解释、选择决策","scenarios":[{"prompt":"这周科技圈有什么大新闻?帮我总结最重要的 3 条,以及为什么值得关注。"},{"prompt":"用通俗的语言解释一下 RAG(检索增强生成)是怎么工作的,就像在给一个非技术人员讲解。"},{"prompt":"Notion 和 Obsidian 做个人笔记哪个更好?从功能、价格、离线使用三方面对比,然后给我建议。"}]},{"id":"content","icon":"content","title":"写作与创作","description":"文案、帖子、翻译润色","scenarios":[{"prompt":"帮我把这个想法写成一条朋友圈/小红书帖子:AI 工具正在让个人贡献者拥有小团队的战斗力。要有感染力,150 字以内。"},{"prompt":"帮我把下面这段话精简润色,让它更有力、适合放在产品官网首屏。"},{"prompt":"把这段中文翻译成英文,语气要地道自然,不要翻译腔。"}]},{"id":"data","icon":"folder","title":"数据与文件","description":"整理、分析、自动化","scenarios":[{"prompt":"看看我的下载文件夹,帮我按类型分类整理,告诉我哪些可以安全删除。"},{"prompt":"我有一份销售数据 CSV,帮我找出营收前 5 的产品,并看看有没有环比增长趋势。"},{"prompt":"帮我创建一个 Markdown 格式的每日计划模板:包含今日 3 件最重要的事、会议安排、备忘、以及每日复盘。"}]}]},"you":"你","assistant":"助手","tool":"工具","thinkingLabel":"思考中…","thoughts":"思考内容","thoughtsStreaming":"思考中…","thoughtsExpandHint":"展开查看模型思考过程","thinkingLevelLabel":"思考深度","thinkingLevels":{"off":"关闭","minimal":"最低","low":"低","medium":"中","high":"高","xhigh":"极高","adaptive":"自适应"},"toolInput":"输入","toolOutput":"输出","noOutput":"(无输出)","viewSteps_one":"查看 {{count}} 步","viewSteps_other":"查看 {{count}} 步","stepSearchedWeb":"搜索网页","stepReadFile":"读取文件","stepDetails":"详情","stepRunCommand":"运行命令","stepListDirectory":"查看文件夹内容","stepWriteFile":"保存文件","stepEditFile":"修改文件","stepOpenUrl":"打开链接","stepFetchUrl":"获取网页内容","stepUnknownTool":"执行:{{name}}","stepsClusterDone":{"search_one":"搜索了网页","search_other":"搜索了 {{count}} 次网页","readFile_one":"读了 1 个文件","readFile_other":"读了 {{count}} 个文件","editFile_one":"改了 1 个文件","editFile_other":"改了 {{count}} 个文件","writeFile_one":"保存了 1 个文件","writeFile_other":"保存了 {{count}} 个文件","runCommand_one":"运行了 1 个命令","runCommand_other":"运行了 {{count}} 个命令","listDir_one":"查看了 1 个文件夹","listDir_other":"查看了 {{count}} 个文件夹","openUrl_one":"打开了 1 个链接","openUrl_other":"打开了 {{count}} 个链接","fetchUrl_one":"抓取了 1 个网页","fetchUrl_other":"抓取了 {{count}} 个网页","other_one":"执行了 1 个工具","other_other":"执行了 {{count}} 个工具"},"stepsClusterIng":{"thinking":"正在思考…","search":"正在搜索网页…","readFile":"正在阅读文件…","editFile":"正在修改文件…","writeFile":"正在保存文件…","runCommand":"正在运行命令…","listDir":"正在查看文件夹…","openUrl":"正在打开链接…","fetchUrl":"正在抓取网页…","other":"正在处理…","mixed":"正在为你处理…"},"stepsClusterJoin":",","stepsClusterJoinFinal":"和","stepsClusterMoreSuffix":" 等","toolCard":{"copyPath":"复制路径","copyCommand":"复制命令","copied":"已复制","viewDiff":"查看改动","hideDiff":"收起改动","viewOutput":"查看输出","hideOutput":"收起输出","viewContent":"查看内容","hideContent":"收起内容","linesBadge":"{{count}} 行","linesPartial":"已加载 {{shown}} / {{total}} 行","diffStats":"+{{added}} −{{removed}}","sizeBadge":"{{size}}","exitCodeOk":"退出码 0","exitCodeNonZero":"退出码 {{code}}","exitCodeUnknown":"未结束","timedOut":"超时","truncatedBadge":"输出已截断","noOutput":"无输出","openInWorkspace":"在工作区中查看","rawDetails":"原始数据(开发者)"},"composerRunStatusSending":"发送中…","composerRunStatusDefault":"处理中…","composerRunningTool":"执行:{{name}}","composerStageThinking":"思考中…","composerStageSearching":"搜索中…","composerStageReading":"阅读中…","composerStageWriting":"撰写中…","composerStageExecuting":"执行中…","composerStageAnalyzing":"分析中…","attachFile":"添加附件","moreActions":"更多操作","fileReference":{"externalBadge":"外部文件","externalDescription":"这个文件不在当前工作区内,因此不能直接在工作区编辑器中编辑。","offWorkspaceBaseDescription":"此文件不在当前会话工作区内,无法在工作区编辑器中打开。","browserOffWorkspaceDescription":"此文件不在当前会话工作区内。请复制路径后在系统或桌面客户端中打开。","locationKind":{"agent-profile":"智能体配置","xopc-skills":"技能","xopc-config":"应用配置","xopc-agents":"智能体数据","xopc-sessions":"会话数据","host":"本机文件"},"openInSettings":"在设置中打开","browserExternalDescription":"当前运行在浏览器中,无法直接打开本地文件。你可以复制路径后在系统中打开。","missingDescription":"文件当前不可用,可能已被移动、删除,或属于另一个运行环境。","invalidDescription":"无法识别这个文件路径。","openExternal":"默认应用打开","revealInFolder":"打开所在目录","copyPath":"复制路径","importToWorkspace":"导入到工作区","importInProgress":"导入中…","importDialogTitle":"把这个文件复制到当前工作区?","importDialogSourceLabel":"源文件","importDialogDestinationLabel":"目标(工作区内相对路径)","importDialogConfirm":"导入","importDialogCancel":"取消","importSuccessToast":"已导入到 {{path}}","importErrors":{"IMPORT_NOT_ALLOWED":"该文件不支持导入到工作区。","SOURCE_NOT_FOUND":"源文件已不可用。","SOURCE_NOT_FILE":"只能导入普通文件。","SOURCE_TOO_LARGE":"文件超过导入大小上限。","INVALID_DESTINATION":"无效的目标路径。","DESTINATION_BLOCKED":"目标路径受保护,请改个名字。","DESTINATION_EXISTS":"目标位置已存在同名文件。","SAME_LOCATION":"源和目标是同一个文件。","FILE_REF_EXPIRED":"文件引用已过期,请重试。","FILE_REF_FORBIDDEN":"该文件引用不属于当前会话。","OVERWRITE_DISABLED":"覆盖已被配置禁用。","IMPORT_FAILED":"导入失败,请重试。","UNKNOWN":"导入失败。"}},"workingDirectory":{"selectWorkingDirectory":"选择工作目录","chooseFolder":"选择目录…","selectPath":"选择文件夹…","recentDirectories":"最近使用的目录","noRecent":"暂无最近使用的目录","notSet":"默认工作区","defaultWorkspace":"会话工作区","copyPath":"复制路径","selectionOnlyAtNewChat":"仅可在发送首条消息前选择工作区。","lockedTapTitle":"本会话无法更改工作区","lockedTapBody":"要选择项目文件夹,请先新建对话,在发送第一条消息前点击此处选择路径。也可在「设置 → 智能体」中配置默认工作空间。","clickToCopyFullPath":"点击复制完整路径","tooltipAgentWorkspace":"智能体工作目录","tooltipOpenProjectFiles":"点击在左侧打开或关闭项目文件。","copied":"已复制","openWorkspaceMenu":"工作区选项","folderPickerRequiresDesktop":"文件夹选择需要使用桌面版(Electron)。请使用桌面端 xopc,或通过其他方式配置路径。","applyErrorTitle":"无法设置工作目录","applyErrorClose":"关闭","pathModalTitle":"工作目录","pathModalDescription":"请输入网关所在机器上的绝对路径(作为本会话的工作区文件夹)。","pathInputPlaceholder":"/绝对路径/到/文件夹","pathModalConfirm":"确定","pathModalCancel":"取消","pickerHostHint":"网关所在主机上的目录:{{hostname}}","pickerLoading":"加载中…","pickerUp":"上级","pickerUseThisFolder":"使用此文件夹","pickerManualPath":"或手动输入绝对路径","pickerApplyManual":"应用路径","pickerListError":"无法读取该位置。","pickerEmptyFolder":"空文件夹","pickerDrives":"驱动器"},"maxAttachmentsReached":"每条消息最多 {{max}} 个文件,请先移除部分附件。","maxAttachmentsTruncated":"已忽略 {{dropped}} 个文件(每条最多 {{max}} 个)。","attachmentFileTooLarge":"文件「{{name}}」过大(单文件最大 {{maxSize}})。","attachmentLoadFailed":"加载附件失败:{{name}}","clipboardFileTypeUnsupported":"剪贴板中的文件类型不支持作为聊天附件","inputPlaceholder":"提问或描述任务 — @ 引用文件,/ 使用技能和命令","currentModel":"当前对话使用的模型","modelSearchPlaceholder":"按名称、服务商或 ID 搜索…","modelNoMatches":"没有匹配的模型","contextWindowHoverShort":"{{percent}}% 上下文","contextWindowHoverNoLimit":"约 {{used}} 上下文","contextWindowAriaSummary":"上下文用量约 {{used}} / {{limit}} tokens","contextWindowAriaSummaryNoLimit":"估计上下文用量约 {{used}} tokens","modelProviderSettingsLink":"配置服务商…","dropFiles":"将文件拖放到此处添加","voiceRecording":"录制语音","voiceRecordingStop":"停止录音","voiceInput":"语音输入","voiceRecordingStatus":"正在录音","voiceInputCancel":"取消录音","voiceInputConfirm":"转为文字","voiceTranscribing":"正在转写…","voiceTranscribeEmpty":"未识别到语音内容。","voiceTranscribeFailed":"转写失败,请重试。","voiceSttNotConfigured":"语音转文字未配置,请在设置 → 语音中启用 STT。","voiceMicDenied":"无法使用麦克风(权限被拒绝或设备不可用)。","inputPlaceholderSteering":"输入后续问题,按 Enter 加入队列;点击队列项可编辑。","inputPlaceholderSteeringEdit":"正在编辑队列中的后续问题 — Enter 保存,Esc 放弃修改","steeringInterruptSend":"停止当前回复并立即发送(⌘↵ 或 Ctrl+↵)","followUpQueueAria":"后续问题队列(本轮结束后按顺序发送)","followUpQueueHeading":"后续问题","followUpQueueClickToEdit":"在输入框中编辑","followUpQueueAttachmentOnly":"(附件)","followUpQueueEmptyPreview":"(空)","followUpQueueDrag":"拖动排序","followUpQueueMoveUp":"上移","followUpQueueMoveDown":"下移","followUpQueueSteerNow":"在工具间隙注入引导内容","followUpQueueRemove":"从队列移除","followUpQueueAttachmentsNote":"含附件的队列项无法使用 ✨ 引导注入,将按顺序作为整条消息发送。","followUpQueueMaxReached":"后续问题队列已满(最多 {{max}} 条)。请删除一条或等当前回复结束。","clarifyRegionAria":"助手澄清问题","clarifyResumeHint":"提交回答后,当前助手回复会从暂停处继续。","clarifyServerTimeout":"服务端约 {{minutes}} 分钟后会超时并收回此提问。","clarifyDefaultTimeoutNote":"若超时且提供了默认项,助手可能会采用该默认答案。","clarifySkipNote":"跳过会向助手发送空回答,以便对话继续。","clarifyChoicesGroupAria":"可选答案","clarifyCustomLabel":"或输入自定义回答","clarifyPlaceholder":"输入你的回答…","clarifySend":"发送","clarifyUseDefault":"使用默认","clarifyDefaultChoice":"默认:{{text}}","clarifySkip":"跳过","clarifyTimeRemaining":"剩余时间(约):{{time}}","browserSetupRequiredTitle":"需要先配置浏览器","browserSetupRequiredCta":"去配置浏览器","browserSetupRequiredDetailToggle":"查看诊断详情","browserSetupRequiredReasons":{"generic":"当前浏览器后端尚未就绪,请到 设置 → 浏览器 完成配置后再继续。","extension_not_installed":"尚未安装 xopc 浏览器扩展。请到 设置 → 浏览器 一键安装后再使用。","extension_bridge_offline":"扩展桥接服务未启动。请到 设置 → 浏览器 启动桥接并保持 Chrome 打开。","extension_not_connected":"桥接已启动,但 Chrome 还没连上。请打开 Chrome 并启用 xopc 扩展。","local_chromium_missing":"本地 Chromium 尚未安装。请到 设置 → 浏览器 一键安装后再使用 local 后端。","cloakbrowser_not_installed":"CloakBrowser 二进制尚未下载。请到 设置 → 浏览器 一键下载。","cdp_unreachable":"配置的 CDP 调试地址无法访问。请到 设置 → 浏览器 确认地址,并确保 Chrome 以 --remote-debugging-port 模式启动。","cloud_api_key_missing":"云端浏览器缺少 API Key。请到 设置 → 浏览器 填入凭证。"},"voicePlay":"播放语音","voicePause":"暂停","voiceLoading":"正在加载音频…","voiceAriaRegion":"语音播放","voiceAwaitingMeta":"正在读取时长","voiceMessage":"语音","loadOlder":"正在加载更早的消息…","scrollToBottom":"回到底部","attachmentPreviewClose":"关闭","attachmentPreviewDownload":"下载","attachmentPreviewRemove":"移除","attachmentPreviewLoading":"正在加载文件…","attachmentPreviewText":"文本","attachmentPreviewPdf":"PDF","attachmentPreviewDocument":"文档","attachmentPreviewPresentation":"演示文稿","attachmentPreviewSpreadsheet":"表格","attachmentPreviewNoText":"无可用文本","attachmentPreviewMissingData":"缺少文件数据","attachmentPreviewLoadError":"加载文件失败","attachmentPreviewMissingAuth":"缺少身份验证","attachmentPreviewFailedPdf":"无法加载 PDF","attachmentPreviewFailedDocx":"无法加载文档","attachmentPreviewFailedExcel":"无法加载表格","attachmentPreviewPdfRendering":"正在渲染 PDF…","attachmentPreviewPdfLoadMore":"向下滚动以加载更多页","attachmentPreviewExcelTruncated":"预览仅显示前 {rows} 行 × {cols} 列。请下载文件查看完整表格。","attachmentPreviewPptxTruncated":"为保护性能,文本预览已截断。请下载文件查看完整演示文稿。","attachmentPreviewPptxSlide":"第 {n} 页","attachmentPreviewPptxEmptySlide":"(本页无文本)","attachmentPreviewOpenElsewhereHint":"请下载文件后,使用本机上的其他应用打开。","attachmentPreviewOpenElsewhereTruncated":"此处仅显示部分内容。请下载完整文件后在本机其他应用中打开。","attachmentPreviewDownloadFull":"下载文件","attachmentPreviewImage":"预览图片","attachmentPreviewFullscreen":"全屏预览","attachmentPreviewExitFullscreen":"退出全屏","messageArtifactsHeading":"本消息输出","stepTimelineThinkingStreaming":"正在思考…","stepTimelineThinkingDone":"思考完成","stepTimelineToolSearchRunning":"搜索网络中…","stepTimelineToolSearchComplete":"搜索网络完成","stepTimelineToolSearchError":"搜索失败","stepTimelineToolGenericRunning":"{{name}}中…","stepTimelineToolGenericComplete":"{{name}}完成","stepTimelineToolGenericError":"{{name}}失败","searchSourcesHeading":"搜索来源 · {{count}}","executionDrawerTitle":"执行过程","executionDrawerClose":"关闭","executionDrawerEmpty":"暂无执行步骤。","executionProgressDone":"已完成思考","executionProgressRunning":"思考与工具执行中…","executionElapsedTitle":"本次执行已耗时","messageCopyPlainText":"复制纯文本","messageCopyMarkdown":"复制 Markdown 格式","codeBlockCopy":"复制","messageCopied":"已复制","userMessageCopy":"复制消息","userMessageRetry":"重试","userMessageEdit":"在输入框中编辑","userMessageRetryDisabledHint":"仅可重试最新一条自己的消息。","userMessageActionsWait":"请等待发送或回复结束后再操作。","userMessageDelete":"删除本轮对话","userMessageDeleteConfirm":"将同时删除你的消息和 AI 的回复,确定要删除吗?","userMessageDeleteConfirmTitle":"删除本轮对话","userMessageDeleteCancel":"取消","userMessageDeleteOk":"删除","commandPalette":{"noResults":"没有匹配的命令或技能","placeholder":"搜索技能与命令…","skillsSection":"技能","commandsSection":"命令","agentsSection":"智能体","currentBadge":"当前","queueBadge":"排队","queueFullBadge":"队列已满","queueFullTooltip":"跟进队列已满,请先处理","showGroupedMore":"显示另外 {{count}} 条"},"goal":{"heading":"持久目标 (/goal)","turns":"{{used}} / {{max}} 轮","checklistHeading":"验收清单","checklistProgress":"{{done}} / {{total}} 已完成","checklistEmpty":"首轮助手回复后会自动生成清单,也可手动添加。","addCriterionPlaceholder":"添加一条验收标准…","addCriterion":"添加","markDone":"完成","markBlocked":"无法完成","removeItem":"删除","resetChecklist":"重置清单","moreActions":"更多","moreHint":"重置轮次预算、清除目标或查看裁判说明","statusActive":"进行中","statusPaused":"已暂停","statusDone":"已完成","agentRunning":"智能体运行中…","pause":"暂停","resume":"继续","clear":"清除目标","restart":"重置预算","detailsToggle":"裁判详情","lastVerdict":"上次判定","verdictDone":"已完成","verdictContinue":"继续推进","verdictSkipped":"已跳过","verdictDecompose":"清单已就绪","lastReason":"说明","loadFailed":"无法加载目标状态。","collapseAria":"收起目标条","expandAria":"展开持久目标","pillTitle":"{{status}} · {{turns}} — 点击展开","elapsedLabel":"用时","runHistory":"运行记录","runHistoryEmpty":"暂无记录。目标为进行中时,每次助手回复后会追加一条。","runHistoryLoading":"加载中…","runHistoryLoadFailed":"无法加载运行记录。","runHistoryTurns":"{{used}} / {{max}} 轮","runHistoryContinue":"将继续","runHistoryStop":"不继续","verdictInactive":"未激活","missionHeading":"目标执行","phaseAgentRunning":"Agent 正在执行","phasePaused":"目标已暂停","phaseDone":"目标已完成","phaseJudged":"裁判已更新","lastJudgementTitle":"最后裁判","showDetails":"展开","hideDetails":"收起","pausedReason":"暂停原因","judgeModel":"裁判模型","parseFailures":"解析失败次数","judgeGenerated":"裁判生成","userAdded":"用户添加","evidenceLabel":"证据","pendingGroup":"待完成","completedGroup":"已完成","impossibleGroup":"不可行","latestRunTitle":"最近一次执行","nextStepContinue":"继续执行","nextStepStop":"停止执行"},"atMention":{"noResults":"无匹配项","placeholder":"搜索文件…","searchError":"搜索工作区失败","files":"文件","folders":"文件夹","recentFiles":"最近","recentBadge":"最近","shiftHint":"Shift+Enter 或 Shift+点击:继续添加 @ 引用。"}}`)},He={cron:JSON.parse('{"title":"定时任务","subtitle":"任务会按计划自动执行,也可随时手动触发。在任意对话里描述你想定期做的事,即可快速创建任务。","needToken":"请先保存网关访问令牌后再管理定时任务。","globals":{"title":"全局设置","hint":"所有任务的 Cron 调度器限制与默认值。部分更改可能需要重启网关。","loading":"加载中…","enabled":"启用 Cron 调度器","maxConcurrent":"最大并发任务数","timezone":"默认时区(IANA)","retentionDays":"运行历史保留(天)","metrics":"启用 Cron 指标","save":"保存","discard":"放弃","saving":"保存中…","saved":"已保存","saveError":"保存 Cron 设置失败"},"statsRegion":"概览","tabMyTasks":"我的定时任务","tabSystemTasks":"系统任务","tabRunHistory":"运行记录","systemTasksIntro":"由网关维护的内置计划:记忆整理(dreaming)相关 cron,以及独立计时的网关心跳。具体行为请在对应设置页调整。","systemHeartbeatTitle":"网关心跳","systemHeartbeatHint":"由网关进程内的定时器按间隔触发(不会出现在 cron 任务列表中)。存在 HEARTBEAT.md 时会一并参考。","systemHeartbeatSettingsLink":"心跳设置","systemHeartbeatStatus":"状态","systemHeartbeatInterval":"节奏","systemHeartbeatEvery":"约每 {{value}} 一次。","systemDreamingTitle":"记忆整理(dreaming)","systemDreamingHint":"三阶段后台任务,用于把短期信号写入长期记忆;计划表达式随智能体记忆配置由网关同步。","systemDreamingSettingsLink":"记忆与梦境设置","systemDreamingEmpty":"当前没有已注册的 dreaming 定时任务(可能已关闭 dreaming 或尚未完成同步)。","wakeBanner":"定时任务仅在设备保持唤醒时运行;系统或屏幕休眠时,执行可能会被跳过。","keepAwake":"保持屏幕常亮","wakeLockUnavailable":"当前浏览器或环境不支持屏幕唤醒锁。","sortCreatedDesc":"创建时间(新→旧)","sortCreatedAsc":"创建时间(旧→新)","historyRangeDay":"日","historyRangeWeek":"周","historyRangeMonth":"月","filterAllTasks":"全部任务","filterAllStatuses":"全部状态","emptyHistoryTitle":"暂无执行记录","emptyHistoryHint":"定时任务开始运行后,记录将显示在这里。","jobCardMenuAria":"任务操作","scheduleBadge":{"everyMinute":"每分钟","everyNMinutes":"每 {{n}} 分钟","everyNHours":"每 {{n}} 小时","hourly":"每小时","dailyAt":"每天 {{time}}","weekdaysAt":"工作日 {{time}}","weeklyOn":"{{day}} {{time}}","cronExpr":"{{expr}}"},"jobsHeading":"计划任务","addJob":"新建任务","editJob":"编辑任务","name":"名称 *","namePlaceholder":"我的定时任务","nameRequired":"请填写名称","schedule":"计划(cron 表达式)*","message":"消息 *","messagePlaceholder":"助手应该做什么?","messageEdit":"编辑","messagePreview":"预览","messageMarkdownHint":"支持 Markdown(标题、列表、代码块、链接等)。","create":"创建任务","runNow":"立即执行","delete":"删除","edit":"编辑","enabled":"已启用","disabled":"已禁用","running":"运行中","nextRun":"下次执行","status":"状态","runHistoryTitle":"运行记录","runHistoryHint":"已完成的执行会保存在本地(state/cron/runs)。点击刷新更新列表。","detailRunHistory":"最近执行","colStarted":"开始时间","colJob":"任务","colDuration":"耗时","colDetail":"结果","colChat":"会话","openChat":"打开","openChatTitle":"在聊天中打开此次执行(仅 AI 智能体隔离会话)","execStatusRunning":"运行中","execStatusSuccess":"成功","execStatusFailed":"失败","execStatusCancelled":"已跳过","noRunsYet":"该时间范围内暂无执行记录。","confirmDelete":"确定要删除此定时任务吗?","confirmRun":"立即执行此定时任务?","scheduleLabel":"计划","messageLabel":"消息","totalJobs":"任务总数","emptyStateCta":"创建第一个任务","channel":"消息通道","channelLocal":"本地(不发出)","deliveryTargetLocalChannel":"本地消息通道 — 内容仅保存在本机","recipient":"接收方 *","recipientPlaceholder":"Telegram:填写数字形式的会话 ID,或从下方最近会话中选择","refreshList":"刷新","refreshRecipientHint":"从最近会话重新加载列表","selectRecipient":"— 请选择 —","noRecentChatsOption":"暂无最近会话","deliveryTarget":"投递目标","scheduleHintPreset":"选择预设或输入自定义 cron 表达式","schedulePicker":{"scheduleTimeLabel":"计划时间","modeNoRepeat":"不重复","modeInterval":"间隔","intervalKindMinutes":"分钟","intervalKindHours":"小时","modeHourly":"每小时","modeDaily":"每天","modeWeekly":"每周","modeMonthly":"每月","modeCustom":"自定义表达式","minuteUnit":"分","minuteAtHour":"分钟","intervalMinutes":"间隔分钟数","intervalHours":"间隔小时数","hourUnit":"小时","dayOfMonth":"日期","customCronHint":"标准五段 cron:分 时 日 月 周","weekdays":["一","二","三","四","五","六","日"]},"mode":"模式","modeDirect":"直接发送消息到消息通道,不经过 AI 处理","modeAgent":"由 AI 智能体处理消息并生成回复后发送","modeDirectOption":"直接发送(发到消息通道)","modeAgentOption":"AI 智能体(先由模型处理再发送)","agentLocalOnly":"仅本地运行(保存对话,不发送到消息通道)","agentLocalOnlyHint":"在本机运行智能体。对话以 cron 类型会话保存到默认或所选智能体下(任务 id 包含在会话键中);不向 Telegram/CLI 投递。","deliveryLocalOnly":"仅本地 — 对话以 cron 会话保存到该智能体目录","agentProfile":"智能体","agentProfileHint":"仅在「AI 智能体」模式下生效。选默认则使用网关配置的默认智能体。","agentProfileDefault":"默认智能体","workingDirectoryLabel":"工作目录","workingDirectoryHint":"可选。填写网关所在机器上的绝对路径;不填则使用该智能体的默认工作空间。","workingDirectoryReset":"使用智能体默认","model":"模型","save":"保存","failedToLoadJobs":"加载任务失败","scheduleRequired":"计划表达式和消息为必填项","chatIdRequired":"会话 ID 为必填项","failedToCreateJob":"创建任务失败","failedToUpdateJob":"保存任务失败","failedToToggleJob":"切换任务状态失败","actionFailed":"操作失败","enterManuallyOrSelect":"手动输入或从最近聊天中选择","noRecentChats":"未找到最近会话。请手动填写会话 ID(例如 Telegram 为 123456789)","refresh":"刷新","close":"关闭","cancel":"取消","loading":"加载中…","schedulePresets":{"custom":"-- 自定义(在下方输入) --","everyMinute":"每分钟","every5Minutes":"每 5 分钟(默认)","every10Minutes":"每 10 分钟","every15Minutes":"每 15 分钟","every30Minutes":"每 30 分钟","everyHour":"每小时","every2Hours":"每 2 小时","every4Hours":"每 4 小时","every6Hours":"每 6 小时","every12Hours":"每 12 小时","everyDayMidnight":"每天午夜","everyDay9AM":"每天早上 9 点","everyDay9PM":"每天晚上 9 点"},"timeLabels":{"overdue":"已过期","lessThanMinute":"不到 1 分钟","minutes":"{{count}} 分钟","hours":"{{count}} 小时"},"lastActiveLabels":{"justNow":"刚刚","minutesAgo":"{{count}} 分钟前","hoursAgo":"{{count}} 小时前","daysAgo":"{{count}} 天前"},"templateFilterAll":"全部","fromTemplate":"从模版创建","templatesEmptyHint":"该分类下暂无模版。","templateCategories":{"daily":"每日","monitoring":"监控","reports":"报告","automation":"自动化"},"templates":{"morning_briefing":{"title":"早间简报","description":"天气/出行提示(无 API 则如实说明)、你关心领域要闻、今日优先三件事——在提示词里改主题列表。","prompt":"生成一份**早间简报**,几分钟内读完。\\n- **天气/出行**:若无真实预报接口,请说明限制;仅根据我写的地区/季节给**一条**穿衣或通勤提示,或跳过。\\n- **要闻**:我关心的领域(**请编辑**):**(例:本地、宏观、科技政策、球队等)**;有检索则概括约 24 小时内要点并标注来源类型;无检索则给出我应**依次打开哪些首页**。\\n- **今日优先 3 件**:尽量从工作区笔记/待办推断;否则请我在文末一次性补充。\\n- **不要编造链接、引语或具体气温数字**。"},"standup_prep":{"title":"站会准备","description":"根据近期 Git 与文件变动起草站会式更新,便于口头汇报。","prompt":"帮我准备**站会发言稿**:\\n- 若可访问 Git:概括**自上次站会或昨天以来**的提交主题(不要堆 hash),若有明显风险路径可点出。\\n- 若不可用:给出我本地应执行的**简短命令**以便下次自动生成。\\n- **文件/改动线索**:从工作区可见信息推断,不确定请标注「推断」。\\n- **阻塞**:最多 3 条,可写「暂无」。\\n- **今天打算做什么**:一句话。\\n- 控制在约 **90 秒**可念完。"},"end_of_day_wrap_up":{"title":"日终小结","description":"总结今日进展、未闭环与明日第一件事。","prompt":"做**工作日日终小结**:\\n- **已完成**:最多 5 条(推断请标注)。\\n- **未闭环/搁置**:最多 4 条,语气中性。\\n- **明日登录后第一件事**:仅一条,动作具体。\\n- 尽量引用工作区内任务/日志;若无则说明缺口。\\n- 不做价值评判。"},"inbox_triage":{"title":"收件箱式梳理","description":"优先列出紧急待跟进项;若工作区无邮件内容则给可执行的梳理流程。","prompt":"协助**收件箱/待处理**梳理(**不假设**能登录真实邮箱):\\n- 若工作区有导出邮件、`.eml`、或关于邮件的笔记:按**紧急跟进优先**列出条目及建议下一步。\\n- 若无材料:给出**五步梳理流程**(文件夹/标签、先处理谁、如何处理老邮件等),并请我在下列 **VIP 发件人或域名**(**请编辑**)基础上下次粘贴若干主题行。\\n- **不要声称已读取真实收件箱**。"},"competitor_watch":{"title":"竞品动态","description":"按你列出的竞品做新闻、产品更新与价格信号摘要;有检索才写细节。","prompt":"竞品或对标名单(**请编辑**):**(填写公司/产品名)**。\\n- 有网络检索:概括约**一周**内公开动态:新闻、产品/changelog、价格或套餐变化;区分**已核实**与**传闻**。\\n- 无检索:列出**应查看的官方入口**(官网、定价页、changelog)及建议核对顺序,**不要编造更新**。\\n- **禁止捏造报道引语、数字或链接**。"},"trending_topics_monitor":{"title":"热点话题追踪","description":"跟踪你列出的行业或社区讨论热度与要闻线索。","prompt":"我关注的行业/社区/话题(**请编辑**):**(例:金融科技、独立游戏、本城论坛、AI 工具)**。\\n- 有检索:用 **5~7 条**要点概括本周**讨论变热或异常活跃**的方向,并注明大致平台类型(新闻/论坛类/HN 类等),勿捏造具体帖子链接。\\n- 无检索:给出**检索词组合**与**建议浏览顺序**。\\n- 若有争议或易误传话题,用一行提示**核实风险**。"},"tech_radar_stack":{"title":"技术雷达","description":"关注你列出的技术栈近期的发版与官方安全通告入口,不臆造 CVE。","prompt":"技术栈清单(**请编辑**):**(例:Node LTS、Postgres、某云产品、Android SDK)**。\\n- 汇总约 **14 天**内值得注意的发版、弃用说明,信息来源限于**官方博客、changelog、注册表**。\\n- 安全相关只指向**官方安全公告渠道**;**严禁编造 CVE 编号**或虚假漏洞版本。\\n- 若可见锁文件可概括生态;信息不足则说明缺哪份文件。"},"dependency_check_audit":{"title":"依赖检查","description":"根据仓库生态建议审计命令与关注项,不假装已跑过扫描。","prompt":"从工作区识别包管理文件(`package.json`、`go.mod`、`pyproject.toml` 等)。\\n- 为每种生态给出**一条**文档中常见的审计/检查命令(若不存在则说明)。\\n- 用文字说明**应关注什么**(大版本、被撤回包、EOL 运行时等),**不要编造扫描结果**。\\n- **不要捏造 CVE**。"},"weekly_review":{"title":"周报式回顾","description":"一周提交主题、未闭环与下周三块重点。","prompt":"写一份**周末/周五周报式回顾**:\\n- **本周交付主题**(结合 git 与笔记,若 git 不可用则说明)。\\n- **仍挂心的事**(≤6 条)。\\n- **下周 3 个标题级重点**。\\n- **一条**「该停做或该委派」的建议(仅在过载迹象明显时)。\\n- 语气像给上级的短简报。"},"code_quality_report":{"title":"代码质量报告","description":"从脚本与 CI 配置推断如何跑 lint/类型检查,并说明如何阅读输出——不虚构错误数量。","prompt":"在工作区查找 **lint / 类型检查 / 格式化** 相关脚本(`package.json`、Makefile、CI 配置等)。\\n- 给出建议的**本地执行顺序**。\\n- 说明**如何扫一眼输出**(错误类别、易 flaky 测试、类型债热点),**不要编造错误条数**。\\n- 若项目无脚本,按识别出的语言给**最小**起步建议并注明局限。"},"git_activity_summary":{"title":"Git 活动摘要","description":"归纳近期提交、活跃分支与热点文件;此处不能跑 git 则只给命令。","prompt":"总结约 **最近 7 天** 的 Git 活动:提交**主题**、值得注意的**分支**、**热点文件**。\\n- 若当前环境不能执行 git:**不要虚构**,改为列出我本地可复制的命令以生成同样摘要。\\n- 避免罗列大量 hash,保持可扫读。"},"user_feedback_digest":{"title":"用户反馈摘要","description":"从工作区内的反馈笔记、工单导出等聚类主题与痛点;无材料则给收集模板。","prompt":"我存放反馈的位置或命名习惯(**请编辑**):**(例:`feedback/`、导出的 issues、问卷摘要)**。\\n- 从可读文本中聚类**重复主题**、**大致情绪**、**主要痛点**(≤5)。\\n- 注意**脱敏**:不展开无关个人信息。\\n- 若无内容:给出我下次应粘贴/保存的**简短结构模板**。"},"stale_todo_or_issue_sweep":{"title":"陈旧待办清扫","description":"扫描 TODO/FIXME 或简易 issue 列表,建议保留/关闭/拆分,不自动改文件。","prompt":"扫描工作区中的 **TODO/FIXME/HACK** 或 Markdown 里的简易任务表。\\n- 列出最多 **10 条**「可能陈旧」的项(根据模糊措辞或文件很少再改动等启发式),每条给**建议动作**:关闭、拆分、排期。\\n- **仅建议,不修改文件**。\\n- 若扫描不完整,说明原因。"},"release_notes_or_changelog_draft":{"title":"发版说明草稿","description":"结合版本号文件与近期提交起草 changelog 草案,需人工核对后发布。","prompt":"为**下一次**版本发布起草 **changelog / 发版说明** 草案:\\n- 读取 `CHANGELOG`、以及 `package.json` / `Cargo.toml` 等版本字段(若存在)。\\n- 从可见提交归纳**面向用户**的变更;无法确定上次标签则退化为「最近一周」。\\n- 不确定条目请标注「待核实」。\\n- 语气克制,避免营销夸张。"},"workspace_cleanup_suggestions":{"title":"工作区清理建议","description":"列出大体积构建产物、缓存、日志等供周末前审视,不自动删除。","prompt":"为**周末前清理**给建议:\\n- 尽量发现**构建产物、缓存、日志**等;用表格:路径 | 可能原因 | 风险 | 建议(仅审视/归档)。\\n- **禁止删除或移动**。\\n- 若无法读磁盘占用,说明限制并给通用模式。"},"smoke_or_ci_health_reminder":{"title":"冒烟 / CI 健康","description":"从 CI 与脚本提炼本周值得跑的检查及如何确认通过,不谎称 CI 已绿。","prompt":"根据 CI 配置与脚本,列出本周值得做的 **smoke / 健康检查**:每条含**命令**、**期望通过信号**、**建议频率**。\\n- 若无 CI 文件:按仓库类型给**最小手工冒烟**路径。\\n- **不要在没有证据时声称 CI 已通过**。"}}}')},Ue={logs:{title:`日志`,subtitle:`网关运行时的诊断与历史记录。`,needToken:`请先保存网关访问令牌后再查看日志。`,filters:`筛选`,level:`级别`,searchPlaceholder:`搜索消息或模块…`,module:`模块`,allModules:`全部模块`,timeRange:`时间范围`,from:`开始`,to:`结束`,clear:`清除`,refresh:`刷新`,autoRefresh:`自动刷新`,pause:`暂停`,liveHint:`每 5 秒自动刷新`,logFiles:`日志文件`,filesEmpty:`磁盘上暂无日志文件`,loadMore:`加载更多`,showingCount:`已加载 {{count}} 条`,moreAvailable:`可能还有更早的条目`,noLogs:`没有匹配的条目`,noLogsDescription:`请调整筛选或搜索,或稍后再试。`,loading:`加载中…`,loadError:`加载日志失败`,details:`日志详情`,close:`关闭`,time:`时间`,message:`消息`,metadata:`元数据`,statsRegion:`抽样(近期文件)`,statsHint:`数量为近期日志文件抽样统计,非全量。`,statsDetailTitle:`各级别数量`,logDir:`目录`,requestId:`请求 ID`,sessionId:`会话 ID`,presetAll:`全部`,presetErrors:`错误`,presetWarnPlus:`警告+`,presetInfoPlus:`信息+`,presetVerbose:`调试`,presetOther:`更多`,levelPresetAria:`按日志级别筛选`,refreshModeAria:`日志刷新方式`,refreshManual:`手动`,refreshLive:`实时`,filtersMore:`更多筛选`,filtersDialogTitle:`更多筛选`,filtersDialogDesc:`时间范围与自定义日志级别。`,filtersDone:`完成`,levelCustom:`自定义级别`,levelCustomHint:`点选以包含或排除;全部不选表示所有级别。`,copyMessage:`复制消息`,copyJson:`复制 JSON`,copied:`已复制`,levelNames:{trace:`跟踪`,debug:`调试`,info:`信息`,warn:`警告`,error:`错误`,fatal:`致命`}}},We={onboarding:{title:`欢迎使用 xopc`,subtitle:`只需 3 步,即可开始使用你的 AI 助手。`,step1Title:`选择 AI 服务商`,step1Subtitle:`选择你想要使用的 AI 服务。`,step2Title:`输入你的 API 密钥`,step2Subtitle:`密钥将保存在本地 xopc 配置文件中。`,step2Placeholder:`在此粘贴你的 API 密钥`,step2SecurityNote:`🔒 密钥不会离开你的设备。`,step3Title:`选择默认模型`,step3Subtitle:`你可以随时在设置中更改。`,back:`返回`,continue:`继续`,startChatting:`开始对话`,skipSetup:`跳过 — 稍后再设置`,setupComplete:`设置完成!在下方开始对话吧。`,stepOf:`第 {{current}} 步,共 {{total}} 步`,providerRecommended:`推荐`}},Ge={providersSettings:{subtitle:`管理各服务商的 API Key 和 OAuth 授权,保存后写入本地网关配置。`,intro:`可搜索或展开分组,再展开具体服务商,粘贴新密钥后点「保存」。支持 OAuth 时,在浏览器中完成授权。`,quickStartIntro:`选择一个服务商,在展开后粘贴 API Key 即可开始。`,docsLink:`模型与服务商文档`,modelsLink:`自定义服务商(models.json)`,rotateHint:`日常轮换密钥:展开对应服务商 → 粘贴新密钥 → 保存,一般无需重启。`,needToken:`请先保存网关访问令牌后再管理服务商密钥。`,loadError:`加载服务商列表失败`,save:`保存`,saving:`保存中…`,saved:`已保存`,noChangesSaved:`没有需要保存的新密钥。`,saveError:`保存失败`,empty:`暂无可用服务商。`,searchPlaceholder:`搜索 OpenAI、Claude、Gemini…`,getApiKey:`获取 API Key`,getApiKeyIntl:`获取 API Key(国际站)`,getApiKeyCn:`获取 API Key(国内)`,savedModelsAvailable:`个可用模型`,savedNoModels:`已配置,暂无模型列表`,envVarAlt:`或通过环境变量配置`,moreOptions:`更多选项`,unconfiguredOnly:`仅显示未配置`,noMatches:`没有符合筛选条件的服务商。`,clearFilters:`清除筛选`,discard:`放弃`,unsavedHint:`有未保存的更改。`,runtimeLabelPrefix:`当前生效密钥:`,sourceAgent:`智能体私有密钥`,sourceGateway:`网关配置(本页保存)`,sourceOauth:`OAuth 授权`,sourceEnv:`环境变量`,sourceModelsJson:`models.json`,sourceExtension:`扩展提供方`,sourceNone:`无`,testKey:`测试输入值`,testingKey:`测试中…`,testOkLiteral:`格式有效(明文或文本)。`,testOkEnv:`环境变量可解析。`,testOkCommand:`命令解析成功。`,testFailed:`检查未通过。`,revokeFailed:`撤销失败。`,expandRowDetails:`展开密钥与操作`,categories:{common:`常用服务商`,specialty:`专业 / 特色`,enterprise:`企业 / 云端`,oauth:`仅 OAuth`,extension:`扩展`},configuredCount:`已配置 {{count}} 个`,metaMasked:`已保存密钥,输入新 Key 可覆盖。`,metaWillSave:`保存后生效。`,metaNotConfigured:`未配置。`,placeholderKey:`API Key`,placeholderKeep:`留空则保留当前`,placeholderOverride:`输入新 Key 覆盖`,show:`显示`,hide:`隐藏`,copy:`复制`,copied:`已复制`,oauth:`OAuth 登录`,revoke:`撤销`,revokeConfirm:`撤销「{{name}}」的 OAuth 凭据?`,oauthStarting:`正在启动 OAuth…`,oauthProcessingCode:`正在处理授权…`,openAuthPage:`打开授权页`,cancelOAuth:`取消`,pasteRedirectUrl:`粘贴完整重定向 URL(含 code= 与 state=)`,submitCode:`提交`,envHint:`API Key 来自环境变量。在上方输入新 Key 可覆盖。`,maskedStoredHint:`已保存的密钥不会显示。在上方输入新 Key 可覆盖。`,oauthHint:`可使用 OAuth 授权登录,也可以手动填写 API Key。`,removeKey:`移除密钥`,removeKeyConfirm:`确定移除「{{name}}」的已保存 API Key?此操作不可撤销。`,removeKeySuccess:`API Key 已移除。`,removeKeyFailed:`移除失败。`},modelsSettings:{needToken:`请先保存网关访问令牌后再编辑 models.json。`,subtitle:`自定义服务商与模型(models.json)。保存后生效;重新加载可读取磁盘上的修改。`,docsLink:`模型与服务商文档`,loadError:`加载 models.json 失败`,loadFileWarning:`文件提示`,filePath:`路径`,addProvider:`添加服务商`,validate:`校验`,validating:`校验中…`,validateError:`校验请求失败`,save:`保存`,discard:`放弃`,saving:`保存中…`,saved:`已保存`,saveError:`保存失败`,reload:`重新加载`,reloading:`加载中…`,reloadError:`重新加载失败`,showJson:`显示 JSON`,hideJson:`隐藏 JSON`,modeGuided:`表单模式`,modeExpert:`JSON 模式`,modeGuidedHint:`通过表单添加服务商和模型,适合大多数配置场景。`,modeExpertHint:`直接编辑 models.json,适合需要精细配置的场景。`,statsProviders:`{{count}} 个服务商`,statsModels:`{{count}} 个模型`,unsavedHint:`有未保存的更改。`,loading:`加载中…`,jsonParseError:`JSON 无效`,jsonReset:`从编辑器还原`,jsonApply:`应用 JSON`,emptyTitle:`暂无自定义服务商`,emptyDesc:`可添加 OpenAI 兼容端点(Ollama、LM Studio、OpenRouter、vLLM 等)及可选的逐模型覆盖。`,emptyCta:`添加第一家服务商`,presetOllama:`Ollama`,presetLmStudio:`LM Studio`,presetOpenRouter:`OpenRouter`,presetZhipuCn:`智谱 GLM(国内 · Coding 端点)`,presetZaiGeneral:`智谱 GLM(国际 · 通用 API)`,presetLabel:`预设`,presetCustom:`自定义`,addProviderTitle:`添加服务商`,addProviderSubtitle:`服务商 ID 须唯一(如 ollama、my-openai)。`,providerIdLabel:`服务商 ID`,providerIdPlaceholder:`例如 ollama`,providerIdRequired:`请填写服务商 ID`,addProviderConfirm:`添加`,cancel:`取消`,close:`关闭`,baseUrl:`Base URL`,apiType:`API 类型`,apiKey:`API Key`,apiKeyPlaceholder:`sk-…、环境变量名 或 !命令`,apiKeyHint:`直接填写密钥、大写环境变量名,或以 ! 开头的 shell 命令`,authHeader:`自动发送 Authorization 头`,testKey:`测试`,show:`显示`,hide:`隐藏`,badgeShell:`shell`,badgeEnv:`env`,badgeLiteral:`字面量`,removeProvider:`删除服务商`,removeProviderConfirm:`删除服务商「{{id}}」及其模型?`,modelsSection:`模型`,modelsEmpty:`无自定义模型;在可用处将使用内置默认。`,addModel:`添加模型`,editModel:`编辑模型`,removeModel:`删除模型`,removeModelConfirm:`删除模型「{{id}}」?`,addModelTitle:`添加模型`,editModelTitle:`编辑模型`,modelProviderLabel:`服务商`,modelId:`模型 ID`,displayName:`显示名称`,inputTypes:`输入类型`,inputTextOnly:`仅文本`,inputTextVision:`文本 + 视觉`,reasoning:`支持推理`,contextWindow:`上下文窗口`,maxOutputTokens:`最大输出 Token 数`,costSection:`费用(每百万 token)`,costInput:`输入`,costOutput:`输出`,modelIdRequired:`请填写模型 ID`,mustBePositive:`必须大于 0`,addModelConfirm:`添加模型`,saveModelConfirm:`保存`,validationErrors:`校验问题`,validationWarnings:`警告`,testError:`错误`,testOk:`解析结果`}},Ke={remoteAccess:{pageTitle:`远程访问`,pageSubtitle:`从其他设备连接此 Gateway。选择一种方式即可 — 同一时间只应启用一种对外暴露模式。`,docsLink:`阅读远程访问指南`,tabsAria:`远程访问方式`,tabs:{guide:`概览`,tailscale:`Tailscale`,public:`公网访问`,"reverse-proxy":`反向代理`,ssh:`SSH 隧道`,lan:`局域网`},tabIntro:{guide:`对比各方式并查看当前 Gateway 上的激活状态。`,tailscale:`适合 tailnet 内的个人设备。Gateway 仍绑定 loopback,由 Tailscale Serve 发布 HTTPS。`,public:`先在 Console 创建 Tunnel Registration Key 并保存,再启动隧道获取公网地址,然后扫码配对移动 App。`,"reverse-proxy":`用自己的 HTTPS 反向代理(Caddy / nginx / Cloudflare Tunnel)将 Gateway 暴露在自定义域名下,然后扫码配对移动 App。`,ssh:`无 VPN 或公网隧道时,通过 CLI 做 SSH 端口转发。`,lan:`在同一 Wi‑Fi 或局域网内,通过 Gateway 绑定地址访问,并扫码配对移动 App。`},guide:{pickMethod:`选择连接方式`,recommended:`推荐`,configure:`去配置`,statusActive:`已启用`,statusOff:`未启用`,statusConnecting:`连接中`,tailscaleCardTitle:`Tailscale Serve`,tailscaleCardDesc:`仅在 tailnet 内提供 HTTPS,不暴露到公网。`,publicCardTitle:`公网隧道`,publicCardDesc:`生成公网 URL,用于移动配对与远程访问。`,reverseProxyCardTitle:`反向代理`,reverseProxyCardDesc:`用自部署的 HTTPS 反代将 Gateway 暴露在自定义域名下。`,sshCardTitle:`SSH 隧道`,sshCardDesc:`无 VPN 或公网隧道时,通过 CLI 做端口转发。`,sshCardStatus:`CLI`,lanCardTitle:`同一 Wi‑Fi / 局域网`,lanCardDesc:`通过 Gateway 绑定地址在同一局域网内访问。`,lanCardStatus:`本地`,conflictsTitle:`配置冲突`,conflictsHint:`同一时间只应启用一种暴露方式。切换前请先关闭另一种。`,oneAtATimeHint:`Tailscale Serve 与公网隧道不能同时运行。切换前请在概览页查看状态。`,needToken:`请先使用有效的 Gateway token 登录后再管理远程访问。`,docsLink:`查看完整文档`},advanced:{proxyTitle:`反向代理与 remote URL`,proxyBody:`Gateway 位于 nginx、Caddy 等反向代理之后时,需配置可信头与可选的 gateway.remote,供 CLI 客户端使用。`,proxyDocs:`阅读远程访问文档`},lan:{title:`同一网络(局域网)`,subtitle:`在同一 Wi‑Fi 下的手机或笔记本访问 Gateway,无需暴露到公网。`,body:`将 Gateway 绑定地址设为局域网 IP(或 0.0.0.0),通过 http://<主机>:<端口> 连接。请注意防火墙规则。`,link:`打开 Gateway 设置`,pairTitle:`移动 App 配对`,pairSubtitle:`在同一 Wi‑Fi 下扫码连接手机。App 会用一次性配对密钥换取 Gateway token。`,pairBlockedNextSteps:`或使用「公网访问」标签通过隧道配对。`,pairPublicTabLink:`打开公网访问`},tailscale:{title:`Tailscale Serve(推荐)`,subtitle:`在 tailnet 上通过 HTTPS 暴露 Gateway,进程仍绑定 loopback。`,statusLabel:`Serve 状态`,stepInstallBefore:`在本机安装 `,stepInstallLink:`Tailscale`,stepInstallAfter:` 并登录 tailnet。`,stepEnable:`在下方启用 Serve,通过 tailnet 主机名发布 HTTPS。`,stepCopy:`在 tailnet 内任意设备打开或复制 HTTPS 地址。`,loading:`正在加载 Tailscale 状态…`,statusActive:`Tailscale Serve 已启用。`,statusOff:`Tailscale Serve 未启用。`,enableServe:`启用 Serve`,disableServe:`停用 Serve`,copyUrl:`复制 HTTPS 地址`,copied:`已复制`,hint:`需要本机已安装并登录 Tailscale。API 仍需要 gateway token。`,docsLink:`Tailscale Serve 文档`,cliMissingIntro:`本机未找到 Tailscale CLI。`,cliMissingDownloadLink:`前往 tailscale.com/download 下载`,cliMissingSuffix:`,安装并登录后重试。`},ssh:{title:`SSH 隧道(CLI)`,subtitle:`无 Tailscale 时,将远程 Gateway 的 loopback 端口转发到本机。`,hint:`将 user@your-host 替换为你的 SSH 登录。在需要使用 Gateway 控制台的机器上运行。`,copy:`复制命令`,copied:`已复制`},reverseProxy:{title:`反向代理(自部署 HTTPS)`,subtitle:`用自己部署的 Caddy / nginx / Cloudflare Tunnel 将 Gateway 暴露在自定义域名下。`,urlLabel:`公网 URL`,urlPlaceholder:`https://gateway.example.com`,urlHint:`不能包含路径。公网域名必须使用 https;http 仅限 RFC1918 / .local。`,probeButton:`测试`,probing:`测试中…`,autoDetectedTitle:`已自动识别当前浏览器地址`,autoDetectedHint:`下方 QR 已使用此 URL。点击「保存为默认」可持久化,让其他机器/重启后共用同一地址。`,saveAsDefault:`保存为默认`,saving:`保存中…`,clear:`清除已保存的 URL`,certWarning:`移动端需要系统信任根证书(Let's Encrypt / Cloudflare / 商业 CA)。v1 不支持自签证书。`,qrTitle:`移动 App 配对 QR`,qrSubtitle:`在 xopc 移动 App 中扫码即可通过反向代理完成配对。`,noUrlYet:`请先在上方输入反代公网 URL 以生成配对 QR。`,mintingSecret:`正在生成配对密钥…`,encoding:`正在生成 QR…`,refreshQr:`刷新 QR`,copyLink:`复制 deeplink`,copied:`已复制`,probeStatus:{ok:`可达`,mobileReady:`移动配对就绪`,codeUnknown:`测试失败`,code_TIMEOUT:`请求超时`,code_TLS_INVALID:`TLS / 证书错误`,code_DNS_OR_CONN_REFUSED:`DNS 解析失败或连接被拒`,code_NETWORK_ERROR:`网络错误`,code_AUTH_BLOCKED:`反代返回 401/403 — 请移除 /api/tunnel/pair/ping 前面的鉴权`,code_HTTP_ERROR:`HTTP 错误`,code_NOT_XOPC_GATEWAY:`URL 未识别为 xopc gateway`,code_invalid_url:`URL 不合法`,code_invalid_scheme:`Scheme 必须是 http(s)`,code_has_userinfo:`URL 不能包含用户名密码`,code_has_path:`URL 不能包含路径`,code_has_query_or_fragment:`URL 不能包含 query 或 fragment`,code_requires_https:`公网域名必须使用 https`,code_INVALID_JSON:`请求体 JSON 不合法`}}}},qe={sessions:{title:`会话`,needToken:`请先保存网关访问令牌后再管理会话。`,searchPlaceholder:`搜索会话…`,filterAll:`全部`,filterActive:`活跃`,filterPinned:`置顶`,filterArchived:`归档`,filterChannelAll:`全部通道`,filterChannelLabel:`通道`,totalSessions:`总计`,activeSessions:`活跃`,pinnedSessions:`置顶`,archivedSessions:`归档`,sessionCount:`已显示 {{count}} 个`,loadMore:`加载更多`,noSessions:`暂无会话`,noSessionsDescription:`在「对话」中开始聊天后,会话将显示在这里。`,startNewChat:`开始新对话`,continueChat:`在对话中继续`,archive:`归档`,unarchive:`取消归档`,pin:`置顶`,unpin:`取消置顶`,export:`导出 JSON`,delete:`删除`,deleteSessionTitle:`删除会话?`,deleteSessionMessage:`确定删除「{{name}}」吗?此操作不可恢复。`,cancel:`取消`,loading:`加载中…`,loadError:`加载会话失败`,gridView:`网格`,listView:`列表`,layoutToggleGroup:`会话布局`,detailLoading:`加载会话…`,detailMessages:`消息`,detailExport:`导出`,close:`关闭`,config:{title:`会话存储`,hint:`私信会话的键名规则以及旧会话元数据的清理策略。`,save:`保存`,discard:`放弃`,saving:`保存中…`,saveError:`保存会话设置失败`,dmScope:`私信会话范围`,dmScopeHint:`控制跨通道与账号的私信如何映射到 session key。`,dmScopeMain:`主会话(单一私信)`,dmScopePerPeer:`按对端`,dmScopePerChannelPeer:`按通道 + 对端`,dmScopePerAccountChannelPeer:`按账号 + 通道 + 对端`,pruneAfterDays:`清理阈值(天)`,maxEntries:`最大会话条目数`,unsetPlaceholder:`留空使用默认值`}}},Je={settingsSections:{overview:`系统状态`,appearance:`偏好设置`,agent:`智能体`,"agent-defaults":`智能体配置`,"agent-chat":`默认配置`,"agent-workspace":`工作区`,"agent-browser":`浏览器`,"agent-runtime":`单轮限制`,"agent-context":`上下文`,"agent-memory":`记忆`,"agent-tools":`工具`,"agent-skills":`默认可用技能`,"agent-mcp":`外部工具 (MCP)`,"agent-system-prompt":`系统提示词`,providers:`LLM 服务商`,credentials:`模型与密钥`,models:`模型`,"image-models":`图像`,channels:`消息通道`,voice:`语音`,gateway:`网关`,heartbeat:`心跳`,tunnel:`远程访问`,"remote-access":`远程访问`,shares:`文件分享`,search:`网络搜索`,dreams:`后台反思`,goals:`目标模式`,agents:`智能体`,system:`系统授权`,"app-management":`应用管理`,cron:`定时任务`,skills:`技能`},settingsPage:{comingSoon:`设置 · {{title}}(即将推出)。`},modelsHub:{subtitle:`服务商密钥、模型、图像生成、语音、网络搜索。`,docsLink:`查看文档`,tabsAria:`模型与密钥分区`,saveBar:{title:`未保存改动汇总`,cleanSummary:`所有分区都已保存。`,dirtySummary:`{{count}} 个分区有未保存改动。`,savedSummary:`所有改动已保存。`,failuresSummary:`{{count}} 个分区保存失败。`,saveAll:`全部保存`,discardAll:`全部丢弃`},providersHint:`为 xopc 支持的 LLM 服务商设置或更换 API Key 与 OAuth 授权。`,modelsHint:`管理默认模型、备用模型,以及手动添加的模型。`,imageHint:`图像理解(视觉)与图像生成的默认配置,以及各服务商密钥。`,voiceHint:`文本转语音、语音转文本的服务商、触发模式与润色设置。`,searchHint:"`web_search` 工具用的搜索厂商。区域与域名拦截规则也在这里。"},setupStatus:{title:`系统状态`,subtitle:`查看当前配置进度,完成必要步骤后即可开始对话。`,refresh:`刷新`,loading:`正在加载状态…`,loadError:`无法加载系统状态,请检查网关连接后重试。`,summaryTitle:`概览`,summarySubtitle:`对话所需的核心服务。`,summaryGateway:`网关`,summaryProviders:`服务商`,summaryModel:`默认模型`,statusOnline:`在线`,statusOffline:`离线`,requiredCompleteMessage:`基础配置已完成,可以开始对话。`,requiredIncompleteMessage:`完成下方基础步骤后即可开始对话。`,checklistTitle:`设置清单`,checklistSubtitle:`点击步骤进入对应设置。带「可选」标记的步骤可稍后再做。`,optionalBadge:`可选`,labels:{gatewayOnline:`已连接网关`,gatewayOffline:`未连接 — 请检查令牌与网关`,providersConfigured:`已配置 {{count}} 个服务商`,providersMetaReady:`{{configured}} / {{total}} 个服务商已就绪`,providersMissing:`尚未配置服务商`,modelConfigured:`{{model}}`,modelMissing:`尚未选择默认模型`,channelConfigured:`已连接至少一个消息通道`,channelMissing:`尚未配置消息通道`,skillsConfigured:`已有 {{count}} 个可用技能`,skillsMissing:`尚未安装技能`,presetsConfigured:`已配置 {{count}} 个智能体`,presetsMissing:`仅有默认智能体 — 可添加预设角色`},items:{gateway:{title:`连接网关`,description:`确认网页控制台可以访问 xopc 网关。`},provider:{title:`配置 LLM 服务商`,description:`至少添加一家 AI 服务商的 API 密钥或 OAuth 令牌。`},defaultModel:{title:`选择默认模型`,description:`设置新对话使用的默认模型。`},channel:{title:`连接消息通道`,description:`关联 Telegram、微信或飞书,从即时通讯应用对话。`},skill:{title:`安装技能`,description:`从市场或目录安装技能,扩展智能体能力。`},presets:{title:`添加预设智能体`,description:`创建专用智能体(如编程、写作等)以应对不同任务。`}},scenarios:{title:`快速场景向导`,subtitle:`按使用方式选择路径 — 每一步会打开对应设置页。`,dismiss:`隐藏`,steps:{stepProviders:`配置 LLM 服务商密钥`,stepDefaultModel:`选择默认对话模型`,stepChannel:`连接消息通道`,stepPresets:`添加专用智能体`,stepCron:`设置定时任务`,stepSkills:`从目录安装技能`},presets:{lightChat:{title:`轻量对话`,description:`在网页控制台对话 — 配置一家服务商并选择默认模型即可。`},multiChannel:{title:`多频道助手`,description:`从 Telegram 等通道回复,并为不同场景配置专用智能体。`},automation:{title:`自动化工作流`,description:`结合技能与定时任务,完成周期性后台工作。`}}}},credentialsHub:{title:`密钥与授权`,subtitle:`集中管理对话、搜索、图像和语音所需的 API 密钥与 OAuth 授权。`,refresh:`刷新`,loading:`正在加载凭证状态…`,loadError:`无法加载凭证状态,请检查网关连接后重试。`,domainsTitle:`密钥分类`,domainsSubtitle:`在对应详情页管理密钥,保存后写入本地网关配置。`,footerHint:`LLM 密钥在「LLM 服务商」页管理。图像、语音和网页搜索密钥也可能来自环境变量;这里仅显示已写入配置的项目。`,status:{ready:`就绪`,partial:`部分`,missing:`缺失`,notNeeded:`可选`},labels:{llmMetaReady:`{{configured}} / {{total}} 个 LLM 服务商已就绪`,llmConfigured:`已配置 {{count}} 个 LLM 服务商`,llmMissing:`尚未配置 LLM 服务商`,webSearchDisabled:`网页搜索已关闭`,webSearchReady:`已设置 {{configured}} / {{total}} 个搜索 API 密钥`,webSearchNoProviders:`尚未配置搜索服务商`,imageReady:`已配置 {{configured}} / {{total}} 个图像服务商`,imageNoProviders:`尚未配置图像服务商`,voiceDisabled:`语音输入/输出已关闭`,voiceReadyNoKeys:`语音已启用 — 无需 API 密钥`,voiceKeysReady:`已设置 {{configured}} / {{total}} 个语音 API 密钥`,voiceMissing:`语音尚未配置`},domains:{llm:{title:`LLM 服务商`,description:`对话模型所需的 API 密钥与 OAuth 授权。`},webSearch:{title:`网页搜索`,description:`Brave、Tavily 等搜索 API 密钥。`},image:{title:`图像生成`,description:`视觉理解与图像生成服务商密钥。`},voice:{title:`语音(STT / TTS)`,description:`语音识别与文字转语音所需的密钥。`}}},dreamingSettings:{title:`梦境`,subtitle:`查看并维护后台记忆晋升(deep promotion)任务的运行状态。`,tabsAriaLabel:`梦境设置分类`,tabConfig:`配置`,tabRuntime:`运行状态`,tabInsights:`预览与日志`,tabMaintenance:`维护`,configTabHint:`调整 dreaming 总开关、全局调度和 Light / Deep / REM 三阶段参数。`,runtimeTabHint:`查看当前生效调度、晋升锁、短期召回存储和最近运行结果。`,insightsTabHint:`预览可晋升候选,并查看各阶段运行审计日志。`,maintenanceTabHint:`重置短期 store 或清理卡住的晋升锁;不会修改 MEMORY.md。`,refresh:`刷新`,runNow:`立即执行`,runPhaseLabel:`阶段`,runNowHint:`立刻触发一次托管 cron job。`,runQueued:`已触发执行。`,actionOk:`已完成。`,configSaved:`配置已保存。`,configTitle:`配置`,configHint:`编辑 agents.defaults.memory.dreaming,并写回网关配置文件。`,configLoading:`正在加载配置…`,saveConfig:`保存`,resetConfig:`重置`,configEnabled:`启用 dreaming`,configFrequency:`全局 fallback 调度`,configTimezone:`时区(IANA)`,configPhaseLight:`浅睡眠(Light)`,configPhaseLightHint:`轻量去重扫描(默认每 6 小时)。`,configPhaseDeep:`深度睡眠(Deep)`,configPhaseDeepHint:`完整评分晋升,含时间衰减(每天凌晨 3 点)。`,configPhaseRem:`快速眼动(REM)`,configPhaseRemHint:`跨条目模式聚类与梦境日记(每周日凌晨 5 点)。`,configPhaseEnabled:`启用`,configPhaseCron:`Cron 表达式`,configLightLookbackDays:`回溯天数`,configLightLimit:`条数上限`,configLightDedupe:`去重相似度`,configDeepMinScore:`最低分数`,configDeepMinRecallCount:`最低召回次数`,configDeepLimit:`条数上限`,configDeepHalfLife:`时间衰减半衰期(天)`,configDeepMaxAge:`最大年龄(天)`,configRemLookbackDays:`回溯天数`,configRemLimit:`条数上限`,configRemMinStrength:`最低模式强度`,previewTitle:`预览(dry-run)`,previewHint:`展示经过 rehydrate、污染过滤、marker/hash 去重后的候选列表,不会写入任何文件。`,previewLoad:`加载预览`,previewNotLoaded:`尚未加载预览。`,previewEmpty:`没有可晋升的候选。`,previewEligible:`可晋升`,runtimeTitle:`运行状态`,runtimeHint:`只读:网关上当前生效的调度、短期 store 与最近一次扫描结果。`,subsectionSchedule:`调度与锁`,subsectionStore:`短期召回`,subsectionPhases:`三阶段配置(实际生效)`,subsectionDeep:`门控(实际生效)`,subsectionLastRun:`最近扫描(Deep)`,subsectionLightLastRun:`最近扫描(Light)`,subsectionRemLastRun:`最近扫描(REM)`,lastRunBlockHint:`数据文件:memory/.dreams/last-run.json`,phaseLastRunEmpty:`尚无运行记录。`,phaseLastRunOk:`成功`,phaseLastRunFailed:`失败`,lockValueLocked:`已锁定`,lockValueUnlocked:`未锁定`,statusTitle:`状态`,statusHint:`读取当前工作区下的存储文件(memory/.dreams)。`,enabled:`启用`,on:`开启`,off:`关闭`,schedule:`频率`,timezone:`时区`,lock:`晋升锁`,storeEntries:`信号条目数`,storePromoted:`已晋升条目数`,storeUpdatedAt:`存储更新时间`,storeLastPromotedAt:`最近晋升时间`,deepGate:`门控参数:`,deepGateValue:`minScore={{minScore}},minRecallCount={{minRecallCount}},limit={{limit}}`,lastRunTitle:`最近一次运行`,lastRunHint:`memory/.dreams/last-run.json:耗时、门控配置快照、候选/应用数量与跳过原因。下方可查看原始 JSON。`,lastRunEmpty:`尚无运行记录。`,lastRunDuration:`耗时`,lastRunStatus:`结果`,lastRunSuccess:`成功`,lastRunFailure:`失败`,lastRunReason:`原因`,lastRunError:`错误`,lastRunRanked:`进入排序的候选数`,lastRunApplied:`写入 MEMORY.md 条数`,lastRunSkipped:`跳过(计数)`,lastRunSkipKey:`键已在 MEMORY 中`,lastRunSkipRehydrate:`片段还原失败`,lastRunSkipContaminated:`内容污染`,lastRunSkipHash:`哈希去重`,lastRunParseError:`无法解析 last-run 文件`,lastRunRaw:`原始 JSON`,eventsTitle:`事件日志`,eventsHint:`记忆整理各阶段的运行审计记录(memory/.dreams/events.jsonl)。`,eventsLoad:`加载日志`,eventsNotLoaded:`尚未加载事件日志。`,eventsEmpty:`暂无事件记录。`,maintenanceTitle:`维护`,maintenanceHint:`仅影响 store/lock 文件,不会修改 MEMORY.md。`,resetStore:`重置 store`,clearLock:`清理锁文件`,confirmResetStore:`确认重置 dreaming store?这会清空短期召回信号。`,confirmClearLock:`确认删除晋升锁文件?仅在 sweep 卡住时使用。`},systemSettings:{title:`系统授权`,behaviorGroup:`应用行为`,desktopOnlyTitle:`仅桌面端`,desktopOnlyBody:`系统集成功能仅在 xopc Electron 桌面版中可用。在浏览器中请通过操作系统设置管理。`,toggles:{openAtLogin:`开机自动启动`,openAtLoginDesc:`登录本机用户时自动启动 xopc。`,keepAwake:`保持系统唤醒`,keepAwakeDesc:`开启后请求系统保持唤醒,减少因空闲睡眠中断长时间任务。`,notifyDesktop:`桌面通知`,notifyDesktopDesc:`应用在后台时显示系统通知(更新提醒、应用内提示、智能体错误等)。`,notifySound:`声音通知`,notifySoundDesc:`每条桌面通知播放短提示音。`},permissionsTitle:`系统权限`,permissionsHint:`状态为尽量检测,修改系统设置后请刷新或重新进入本页。`,permissionsHintDarwin:`macOS 的隐私/媒体状态为尽量检测。修改系统设置后请用「刷新状态」或再次进入本页。`,permissionsHintDevDarwin:`开发模式(electron:dev)在系统设置中显示为 Electron,而非 xopc。请用打包后的 .app 验证权限名称是否正确。`,permissionsHintWin:`在 Windows 上,麦克风和(如系统可报告)录屏等能力受系统级开关影响;每个按钮会打开系统「设置」中的相关页面。`,permissionsHintLinux:`Linux 上此处不显示各权限的准确状态。会尝试打开桌面环境设置,失败时打开说明文档。请在发行版/Flatpak/ portal 中授予「文件、麦克风、通知」等。`,status:{granted:`已授权`,denied:`未授权`,unknown:`未知`},openSettings:`去设置`,refresh:`刷新状态`,refreshing:`刷新中…`,refreshDone:`权限状态已更新。`,openSettingsDone:`已打开系统设置。`,openSettingsFailed:`无法打开系统设置,请从系统偏好设置中手动查找对应项。`,requestAccess:`请求访问`,permFeedback:{granted:`麦克风已授权。`,alreadyGranted:`麦克风此前已授权。`,openedSettings:`已在系统设置中打开麦克风页面,请启用 xopc 后点击「刷新状态」。`,denied:`麦克风未授权,请在系统设置中启用 xopc。`,rendererDenied:`浏览器层无法访问麦克风,请检查系统隐私设置。`,prompted:`若出现系统提示,请选择允许麦克风访问。`},screenFeedback:{granted:`录屏权限已授权。`,alreadyGranted:`录屏此前已授权。`,openedSettings:`已在系统设置中打开录屏页面,请启用 xopc 后点击「刷新状态」。`,denied:`录屏未授权,请在系统设置中启用 xopc。`,prompted:`若出现系统提示,请允许 xopc 进行屏幕录制。`},accessibilityFeedback:{granted:`辅助功能已授权。`,alreadyGranted:`辅助功能此前已授权。`,openedSettings:`已在系统设置中打开辅助功能页面,请启用 xopc 后点击「刷新状态」。`,denied:`辅助功能未授权,请在系统设置中启用 xopc。`},notificationsFeedback:{granted:`通知权限已授权。`,alreadyGranted:`通知此前已授权。`,openedSettings:`已在系统设置中打开通知页面,请启用 xopc 后点击「刷新状态」。`,denied:`通知权限被拒绝,请在系统设置中启用 xopc。`,prompted:`若出现系统提示,请允许 xopc 发送通知。`,default:`未选择通知权限,请重试或在系统设置中手动启用。`,unsupported:`当前环境不支持系统通知。`},desktopNotify:{testTitle:`桌面通知已开启`,testBody:`当 xopc 在后台运行时会在此显示提醒。`,testShown:`已发送测试通知。若未看到,请在系统设置中允许 xopc 的通知。`,denied:`通知权限被拒绝。请先在系统中允许 xopc 的通知,再重试。`,agentErrorTitle:`智能体运行失败`,agentErrorBody:`打开 xopc 查看详情。`},perm:{fullDisk:{title:`文件与磁盘访问`,desc:`在需要时访问工作区、用户目录等(具体名称因系统而异)。`},screen:{title:`录屏`,desc:`在应用内浏览器外进行整屏/窗口采集、供视觉类能力使用。`},microphone:{title:`麦克风`,desc:`在对话和语音能力中录音。`},accessibility:{title:`辅助功能`,desc:`使用全局快捷键及辅助功能相关能力。`},automation:{title:`自动操作 / 与系统集成`,desc:`与其他应用或系统能力协作(在 macOS 上对应自动化与隐私;在 Windows 上为默认应用等;Linux 为桌面/portal 能力)。`},notifications:{title:`通知`,desc:`在系统「通知」或本应用项中允许通知,以便任务完成时提示。`},location:{title:`位置`,desc:`在提供地理位置相关任务时获取位置信息。`}},permUnknown:{fullDisk:{darwin:`macOS 在真正访问前无法准确报告。若读取工作区失败,请在「完全磁盘访问权限」中启用 xopc。`,win32:`Windows 无法在此准确报告。若文件访问失败,请打开「存储」相关设置。`,linux:`若文件访问失败,请在发行版、Flatpak 或 desktop portal 中授予文件权限。`},screen:{darwin:`若录屏/截屏失败,请在「屏幕录制」中为 xopc 授权。`,win32:`若屏幕采集失败,请在「设置」中允许桌面应用的屏幕捕获。`,linux:`若屏幕采集失败,请在 desktop portal 或合成器设置中授权。`},microphone:{darwin:`若语音输入失败,请点「请求访问」或打开「麦克风」隐私设置。`,win32:`若语音输入失败,请点「请求访问」或打开「麦克风」隐私设置。`,linux:`若语音输入失败,请在桌面环境或 Flatpak 中授予麦克风权限。`},accessibility:{darwin:`全局快捷键需要辅助功能权限。请「请求访问」后在「辅助功能」中启用 xopc。`,win32:`若全局快捷键或集成失败,请打开「辅助功能」设置。`,linux:`若快捷键失败,请在桌面环境的辅助功能/权限设置中授权。`},automation:{darwin:`若控制其他应用失败,请在「自动化」/ Apple 事件中为 xopc 授权。`,win32:`若与其他应用集成失败,请在 Windows「设置」中配置默认应用与自动化。`,linux:`若自动化失败,请在 desktop portal 或会话设置中授权应用集成。`},notifications:{darwin:`请「请求访问」,然后在系统「通知」中为 xopc 开启通知。`,win32:`请「请求访问」,然后在「设置」中为 xopc 开启通知。`,linux:`请在桌面环境或 Flatpak 权限中允许通知。`},location:{darwin:`若位置功能失败,请在「定位服务」中为 xopc 授权。`,win32:`若位置功能失败,请在「设置」中允许桌面应用访问位置。`,linux:`若位置功能失败,请在 desktop portal 中授予位置权限。`}},appManagement:{title:`应用管理`,loading:`加载中…`,devOnlyTitle:`开发模式`,devOnlyBody:`清除数据与卸载仅在打包后的桌面应用中可用。下方路径仅供参考。`,appPath:`安装位置`,dataPath:`本地数据`,dataSize:`数据大小`,dataSizeUnknown:`—`,copyPath:`复制`,copied:`已复制`,copyFailed:`无法复制到剪贴板,请手动选择路径复制。`,cliDataWarning:`检测到独立的 CLI 数据目录 ~/.xopc。在此清除本地数据不会删除该目录。`,openCliData:`打开 CLI 数据目录`,pendingUpdateBlocked:`有待安装的更新时无法清除数据或卸载,请先完成或取消更新。`,clearData:`清除本地数据`,clearDataDesc:`删除配置、会话、工作区与缓存。应用将重启并恢复默认设置。`,clearDataConfirmTitle:`清除本地数据?`,clearDataConfirmDesc:`将永久删除桌面应用保存的 API 密钥、会话、对话记录与工作区文件,且无法恢复。`,clearDataConfirmCheckbox:`我了解此操作不可恢复`,clearDataConfirmPhrase:`确认删除`,clearDataConfirmLabel:`请输入「确认删除」以继续`,clearDataConfirmHint:`必须输入「确认删除」后才会启用清除按钮。`,uninstall:`卸载应用`,uninstallDescDarwin:`将在 Finder 中选中 xopc 并退出应用。请将 xopc.app 拖入废纸篓以完成卸载。`,uninstallDescWin:`将打开 Windows 卸载向导并退出 xopc。`,uninstallDescLinuxAppImage:`将打开 AppImage 所在文件夹并退出 xopc。删除该 AppImage 文件即可完成卸载。`,uninstallDescLinuxDeb:`将退出 xopc 并打开安装目录。在终端执行:sudo dpkg -r {{package}}(或使用发行版软件中心卸载)。`,uninstallDescLinuxUnknown:`将打开安装位置并退出 xopc。请使用发行版工具删除应用文件或软件包。`,uninstallConfirmTitle:`卸载 xopc?`,removeUserDataCheckbox:`卸载前同时清除本地数据`,confirmClear:`清除数据`,confirmUninstall:`卸载`,cancel:`取消`,errors:{pendingUpdate:`已有下载完成的更新等待安装。请先重启完成更新,再卸载。`,uninstallerNotFound:`未找到卸载程序。请在「设置 → 应用 → 已安装的应用」中移除 xopc。`,notPackaged:`开发模式下无法执行此操作,请使用打包后的桌面应用。`,generic:`操作失败。请重试或通过系统设置卸载。`}}},settingsNavGroups:{general:`通用`,system:`系统设置`,credentials:`模型与密钥`,agent:`智能体配置`,connection:`连接`,automation:`自动化`,diagnostics:`诊断`,extensions:`扩展`},cronSettingsPage:{title:`定时任务`,subtitle:`调度引擎开关、并发、时区与运行历史保留等全局参数。`,tasksLink:`管理任务与运行历史 →`},goalsSettingsPage:{title:`目标评判`,subtitle:`持久目标 /goal 的评判模型、轮数上限与清单模式默认值。`},imageModelsSettings:{title:`图像`,subtitle:`配置图像理解、图像生成的默认模型、运行参数和图像服务商密钥。`,refresh:`刷新`,crossLinkHint:`对话主模型和采样参数在「对话」中设置;文本备用模型在「模型」中设置。本页用于配置图像理解和图像生成相关默认项。`,timeoutLabel:`超时(毫秒)`,timeoutHint:`单次生成的最大耗时,留空使用网关默认值(120000 毫秒)。`,autoFallbackLabel:`失败时尝试其他已配置服务商`,autoFallbackHint:`当前备用模型都失败后,会继续按顺序尝试其他已配置服务商。`,save:`保存`,discard:`放弃`,saving:`保存中…`,saved:`已保存。`,fallbackChainsTitle:`备用模型`,runtimeTuningTitle:`运行参数`,providersTitle:`图像服务商`,providersEmpty:`尚未配置图像生成服务商。`,configured:`已配置`,missingKey:`缺少 API Key`,unsavedChanges:`未保存`,expandProvider:`展开服务商配置`,collapseProvider:`收起服务商配置`,defaultModel:`默认模型`,modelsLabel:`模型`,modelCountOne:`1 个模型`,modelCountMany:`{count} 个模型`,credentialsIntro:`在这里填写图像服务商的 API Key 和可选接口地址。密钥会保存在本地配置中,网关不会返回完整密钥。`,apiKeyLabel:`API Key`,regionLabel:`区域`,regionHint:`DashScope:在卡片中选择区域后,会自动写入 region 和官方图像接口地址;选择「自定义」后可手动填写。`,endpointPresetsHint:`如果卡片提供接口地址或集群预设,请选择一项;选择「自定义」后可手动填写 Base URL。`,baseUrlLabel:`Base URL`,imageBaseUrlLabel:`图像 Base URL`,optionalPlaceholder:`可选`,saveCredentials:`保存密钥`,savingCredentials:`保存中…`,credentialsSaved:`密钥已保存。`,discardCredentials:`放弃密钥修改`,credentialsSaveError:`无法保存服务商密钥。`,credentialsNothingToSave:`没有需要保存的密钥变更。`,regionPresetDefault:`默认(由网关自动选择)`,regionPresetCustom:`自定义区域 / 端点`,baseUrlPresetDefault:`默认(官方地址)`,baseUrlPresetCustom:`自定义 URL`,openExtensionSettings:`扩展设置页`,openImageModelsPage:`打开「图像」设置`,extensionSettingsLinkTitle:`打开该服务商的扩展设置`,imageModelsLinkTitle:`打开「图像」设置(全部 Provider)`,imageBaseUrlPresetHint:`由区域预设自动填入;选择「自定义」后可编辑。`,dashscopeRegion_beijing:`中国(北京)`,dashscopeRegion_singapore:`国际(新加坡)`,dashscopeRegion_us:`美国(弗吉尼亚)`,apiKeyMaskedHelp:`已保存的密钥默认隐藏。点击眼睛图标可从配置文件读取(仅 providers.<id>.apiKey,不含环境变量里的密钥)。`,apiKeyCopy:`复制`,apiKeyCopied:`已复制`,apiKeyShow:`显示密钥`,apiKeyHide:`隐藏密钥`,apiKeyNotInConfigFile:`配置文件里没有该 Provider 的 API Key(可能只通过环境变量提供)。`,apiKeyRevealFailed:`无法从网关读取密钥。`,minimaxClusterLabel:`MiniMax 集群(API 主机)`,minimaxClusterHint:`MiniMax 区分国内与国际靠的是不同主机名,配置里写在 providers.minimax.baseUrl,而不是像 DashScope 那样用 region 字段;DashScope 用 region 再映射到官方图像接口 URL。`,falQueueBaseLabel:`Fal 队列 / API 根地址`,falQueueBaseHint:`Fal 文生图请求挂在队列根地址上(默认 https://queue.fal.run),对应配置项 providers.fal.baseUrl。`},extensionImageGen:{banner:`API Key 与端点写入全局配置 providers.<id>(与「设置 → 图像」相同)。两个入口任选其一,保存后会保持一致。`,openImageModels:`打开「图像」设置(全部 Provider)`},extensionSttMedia:{banner:`STT 凭据写入 tools.media.audio.providers.<id>(与「设置 → 语音」相同)。两个入口任选其一,保存后会保持一致。`,openVoice:`打开「语音」设置(全部 STT Provider)`,credentialsTitle:`STT 凭据`,credentialsHint:`保存时会写入 tools.media.audio.providers.{providerId},并启用 STT。`,configured:`已配置`,notConfigured:`未配置`},appearanceSettings:{pageTitle:`偏好设置`,subtitle:`语言、界面外观与对话字号等日常使用的显示行为,仅保存在本浏览器。`,languageTitle:`语言`,languageDescription:`选择界面语言。`,themeTitle:`主题亮暗`,themeDescription:`浅色、深色,或跟随系统。`,colorSchemeTitle:`配色方案`,colorSchemeDescription:`界面的视觉风格。`,colorSchemeDefault:`默认`,colorSchemeLightGreen:`浅绿`,colorSchemeModernMono:`mono/单色`,colorSchemeClay:`奶油 Clay`,fontScaleTitle:`对话字号`,fontScaleDescription:`调整对话与阅读区域的文字大小。`,fontScaleCompact:`小`,fontScaleDefault:`中`,fontScaleLarge:`大`,langOptionEn:`English`,langOptionZh:`中文`,themeOptionLight:`浅色`,themeOptionDark:`深色`,themeOptionSystem:`跟随系统`,openFullPreferences:`打开全部设置`,quickMenuHint:`语言、主题与字号`,aboutApp:`关于`,developerGroupTitle:`开发者选项`,developerGroupDescription:`影响对话中工具调用结果的展示形式。`,showRawToolDataTitle:`显示工具调试数据`,showRawToolDataDescription:`在工具调用步骤中显示原始 JSON 输入与输出,便于排查问题。`},mcpSettings:{title:`外部工具 (MCP)`,subtitle:`配置出站 MCP 服务(stdio 或 HTTP),供嵌入式 Agent 运行时使用。可在 Agent 的 tools.disable 中加入 "bundle-mcp" 关闭全部 MCP 工具。`,loading:`正在加载 MCP 配置…`,saved:`MCP 配置已保存。`,save:`保存`,discard:`放弃更改`,saving:`保存中…`,globalTitle:`运行时`,globalHint:`会话空闲 TTL 控制未使用的 MCP 客户端何时被回收(0 = 永不回收)。`,idleTtlLabel:`会话空闲 TTL(分钟)`,idleTtlHint:`未设置时默认 10 分钟。设为 0 表示禁用空闲回收。`,idleTtlPlaceholder:`10`,serversTitle:`服务器`,serversHint:`每个 server id 会作为工具名前缀(server__tool)。扩展的 .mcp.json 会自动合并。`,serversEmpty:`尚未配置 MCP 服务器。`,addServer:`添加服务器`,removeServer:`删除`,serverIdPlaceholder:`server-id`,serverIdLabel:`服务器名称`,serverCardTitle:`MCP 服务器`,cardUntitled:`未命名服务器`,cardExpandAria:`展开服务器配置`,cardCollapseAria:`折叠服务器配置`,transportLabel:`服务器类型`,commandLabel:`命令`,argsLabel:`参数`,argsHint:`以空格分隔(不含 shell 引号)。`,cwdLabel:`工作目录`,envLabel:`环境变量(JSON 对象)`,envHint:"值可使用 ${ENV_VAR}。危险的主机环境变量会在启动时被过滤。",urlLabel:`服务器地址`,headersLabel:`Headers`,optionalSuffix:`(可选)`,headersHint:`远程 MCP 服务的 Bearer token 与自定义头。`,addHeader:`添加 Header`,removeHeader:`删除 Header`,pasteHeaders:`粘贴`,pasteHeadersFailed:`无法解析请求头。请粘贴 JSON 对象,或 "Authorization: Bearer token" 格式的多行文本。`,headerKeyPlaceholder:`Authorization`,headerValuePlaceholder:`Bearer your-token`,timeoutLabel:`超时时间(可选)`,timeoutHint:`连接、工具列表获取及工具调用的超时时间,单位为秒(1–600)。留空使用默认值(30 秒)。`,timeoutPlaceholder:`30`,testConnection:`测试`,toolsTitle:`MCP 工具({{count}})`,toolsSummary:`发现 {{count}} 个工具`,toolsLoading:`正在获取工具列表…`,toolsEmpty:`该服务器未返回任何工具。`,viewAllTools:`查看全部`,toolsDialogTitle:`MCP 工具列表`,toolsDialogSubtitle:`{{serverId}} · 共 {{count}} 个工具`,toolsDialogSearchPlaceholder:`按名称或描述搜索…`,toolsDialogSearchEmpty:`没有匹配的工具。`,toolsDialogClose:`关闭`,disableHint:`若需禁止某 Agent 使用 MCP,在 Agent 默认或单个 Agent 的 tools.disable 中加入 bundle-mcp。`,transportLabels:{stdio:`stdio`,sse:`SSE`,"streamable-http":`Streamable HTTP`}}},Ye={appBrand:`XOPC`,sidebarCollapse:`收起侧边栏`,sidebarExpand:`展开侧边栏`,titleBarCommandPalette:`命令面板`,historyBack:`后退`,historyForward:`前进`,closeMenu:`关闭菜单`,openMenu:`打开菜单`,appBarPreferences:`语言与主题`,nav:{chat:`对话`,settings:`设置`,sessions:`会话管理`,cron:`定时任务`,skills:`技能`,channels:`消息通道`,agents:`智能体`,apps:`应用`,logs:`诊断日志`,settingsAppearance:`偏好设置`,settingsOverview:`系统状态`,settingsCredentials:`密钥与授权`,settingsProviders:`LLM 服务商`,settingsModels:`模型`,settingsImageModels:`图像`,settingsChannels:`消息通道`,settingsVoice:`语音`,settingsGateway:`网关`,settingsHeartbeat:`心跳`,settingsTunnel:`远程访问`,settingsShares:`文件分享`,settingsSearch:`网络搜索`,settingsDreams:`梦境`,settingsCron:`定时任务`,settingsGoals:`目标评判`,settingsAgentDefaults:`智能体配置`,settingsAgentChat:`默认配置`,settingsAgentWorkspace:`工作区`,settingsAgentBrowser:`浏览器`,settingsAgentRuntime:`单轮限制`,settingsAgentContext:`上下文`,settingsAgentMemory:`记忆`,settingsAgentTools:`工具`,settingsAgentSkills:`默认可用技能`,settingsAgentMcp:`外部工具 (MCP)`,settingsAgentSystemPrompt:`系统提示词`,settingsAgents:`智能体`,settingsSystem:`系统授权`,settingsAppManagement:`应用管理`},token:{title:`需要身份验证`,description:`请输入网关访问令牌以继续。`,gatewayUrl:`网关地址`,tokenLabel:`访问令牌`,placeholder:`网关访问令牌(例如 ea4c67bf…)`,save:`保存`,show:`显示`,hide:`隐藏`},gatewayLanding:{headline:`连接网关`,subline:`网页控制台需使用与网关相同的访问令牌。请从初始化向导或配置文件中获取,并在下方粘贴。`,sessionExpired:`登录已失效或访问令牌被拒绝,请重新输入有效的网关访问令牌。`,stepOnboard:`在终端运行 xopc onboard(或 xopc onboard --gateway)并启用网页控制台,向导会打印访问令牌。`,stepPaste:`将访问令牌粘贴到下方并保存。也可直接打开向导给出的带 ?token= 的链接。`,stepUrlHint:`若使用带 ?token= 的链接打开,访问令牌会自动保存(随后地址栏会去掉参数)。`,docsGatewayLink:`网关说明`},electron:{setupBannerTitle:`完成设置后即可对话`,setupBannerBody:`请至少配置一家模型服务商的 API 密钥,并选择默认模型。之后可随时在设置中修改。`,setupBannerLinkProviders:`服务商与密钥`,setupBannerLinkModels:`默认模型`,setupBannerDismiss:`不再提示`,gatewayExitTitle:`本地网关已停止`,gatewayExitBody:`助手后端进程异常退出,请重启应用后再试。`},connection:{connecting:`连接中…`,online:`在线`,reconnecting:`重连中…`,offline:`离线`,error:`连接异常`,reconnect:`重连`},api:{errorBadGateway:`网关错误 (502)`,errorServiceUnavailable:`服务不可用 (503)`,errorGatewayTimeout:`网关超时 (504)`,errorInternal:`服务器内部错误 (500)`,errorServer:`服务器错误 ({{status}})`,errorNotFound:`未找到 (404)`,errorForbidden:`禁止访问 (403)`,errorRequest:`请求失败 ({{status}})`},sidebar:{newTask:`新建对话`,moreApps:`更多应用`,moreAppsAria:`更多应用`,navDragHandle:`拖动调整顺序`,tasksHeading:`对话`,viewAllSessions:`全部会话`,taskListEmpty:`暂无会话`,taskListNeedToken:`保存网关访问令牌后即可在此查看最近会话。`,taskListAddToken:`填写访问令牌`,taskListStartChat:`开始对话`,appMenuAria:`应用菜单与设置`,taskSessionMenuAria:`会话操作`,taskSessionAgentRunning:`助手仍在回复中`,taskRename:`重命名`,taskCopyChatId:`复制会话 ID`,taskChatIdCopied:`会话 ID 已复制`,taskDeleteTask:`删除对话`,taskRenameTitle:`重命名对话`,taskRenamePlaceholder:`会话名称`,taskRenameSave:`保存`,taskRenameCancel:`取消`,backToApp:`返回应用`,backToAgents:`返回智能体`,back:`返回`,helpDocs:`帮助文档`,sessionChannelFilterAria:`按来源筛选:网页对话或消息通道`,sessionTasksTab:`对话`,sessionChannelsTab:`消息通道`,resizeHandleAria:`调整左侧导航宽度`},aboutDialog:{windowTitle:`关于本应用`,close:`关闭`,versionLabel:`版本`,commitLabel:`提交`,buildDateLabel:`时间`,gatewayVersionLabel:`网关`,consoleBuildHint:`以上为控制台界面构建信息;网关为当前运行的 xopc 服务版本。`,checkUpdates:`检查更新`,checkUpdatesChecking:`检查中...`,checkUpdatesUpToDate:`已是最新版本`,checkUpdatesAvailable:`有新版本:v{version}`,checkUpdatesDownloading:`下载中... {percent}%`,checkUpdatesDownloaded:`已下载,可安装:v{version}`,checkUpdatesError:`检查失败`,gatewayUnavailable:`—`,openSourceLead:`本软件离不开 `,openSourceLink:`开源软件`,copyright:`版权所有 © {year} xopcai`},updatePanel:{restartToUpdate:`重启以更新`,dismissAria:`关闭`,dismissHint:`不再提醒此版本`,reminderElectronReady:`新版本 v{{version}} 已就绪,重启应用以安装。`,reminderDownloading:`正在下载更新… {{percent}}%`,reminderElectronUpdateError:`桌面版更新失败:{{detail}}`,reminderNpm:`网关有新版本 v{{version}} 可用。`,updateNow:`立即更新`,updateRunning:`正在更新…`,updateSuccess:`已安装更新`,updateSuccessDetail:`请重启网关以使用新版本(例如:xopc gateway restart)。`,updateErrorGit:`无法一键更新`,updateErrorBusy:`已有更新任务在进行中`,updateErrorFailed:`更新失败`,restartRequired:`已安装 v{{version}}。请重启网关以使用新版本。`,restartGateway:`重启网关`,restartPolling:`网关正在重启,等待恢复中…`,restartPollTimeout:`网关在预期时间内未响应,可能仍在启动中。`,restartPollRetry:`重试`},commandPalette:{groups:{navigate:`导航`,quickSettings:`快捷设置`,extensions:`扩展`,sessions:`会话`,files:`文件`,commands:`命令`,skills:`技能`,actions:`操作`},routes:{chatSubtitle:`打开聊天`,agentsSubtitle:`管理智能体`,appsSubtitle:`扩展应用`,sessionsSubtitle:`管理与搜索会话`,logsSubtitle:`网关诊断日志`,skillsSubtitle:`管理技能`,channelsSubtitle:`消息通道设置`,cronSubtitle:`定时任务与调度`,cronSettingsSubtitle:`定时任务调度引擎全局设置`,goalsSettingsSubtitle:`/goal 目标评判默认配置`,dreamsSettingsSubtitle:`记忆整合(梦境)调度`,settingsSubtitle:`打开设置`,credentialsSubtitle:`对话、搜索、图像与语音 API 密钥`,providersSubtitle:`LLM 服务商密钥与 OAuth`,modelsSubtitle:`模型配置`,voiceSubtitle:`语音设置`,gatewaySubtitle:`网关设置`,agentDefaultsSubtitle:`智能体默认配置`},quickSettings:{switchModel:`切换模型`,switchModelSubtitle:`更改默认 AI 模型`,switchAgent:`切换智能体`,switchAgentSubtitle:`更改新对话使用的智能体`,themeLight:`切换到浅色主题`,themeDark:`切换到深色主题`,themeSystem:`使用系统主题`,appearanceSubtitle:`外观`,languageSubtitle:`语言`,languageEn:`切换到 English`,languageZh:`切换到中文`},actions:{createCron:`创建定时任务`,createCronSubtitle:`新建 Cron 任务`,manageCron:`管理定时任务`,manageCronSubtitle:`查看和编辑 Cron`,manageSkills:`管理技能`,manageSkillsSubtitle:`启用或禁用技能`,reloadSkills:`重新加载技能`,reloadSkillsSubtitle:`从磁盘重新加载`}},clipboard:{copy:`复制`,copied:`已复制!`,copyFailed:`无法复制到剪贴板,文本已选中,请按 Ctrl/Cmd+C 手动复制。`}},Xe={sharesSettings:{title:`文件分享`,subtitle:`管理工作目录文件的临时公开下载链接。`,tabShares:`分享`,tabPolicy:`分享策略`,tabsAria:`文件分享配置标签`,needToken:`请先使用网关访问令牌登录,再管理文件分享。`,emptyState:`暂无分享链接。可从文件树创建,也可以通过 API 创建。`,createTitle:`创建分享`,createHint:`从工作区选择要分享的文件或目录,生成可分享的下载链接。`,pathLabel:`文件 / 目录`,pathPlaceholder:`如 reports/monthly.pdf`,pathBrowse:`选择…`,pathBrowseChange:`更改`,pathPickedFile:`已选文件`,pathPickedDirectory:`已选目录`,pickerTitle:`选择要分享的内容`,pickerConfirm:`确定`,pickerAgentLabel:`Agent`,pickerHintNone:`点选文件或目录后即可确认`,pickerHintNeedsFile:`请选择一个文件`,pickerHintNeedsDirectory:`请选择一个目录`,directoryModeLabel:`目录模式`,directoryModeBrowse:`可浏览目录`,directoryModeZipOnly:`仅 ZIP 下载`,ttlLabel:`有效期`,ttlOptions:{"1h":`1 小时`,"6h":`6 小时`,"24h":`24 小时`,"3d":`3 天`,"7d":`7 天`},maxViewsLabel:`最大下载次数`,maxViewsUnlimited:`不限`,descriptionLabel:`备注(可选)`,descriptionPlaceholder:`给接收者的简短说明`,createButton:`生成链接`,creating:`创建中…`,shareCreated:`分享链接已生成`,copyUrl:`复制链接`,copy:`复制`,publicUrlLabel:`公网(FRP)`,lanUrlLabel:`内网`,localUrlLabel:`本机`,expiresLabel:`过期时间`,copied:`已复制!`,copyFailed:`无法复制到剪贴板,请手动选择链接复制。`,listTitle:`活跃的分享`,allSharesTitle:`全部分享`,showExpired:`显示已过期/已撤销`,hideExpired:`隐藏已过期/已撤销`,fileName:`文件`,status:`状态`,statusActive:`有效`,statusExpired:`已过期`,statusRevoked:`已撤销`,statusFileGone:`文件已删除`,views:`下载次数`,viewsOf:`/`,expiresAt:`过期时间`,createdAt:`创建时间`,revoke:`撤销`,revokeConfirmTitle:`撤销分享?`,revokeConfirmBody:`此链接将立即失效,且无法恢复。`,revokeConfirmLabel:`撤销`,batchRevoke:`批量撤销`,cleanExpired:`清理过期`,cleanExpiredConfirmTitle:`清理过期分享?`,cleanExpiredConfirmBody:`这将永久撤销所有已过期和已撤销的分享记录。`,cleanExpiredConfirmLabel:`清理`,extend:`续期`,extendTitle:`延长有效期`,extendBy:`延长`,reachability:`可达性`,reachPublic:`公网可达(隧道已开启)`,reachLan:`仅局域网`,reachLocal:`仅本机`,reachLocalHint:`前往「远程访问」开启隧道后,分享链接即可从公网访问。`,noShareUrl:`外部不可达`,openTunnel:`打开远程访问`,loading:`加载中…`,error:`加载分享列表失败`,retry:`重试`,cancel:`取消`,policyTitle:`分享策略`,policyHint:`配置临时文件下载链接的限制与默认值。`,policyEnabled:`启用文件分享`,policyDefaultTtlHours:`默认过期时间(小时)`,policyDefaultTtlHint:`新建分享的默认 TTL(1–168 小时)。`,policyMaxTtlDays:`最长过期时间(天)`,policyMaxTtlHint:`创建或延长分享时的上限(1–30 天)。`,policyMaxActiveShares:`最大活跃分享数`,policyMaxActiveSharesHint:`允许同时存在的未过期分享数量(1–10,000)。`,policyMaxFileSizeMb:`最大文件大小(MB)`,policyMaxFileSizeHint:`创建分享时的单文件上限(1 MB–10 GB)。`,policyInlinePreviewMimes:`内联预览 MIME 类型`,policyInlinePreviewMimesHint:`允许通过 ?inline=1 在浏览器内预览的 MIME 类型。`,policyMimePlaceholder:`输入 MIME 类型后按 Enter(如 image/png)`,policySave:`保存策略`,policyDiscard:`放弃`,policySaving:`保存中…`,policySaved:`策略已保存`,policySaveError:`保存分享策略失败`,policyUnsaved:`有未保存的策略更改。`,policyRestartHint:`策略更改需要重启网关后生效。`,policyLoading:`加载分享策略中…`}},Ze={tunnelSettings:{title:`远程访问`,subtitle:`通过公网隧道,让手机 App 在外网也能连接本机网关。默认关闭以保护安全。`,needToken:`请先使用有效的网关访问令牌登录,再管理远程访问。`,riskBannerTitle:`安全提示`,riskBannerBody:`远程访问会把本机网关暴露到公网。仅在充分理解风险后开启。`,emptyStateTitle:`获取公网 HTTPS 地址`,emptyStateBody:`开启远程访问后,可从手机或任意网络连接此网关。`,publicUrlLabel:`公网地址`,showOptions:`更多选项`,hideOptions:`收起选项`,showAdvanced:`高级设置`,hideAdvanced:`收起高级设置`,pairWaitingForTunnel:`请先在上方开启远程访问,再在此扫描二维码配对移动 App。`,consentExpiredBanner:`远程访问安全说明已更新。请重新确认后再开启隧道或启用「启动时自动开启」。`,statusTitle:`状态`,loading:`正在加载隧道状态…`,statusConnected:`已连接`,statusConnecting:`连接中…`,statusReconnecting:`重新连接中…`,statusPreparingFrpc:`准备 frpc…`,statusRegistering:`注册隧道…`,statusProvisioningTls:`申请 HTTPS 证书…`,statusStartingFrpc:`连接 frp 服务器…`,statusError:`错误`,statusOff:`未开启`,frpcDownloading:`正在下载 frpc…`,frpcDownloadingPercent:`正在下载 frpc… {{percent}}%`,frpcDownloadingBytes:`正在下载 frpc… {{received}}`,frpcDownloadingUrlLabel:`下载地址`,frpcExtracting:`正在解压 frpc…`,startProgressTitle:`启动进度`,startProgressHint:`首次开启可能需要 2–4 分钟(DNS 传播 + HTTPS 证书)。DNS 验证失败会自动重试一次。公网地址会先显示,但隧道尚未完全就绪。`,startProgressElapsed:`当前步骤已进行 {{elapsed}}`,publicUrlPendingNotice:`公网地址已分配,请等待剩余步骤完成后再从外网访问。`,stepPrepareFrpc:`准备 frpc 客户端`,stepRegister:`向 Broker 注册`,stepRegisterDetail:`公网地址已分配,仍在申请 HTTPS 并连接 frp`,stepTls:`申请 HTTPS 证书`,stepTlsDetail:`正在为子域申请 TLS 证书`,stepTlsChecking:`检查已有证书`,stepTlsDnsChallenge:`发布 DNS 验证记录`,stepTlsDnsPropagation:`等待 DNS 在全球解析器生效(约 2–4 分钟)`,stepTlsCaValidation:`等待证书机构验证`,stepTlsIssuing:`签发证书中`,stepFrpcLogin:`连接 frpc 到 frp 服务器`,stepFrpcDetail:`等待 frpc 登录(最多约 60 秒)`,stepReconnectDetail:`frpc 中断后正在重连`,uptime:`运行时间`,lanHint:`若需同时生成局域网 + 隧道双地址 QR,请在「网关」设置中将 host 设为 0.0.0.0。`,pairTitle:`移动应用配对`,pairSubtitle:`使用移动客户端扫描后连接网关:应用会用一次性配对密钥换取访问令牌。`,pairTunnelActive:`远程访问已开启。二维码包含隧道地址、可用时的局域网地址,以及一次性配对密钥。`,pairBaseUrlLabel:`配对用的网关地址`,pairBaseUrlHint:`请填写手机能访问的地址(例如局域网 IP 与端口),可能与桌面浏览器当前地址不一致。`,pairBaseUrlPlaceholder:`http://192.168.x.x:28790`,pairBlockedTitle:`本机 localhost 尚无法配对`,pairBlockedLoopbackBody:`网关目前只监听本机(127.0.0.1),手机无法访问该地址。请先将网关暴露到局域网并使用下方 LAN 地址,或开启下方远程访问通过隧道配对。`,pairBlockedNextSteps:`或在下方开启远程访问,通过隧道配对。`,pairEnableLanButton:`开启局域网配对`,pairEnableLanConfirmTitle:`在局域网上暴露网关?`,pairEnableLanConfirmBody:`将把网关监听地址设为局域网(0.0.0.0)并重启网关。同一局域网内获得配对二维码或令牌的人可能访问你的助手。请仅在可信网络下继续。`,pairEnableLanEnabling:`正在开启局域网配对…`,pairEnableLanSecurityAuditLink:`查看网关安全审计`,pairSuggestedLanLabel:`本机检测到的局域网地址`,pairUseSuggestedUrl:`使用建议地址`,pairCandidatesTitle:`检测到的局域网地址`,pairSelectCandidateTitle:`选择局域网地址`,pairSelectCandidateHint:`请选择手机在本网络能访问的地址。移动应用可在配对前通过 GET /api/tunnel/pair/ping 探测连通性。`,pairMobileProbeHint:`移动应用:手动地址先用 POST /api/tunnel/pair/validate-url 校验,再用 GET /api/tunnel/pair/ping 探测,最后通过 POST /api/tunnel/exchange-token 用 ps 换取 token。`,pairQrDisabled:`在手机无法访问网关前,暂不提供可扫描的二维码。`,pairLocalhostWarning:`当前地址看起来像本机 localhost。局域网内的手机默认无法直连,请在网关监听局域网并改用 http://<本机局域网IP>:<端口>。`,pairSecurityNote:`二维码含一次性配对密钥(5 分钟有效、单次使用)。请在可信环境中展示,留意周围摄像头与他人。`,pairEncoding:`生成二维码中…`,pairImageError:`无法生成二维码,可复制配对链接。`,pairCopyLink:`复制配对链接`,pairCopied:`已复制配对链接`,pairSchemeHint:`应用注册的格式:xopc://gateway/mobile-connect?baseUrl=…&ps=…(通过 POST /api/tunnel/exchange-token 用 ps 换取 token)`,pairInvalidBaseUrl:`请输入以 http:// 或 https:// 开头的完整网关地址(无需路径)。`,pairTunnelPublicUrl:`隧道地址`,pairTunnelLanUrl:`局域网地址(已写入二维码)`,start:`开启远程访问`,stop:`断开连接`,release:`释放公网地址`,releaseHint:`在 Broker 上注销子域;下次开启将获得新的公网 URL。`,releaseConfirmTitle:`释放公网地址?`,releaseConfirmBody:`将在 frp.xopc.ai 注销隧道并清除本地凭证;再次开启远程访问时会分配新的子域。`,releaseConfirmLabel:`释放`,copyUrl:`复制公网地址`,copied:`已复制`,refreshQr:`刷新二维码`,optionsTitle:`选项`,autoStart:`网关启动时自动开启隧道`,autoStartHint:`需先成功开启一次远程访问并接受安全说明。`,autoStartConfirmTitle:`每次启动网关都开启隧道?`,autoStartConfirmBody:`只要网关在运行,就可能从公网访问。请确认你能接受该风险。`,autoStartConfirmLabel:`启用自动开启`,consentTitle:`开启远程访问`,consentIntro:`在暴露网关之前请仔细阅读:`,consentBullet1:`公网 URL 可能被他人用来访问你的网关 Bearer 令牌。`,consentBullet2:`流量经 frp.xopc.ai 转发(第三方基础设施)。`,consentBullet3:`请使用强令牌;不需要远程访问时请关闭隧道。`,consentCheckbox:`我已理解上述风险,并希望开启远程访问`,consentConfirm:`接受并开启`,consentReconfirm:`接受并继续`,consentCancel:`取消`,deeplinkTitle:`深链内容`,brokerNote:`流量经 frp.xopc.ai 转发,请妥善保管网关访问令牌。`,brokerDocsLink:`公网隧道安全文档`,brokerSecretTitle:`Tunnel Registration Key`,brokerSecretStepTitle:`步骤 1 · Tunnel Registration Key`,brokerSecretHint:`在 xopc Console 创建 Tunnel Registration Key,粘贴到下方并保存。密钥通过 X-Registration-Secret 向 frp.xopc.ai 注册,保存在本机 xopc.json 中。`,brokerSecretConsoleLink:`在 Console 创建 Tunnel Registration Key`,brokerSecretEnvHint:`当前通过旧版环境变量 XOPC_TUNNEL_REGISTRATION_SECRET 提供(优先级高于下方配置)。建议在 Console 创建新密钥并保存到此处后移除该环境变量。`,brokerSecretMaskedHelp:`密钥已保存在本机配置中。可查看、复制,或重新配置。`,brokerSecretPlaceholder:`粘贴 Tunnel Registration Key`,brokerSecretPlaceholderKeep:`粘贴新的 Tunnel Registration Key`,brokerSecretMissingHint:`请先在 Console 创建密钥,再粘贴到此处并保存。`,brokerSecretRequiredBeforeStart:`请先保存上方的 Tunnel Registration Key,再启动远程访问。`,brokerSecretSave:`保存密钥`,brokerSecretSaveAndContinue:`保存并继续`,brokerSecretClear:`清除已保存密钥`,brokerSecretSaved:`Tunnel Registration Key 已保存`,brokerSecretCleared:`已清除保存的 Tunnel Registration Key`,brokerSecretReadyTitle:`Tunnel Registration Key 已配置`,brokerSecretReadyHint:`可在下方启动远程访问;需要更换密钥时点击「重新配置」。`,brokerSecretReconfigure:`重新配置`,brokerSecretCancelReconfigure:`取消`,brokerSecretRevealFailed:`无法读取已保存的密钥`,brokerSecretNotInConfigFile:`密钥不在配置文件中,无法显示明文。`,copyKey:`复制密钥`,showKey:`显示密钥`,hideKey:`隐藏密钥`,flowStepStart:`步骤 2 · 启动远程访问`}},Qe={skills:{title:`技能`,needToken:`请先保存网关访问令牌后再管理技能。`,tagline:`安装和管理技能,让 xopc 在对话中完成更多任务。`,refresh:`刷新列表`,reloadRuntime:`从磁盘重载`,reloadDiskAria:`从磁盘重载技能`,skillsNavAria:`技能分区`,tabBuiltin:`内置`,tabUser:`用户安装`,tabMarketplace:`技能广场`,marketplacePlaceholder:`技能广场即将上线,敬请期待。`,sectionMarketplace:`技能商店`,marketplaceBrowseSkillhub:`SkillHub`,marketplaceBrowseClawhub:`ClawHub`,marketplaceBrowseStore:`XOPC 商店`,marketplaceBrowseSwitchAria:`技能广场来源`,marketplaceResultsTabsAria:`搜索结果来源`,marketplaceResultsTabAll:`全部`,marketplaceSortLabel:`排序`,marketplaceSortDownloads:`下载最多`,marketplaceSortNewest:`最新`,marketplaceCategoryAll:`全部`,marketplaceCategoriesAria:`技能市场分类`,marketplaceCategoriesFailed:`分类加载失败`,marketplaceSearchPackages:`搜索技能名称、描述或标签…`,marketplaceStars:`收藏`,marketplaceSource:`源自`,marketplaceLoadFailed:`无法加载技能市场`,marketplaceEmpty:`没有找到匹配的技能。`,marketplaceEmptySearch:`没有找到匹配「{{query}}」的技能。`,marketplaceEmptySearchTryProvider:`在 {{provider}} 中搜索`,marketplaceEmptySearchClear:`清除搜索`,marketplaceInstall:`安装`,previewUseInChat:`使用`,previewUseInChatBusy:`安装中…`,marketplaceReinstall:`重新安装`,marketplaceInstalled:`已安装`,marketplaceReinstallConfirm:`该技能已安装。是否用商店中的版本覆盖本地?`,marketplacePagePrev:`上一页`,marketplacePageNext:`下一页`,marketplacePageStatus:`第 {{page}} / {{totalPages}} 页 · 共 {{total}} 个技能`,marketplaceAuthor:`作者`,marketplaceOpenOnSkillhub:`在 SkillHub 打开`,marketplaceOpenOnSkillhubAria:`在新标签页打开 skillhub.cn 上的该技能`,marketplaceOpenExternal:`在源站打开`,marketplaceOpenExternalAria:`在新标签页打开该技能的源站页面`,marketplaceDownloads:`下载`,marketplaceVersion:`最新版本`,sectionBuiltinList:`内置技能`,categoryLabel:{business:`创业与商业`,creative:`创意与设计`,documents:`文档处理`,engineering:`工程与研发`,tools:`工具与实用程序`},filterAll:`全部`,filterDisabledOnly:`仅停用 ({{count}})`,filterDisabledOnlyAria:`只显示已停用的技能`,statusDisabled:`已停用`,statusEnabled:`已启用`,noDisabledSkills:`当前列表中没有停用的技能。`,filterGlobal:`全局`,filterWorkspace:`工作区`,filterExtra:`扩展`,sectionUser:`已安装`,installCta:`安装技能`,installModalTitle:`安装技能`,installModalDropHint:`拖放 .zip 或 SKILL.md 文件,或点击选择`,installModalReqTitle:`文件要求`,installModalReq1:`包含 SKILL.md 文件的 .zip 压缩包`,installModalReq2:`或直接拖入 SKILL.md 文件`,installAction:`安装`,installClose:`关闭`,searchPlaceholder:`搜索技能`,noSearchResults:`没有匹配的技能。`,uploading:`上传中…`,loading:`加载中…`,empty:`暂无技能。`,loadFailed:`加载技能失败`,reloadFailed:`重载失败`,skillToggleFailed:`更新技能状态失败`,uploadFailed:`上传失败`,installSuccess:`技能已安装。`,zipOnly:`请选择 .zip 文件`,invalidFile:`请选择 .zip 或 SKILL.md 文件`,delete:`删除`,deleteTitle:`删除技能`,deleteMessage:`确定删除已管理技能目录「{{id}}」?此操作不可恢复。`,deleteConfirm:`删除`,deleteFailed:`删除失败`,yes:`是`,no:`否`,cancel:`取消`,source:{builtin:`内置`,workspace:`工作区`,global:`全局`,extra:`扩展`},col:{name:`名称`,description:`描述`,source:`来源`,managed:`可管理`,actions:`操作`},detailModalBanner:`元数据来自 SKILL.md 的 YAML frontmatter;下方为去掉该段后的正文说明。`,detailModalBannerStore:`以下为技能商店中该包发布的 Markdown 正文(与商店中的包说明一致)。`,detailSummaryHeading:`概要`,detailInstructionsHeading:`使用说明`,detailNoInstructionsBody:`该技能暂无详细说明。`,detailHomepageLabel:`主页`,detailPlatformsLabel:`适用平台`,detailRequiresLabel:`运行要求`,detailRequiresBins:`依赖命令`,detailRequiresEnv:`环境变量`,detailRequiresAnyBins:`满足其一即可的命令`,detailInstallLabel:`安装步骤`,detailToolGatingLabel:`工具可见性`,detailToolsRequiresList:`依赖工具`,detailToolsetsRequiresList:`依赖工具集`,detailToolsFallbackList:`备用工具`,detailToolsetsFallbackList:`备用工具集`,detailEnvVarsLabel:`会话环境变量`,detailNotInjectedNote:`该技能不会注入到模型上下文(disable-model-invocation)。`,marketplaceNoReadme:`该技能暂无说明正文。`,detailModalEnable:`启用`,detailModalDisable:`停用`,useRequiresEnabled:`请先启用该技能后再使用`,detailLoadFailed:`无法加载 SKILL.md`,detailCloseAria:`关闭`,hubRemote:`远程`,hubKindGit:`git`,hubKindArchive:`归档`},skillsMarketplaceSettings:{title:`市场来源`,hint:`技能市场标签页的默认提供商与商店 API 基础 URL。`,save:`保存`,discard:`放弃`,saving:`保存中…`,saveError:`保存市场设置失败`,provider:`提供商`,providerHint:`默认浏览的目录(store、skillhub、clawhub)。`,storeBaseUrl:`商店基础 URL`,storeBaseUrlHint:`包列表 REST 基础地址。可用环境变量 XOPC_SKILLS_STORE_URL 覆盖。`}},$e={workspace:{title:`项目文件`,currentWorkspace:`当前工作区`,openFiles:`项目文件`,preview:`预览`,download:`下载`,copyPath:`复制路径`,pathCopied:`路径已复制`,edit:`编辑`,viewing:`查看中`,saved:`已保存`,saving:`保存中…`,emptyDir:`暂无文件`,loadError:`加载失败`,close:`关闭`,resizeHandleAria:`调整项目文件区域宽度`,lastModified:`修改时间`,openElsewhereHint:`预览可能受限或不可用。请下载文件或使用其他应用打开。`,cannotPreviewType:`无法在预览中打开此类型的文件。`,openSystemApp:`用默认应用打开`,revealInFolder:`打开所在目录`,shareLink:`分享链接`,sharing:`正在创建分享…`,shareFailed:`创建分享链接失败`}},Z={...Se,...Ce,...we,...Te,...Ee,...De,...Oe,...ke,...Ae,...je,...Me,...Ne,...Pe,...Fe,...Ie,...Le},Q={...Re,...ze,...Be,...Ve,...He,...Ue,...We,...Ge,...Ke,...qe,...Je,...Ye,...Xe,...Ze,...Qe,...$e};U.use(ge).init({resources:{en:{translation:Z},zh:{translation:Q}},lng:X(),fallbackLng:`en`,interpolation:{escapeValue:!1},react:{useSuspense:!1}});var et={en:Z,zh:Q};function tt(e){return et[e]}function nt(e,t){let n=tt(e);return t===`settingsAgents`?n.nav.agents:t===`settingsAgentDefaults`?n.nav.settingsAgentChat:n.nav[t]}var rt=e=>{let t,n=new Set,r=(e,r)=>{let i=typeof e==`function`?e(t):e;if(!Object.is(i,t)){let e=t;t=r??(typeof i!=`object`||!i)?i:Object.assign({},t,i),n.forEach(n=>n(t,e))}},i=()=>t,a={setState:r,getState:i,getInitialState:()=>o,subscribe:e=>(n.add(e),()=>n.delete(e))},o=t=e(r,i,a);return a},it=(e=>e?rt(e):rt),at=e=>e;function ot(e,t=at){let r=n.useSyncExternalStore(e.subscribe,n.useCallback(()=>t(e.getState()),[e,t]),n.useCallback(()=>t(e.getInitialState()),[e,t]));return n.useDebugValue(r),r}var st=e=>{let t=it(e),n=e=>ot(t,e);return Object.assign(n,t),n},$=(e=>e?st(e):st),ct=$(e=>({language:X(),setLanguage:t=>{xe(t),document.documentElement.setAttribute(`lang`,q(t)),U.changeLanguage(t),e({language:t})}}));function lt(){return window.location.origin}function ut(e){let t=e.startsWith(`/`)?e:`/${e}`;return`${lt()}${t}`}function dt(e){let t=e.baseUrl.trim().replace(/\/+$/,``),n=new URL(`xopc://gateway/mobile-connect`);return n.searchParams.set(`baseUrl`,t),e.lanUrl?.trim()&&n.searchParams.set(`lanUrl`,e.lanUrl.trim().replace(/\/+$/,``)),n.searchParams.set(`ps`,e.pairingSecret),n.toString()}function ft(e){try{let t=new URL(e.trim());if(t.protocol!==`http:`&&t.protocol!==`https:`)return!1;let n=t.hostname.toLowerCase();return!!(n===`localhost`||n===`127.0.0.1`||n===`[::1]`||n===`::1`||/^127\.\d+\.\d+\.\d+$/.test(n))}catch{return!1}}export{$ as a,be as c,ye as d,q as f,U as h,ct as i,X as l,pe as m,dt as n,tt as o,he as p,ft as r,nt as s,ut as t,ve as u};