ysk-omni 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1140) hide show
  1. package/.env.example +80 -0
  2. package/LICENSE +21 -0
  3. package/README-ZH.md +51 -0
  4. package/README.md +41 -0
  5. package/dist/app.d.ts +3 -0
  6. package/dist/app.d.ts.map +1 -0
  7. package/dist/app.js +277 -0
  8. package/dist/app.js.map +1 -0
  9. package/dist/catalog/curated.d.ts +14 -0
  10. package/dist/catalog/curated.d.ts.map +1 -0
  11. package/dist/catalog/curated.js +30 -0
  12. package/dist/catalog/curated.js.map +1 -0
  13. package/dist/cli/commands/admin-otp.d.ts +10 -0
  14. package/dist/cli/commands/admin-otp.d.ts.map +1 -0
  15. package/dist/cli/commands/admin-otp.js +82 -0
  16. package/dist/cli/commands/admin-otp.js.map +1 -0
  17. package/dist/cli/commands/admin-panel.d.ts +13 -0
  18. package/dist/cli/commands/admin-panel.d.ts.map +1 -0
  19. package/dist/cli/commands/admin-panel.js +98 -0
  20. package/dist/cli/commands/admin-panel.js.map +1 -0
  21. package/dist/cli/commands/admin-sessions.d.ts +6 -0
  22. package/dist/cli/commands/admin-sessions.d.ts.map +1 -0
  23. package/dist/cli/commands/admin-sessions.js +62 -0
  24. package/dist/cli/commands/admin-sessions.js.map +1 -0
  25. package/dist/cli/commands/api-features.d.ts +8 -0
  26. package/dist/cli/commands/api-features.d.ts.map +1 -0
  27. package/dist/cli/commands/api-features.js +136 -0
  28. package/dist/cli/commands/api-features.js.map +1 -0
  29. package/dist/cli/commands/audit.d.ts +7 -0
  30. package/dist/cli/commands/audit.d.ts.map +1 -0
  31. package/dist/cli/commands/audit.js +48 -0
  32. package/dist/cli/commands/audit.js.map +1 -0
  33. package/dist/cli/commands/catalog.d.ts +26 -0
  34. package/dist/cli/commands/catalog.d.ts.map +1 -0
  35. package/dist/cli/commands/catalog.js +223 -0
  36. package/dist/cli/commands/catalog.js.map +1 -0
  37. package/dist/cli/commands/chats.d.ts +10 -0
  38. package/dist/cli/commands/chats.d.ts.map +1 -0
  39. package/dist/cli/commands/chats.js +97 -0
  40. package/dist/cli/commands/chats.js.map +1 -0
  41. package/dist/cli/commands/conversations.d.ts +10 -0
  42. package/dist/cli/commands/conversations.d.ts.map +1 -0
  43. package/dist/cli/commands/conversations.js +68 -0
  44. package/dist/cli/commands/conversations.js.map +1 -0
  45. package/dist/cli/commands/ddos.d.ts +18 -0
  46. package/dist/cli/commands/ddos.d.ts.map +1 -0
  47. package/dist/cli/commands/ddos.js +298 -0
  48. package/dist/cli/commands/ddos.js.map +1 -0
  49. package/dist/cli/commands/docs.d.ts +13 -0
  50. package/dist/cli/commands/docs.d.ts.map +1 -0
  51. package/dist/cli/commands/docs.js +104 -0
  52. package/dist/cli/commands/docs.js.map +1 -0
  53. package/dist/cli/commands/doctor.d.ts +6 -0
  54. package/dist/cli/commands/doctor.d.ts.map +1 -0
  55. package/dist/cli/commands/doctor.js +207 -0
  56. package/dist/cli/commands/doctor.js.map +1 -0
  57. package/dist/cli/commands/key.d.ts +42 -0
  58. package/dist/cli/commands/key.d.ts.map +1 -0
  59. package/dist/cli/commands/key.js +192 -0
  60. package/dist/cli/commands/key.js.map +1 -0
  61. package/dist/cli/commands/logs.d.ts +19 -0
  62. package/dist/cli/commands/logs.d.ts.map +1 -0
  63. package/dist/cli/commands/logs.js +104 -0
  64. package/dist/cli/commands/logs.js.map +1 -0
  65. package/dist/cli/commands/migrate.d.ts +5 -0
  66. package/dist/cli/commands/migrate.d.ts.map +1 -0
  67. package/dist/cli/commands/migrate.js +25 -0
  68. package/dist/cli/commands/migrate.js.map +1 -0
  69. package/dist/cli/commands/models.d.ts +5 -0
  70. package/dist/cli/commands/models.d.ts.map +1 -0
  71. package/dist/cli/commands/models.js +68 -0
  72. package/dist/cli/commands/models.js.map +1 -0
  73. package/dist/cli/commands/open.d.ts +7 -0
  74. package/dist/cli/commands/open.d.ts.map +1 -0
  75. package/dist/cli/commands/open.js +24 -0
  76. package/dist/cli/commands/open.js.map +1 -0
  77. package/dist/cli/commands/queue.d.ts +33 -0
  78. package/dist/cli/commands/queue.d.ts.map +1 -0
  79. package/dist/cli/commands/queue.js +467 -0
  80. package/dist/cli/commands/queue.js.map +1 -0
  81. package/dist/cli/commands/restart.d.ts +8 -0
  82. package/dist/cli/commands/restart.d.ts.map +1 -0
  83. package/dist/cli/commands/restart.js +36 -0
  84. package/dist/cli/commands/restart.js.map +1 -0
  85. package/dist/cli/commands/runtimes.d.ts +9 -0
  86. package/dist/cli/commands/runtimes.d.ts.map +1 -0
  87. package/dist/cli/commands/runtimes.js +87 -0
  88. package/dist/cli/commands/runtimes.js.map +1 -0
  89. package/dist/cli/commands/seed.d.ts +5 -0
  90. package/dist/cli/commands/seed.d.ts.map +1 -0
  91. package/dist/cli/commands/seed.js +22 -0
  92. package/dist/cli/commands/seed.js.map +1 -0
  93. package/dist/cli/commands/settings.d.ts +13 -0
  94. package/dist/cli/commands/settings.d.ts.map +1 -0
  95. package/dist/cli/commands/settings.js +182 -0
  96. package/dist/cli/commands/settings.js.map +1 -0
  97. package/dist/cli/commands/setup.d.ts +6 -0
  98. package/dist/cli/commands/setup.d.ts.map +1 -0
  99. package/dist/cli/commands/setup.js +70 -0
  100. package/dist/cli/commands/setup.js.map +1 -0
  101. package/dist/cli/commands/start.d.ts +9 -0
  102. package/dist/cli/commands/start.d.ts.map +1 -0
  103. package/dist/cli/commands/start.js +140 -0
  104. package/dist/cli/commands/start.js.map +1 -0
  105. package/dist/cli/commands/stats.d.ts +3 -0
  106. package/dist/cli/commands/stats.d.ts.map +1 -0
  107. package/dist/cli/commands/stats.js +83 -0
  108. package/dist/cli/commands/stats.js.map +1 -0
  109. package/dist/cli/commands/status.d.ts +6 -0
  110. package/dist/cli/commands/status.d.ts.map +1 -0
  111. package/dist/cli/commands/status.js +70 -0
  112. package/dist/cli/commands/status.js.map +1 -0
  113. package/dist/cli/commands/stop.d.ts +11 -0
  114. package/dist/cli/commands/stop.d.ts.map +1 -0
  115. package/dist/cli/commands/stop.js +51 -0
  116. package/dist/cli/commands/stop.js.map +1 -0
  117. package/dist/cli/commands/update.d.ts +9 -0
  118. package/dist/cli/commands/update.d.ts.map +1 -0
  119. package/dist/cli/commands/update.js +182 -0
  120. package/dist/cli/commands/update.js.map +1 -0
  121. package/dist/cli/commands/version.d.ts +2 -0
  122. package/dist/cli/commands/version.d.ts.map +1 -0
  123. package/dist/cli/commands/version.js +16 -0
  124. package/dist/cli/commands/version.js.map +1 -0
  125. package/dist/cli/index.d.ts +3 -0
  126. package/dist/cli/index.d.ts.map +1 -0
  127. package/dist/cli/index.js +835 -0
  128. package/dist/cli/index.js.map +1 -0
  129. package/dist/cli/lib/auto-migrate.d.ts +14 -0
  130. package/dist/cli/lib/auto-migrate.d.ts.map +1 -0
  131. package/dist/cli/lib/auto-migrate.js +42 -0
  132. package/dist/cli/lib/auto-migrate.js.map +1 -0
  133. package/dist/cli/lib/db-keys.d.ts +51 -0
  134. package/dist/cli/lib/db-keys.d.ts.map +1 -0
  135. package/dist/cli/lib/db-keys.js +207 -0
  136. package/dist/cli/lib/db-keys.js.map +1 -0
  137. package/dist/cli/lib/env-file.d.ts +14 -0
  138. package/dist/cli/lib/env-file.d.ts.map +1 -0
  139. package/dist/cli/lib/env-file.js +143 -0
  140. package/dist/cli/lib/env-file.js.map +1 -0
  141. package/dist/cli/lib/paths.d.ts +27 -0
  142. package/dist/cli/lib/paths.d.ts.map +1 -0
  143. package/dist/cli/lib/paths.js +87 -0
  144. package/dist/cli/lib/paths.js.map +1 -0
  145. package/dist/cli/lib/pm2-runner.d.ts +14 -0
  146. package/dist/cli/lib/pm2-runner.d.ts.map +1 -0
  147. package/dist/cli/lib/pm2-runner.js +179 -0
  148. package/dist/cli/lib/pm2-runner.js.map +1 -0
  149. package/dist/cli/lib/print-table.d.ts +3 -0
  150. package/dist/cli/lib/print-table.d.ts.map +1 -0
  151. package/dist/cli/lib/print-table.js +29 -0
  152. package/dist/cli/lib/print-table.js.map +1 -0
  153. package/dist/cli/lib/print.d.ts +10 -0
  154. package/dist/cli/lib/print.d.ts.map +1 -0
  155. package/dist/cli/lib/print.js +28 -0
  156. package/dist/cli/lib/print.js.map +1 -0
  157. package/dist/cli/lib/process-mgr.d.ts +23 -0
  158. package/dist/cli/lib/process-mgr.d.ts.map +1 -0
  159. package/dist/cli/lib/process-mgr.js +207 -0
  160. package/dist/cli/lib/process-mgr.js.map +1 -0
  161. package/dist/cli/lib/run-prisma.d.ts +13 -0
  162. package/dist/cli/lib/run-prisma.d.ts.map +1 -0
  163. package/dist/cli/lib/run-prisma.js +99 -0
  164. package/dist/cli/lib/run-prisma.js.map +1 -0
  165. package/dist/cli/lib/runner-info.d.ts +20 -0
  166. package/dist/cli/lib/runner-info.d.ts.map +1 -0
  167. package/dist/cli/lib/runner-info.js +120 -0
  168. package/dist/cli/lib/runner-info.js.map +1 -0
  169. package/dist/cli/lib/runtime-context.d.ts +23 -0
  170. package/dist/cli/lib/runtime-context.d.ts.map +1 -0
  171. package/dist/cli/lib/runtime-context.js +60 -0
  172. package/dist/cli/lib/runtime-context.js.map +1 -0
  173. package/dist/cli/lib/seed-admin.d.ts +17 -0
  174. package/dist/cli/lib/seed-admin.d.ts.map +1 -0
  175. package/dist/cli/lib/seed-admin.js +80 -0
  176. package/dist/cli/lib/seed-admin.js.map +1 -0
  177. package/dist/cli/lib/spinner.d.ts +20 -0
  178. package/dist/cli/lib/spinner.d.ts.map +1 -0
  179. package/dist/cli/lib/spinner.js +72 -0
  180. package/dist/cli/lib/spinner.js.map +1 -0
  181. package/dist/config/constants.d.ts +143 -0
  182. package/dist/config/constants.d.ts.map +1 -0
  183. package/dist/config/constants.js +355 -0
  184. package/dist/config/constants.js.map +1 -0
  185. package/dist/config/cors.d.ts +3 -0
  186. package/dist/config/cors.d.ts.map +1 -0
  187. package/dist/config/cors.js +30 -0
  188. package/dist/config/cors.js.map +1 -0
  189. package/dist/config/database.d.ts +4 -0
  190. package/dist/config/database.d.ts.map +1 -0
  191. package/dist/config/database.js +18 -0
  192. package/dist/config/database.js.map +1 -0
  193. package/dist/config/env.d.ts +48 -0
  194. package/dist/config/env.d.ts.map +1 -0
  195. package/dist/config/env.js +163 -0
  196. package/dist/config/env.js.map +1 -0
  197. package/dist/config/omni-home.d.ts +3 -0
  198. package/dist/config/omni-home.d.ts.map +1 -0
  199. package/dist/config/omni-home.js +16 -0
  200. package/dist/config/omni-home.js.map +1 -0
  201. package/dist/controllers/admin/api-features.handlers.d.ts +6 -0
  202. package/dist/controllers/admin/api-features.handlers.d.ts.map +1 -0
  203. package/dist/controllers/admin/api-features.handlers.js +62 -0
  204. package/dist/controllers/admin/api-features.handlers.js.map +1 -0
  205. package/dist/controllers/admin/audit.handlers.d.ts +5 -0
  206. package/dist/controllers/admin/audit.handlers.d.ts.map +1 -0
  207. package/dist/controllers/admin/audit.handlers.js +79 -0
  208. package/dist/controllers/admin/audit.handlers.js.map +1 -0
  209. package/dist/controllers/admin/auth.handlers.d.ts +8 -0
  210. package/dist/controllers/admin/auth.handlers.d.ts.map +1 -0
  211. package/dist/controllers/admin/auth.handlers.js +56 -0
  212. package/dist/controllers/admin/auth.handlers.js.map +1 -0
  213. package/dist/controllers/admin/catalog.handlers.d.ts +10 -0
  214. package/dist/controllers/admin/catalog.handlers.d.ts.map +1 -0
  215. package/dist/controllers/admin/catalog.handlers.js +170 -0
  216. package/dist/controllers/admin/catalog.handlers.js.map +1 -0
  217. package/dist/controllers/admin/chats.handlers.d.ts +6 -0
  218. package/dist/controllers/admin/chats.handlers.d.ts.map +1 -0
  219. package/dist/controllers/admin/chats.handlers.js +22 -0
  220. package/dist/controllers/admin/chats.handlers.js.map +1 -0
  221. package/dist/controllers/admin/conversations.handlers.d.ts +9 -0
  222. package/dist/controllers/admin/conversations.handlers.d.ts.map +1 -0
  223. package/dist/controllers/admin/conversations.handlers.js +70 -0
  224. package/dist/controllers/admin/conversations.handlers.js.map +1 -0
  225. package/dist/controllers/admin/core.handlers.d.ts +13 -0
  226. package/dist/controllers/admin/core.handlers.d.ts.map +1 -0
  227. package/dist/controllers/admin/core.handlers.js +201 -0
  228. package/dist/controllers/admin/core.handlers.js.map +1 -0
  229. package/dist/controllers/admin/ddos.handlers.d.ts +13 -0
  230. package/dist/controllers/admin/ddos.handlers.d.ts.map +1 -0
  231. package/dist/controllers/admin/ddos.handlers.js +178 -0
  232. package/dist/controllers/admin/ddos.handlers.js.map +1 -0
  233. package/dist/controllers/admin/documents.handlers.d.ts +8 -0
  234. package/dist/controllers/admin/documents.handlers.d.ts.map +1 -0
  235. package/dist/controllers/admin/documents.handlers.js +207 -0
  236. package/dist/controllers/admin/documents.handlers.js.map +1 -0
  237. package/dist/controllers/admin/keys.handlers.d.ts +8 -0
  238. package/dist/controllers/admin/keys.handlers.d.ts.map +1 -0
  239. package/dist/controllers/admin/keys.handlers.js +84 -0
  240. package/dist/controllers/admin/keys.handlers.js.map +1 -0
  241. package/dist/controllers/admin/media.handlers.d.ts +27 -0
  242. package/dist/controllers/admin/media.handlers.d.ts.map +1 -0
  243. package/dist/controllers/admin/media.handlers.js +637 -0
  244. package/dist/controllers/admin/media.handlers.js.map +1 -0
  245. package/dist/controllers/admin/playground.handlers.d.ts +6 -0
  246. package/dist/controllers/admin/playground.handlers.d.ts.map +1 -0
  247. package/dist/controllers/admin/playground.handlers.js +76 -0
  248. package/dist/controllers/admin/playground.handlers.js.map +1 -0
  249. package/dist/controllers/admin/pm2.handlers.d.ts +15 -0
  250. package/dist/controllers/admin/pm2.handlers.d.ts.map +1 -0
  251. package/dist/controllers/admin/pm2.handlers.js +161 -0
  252. package/dist/controllers/admin/pm2.handlers.js.map +1 -0
  253. package/dist/controllers/admin/queue.handlers.d.ts +16 -0
  254. package/dist/controllers/admin/queue.handlers.d.ts.map +1 -0
  255. package/dist/controllers/admin/queue.handlers.js +159 -0
  256. package/dist/controllers/admin/queue.handlers.js.map +1 -0
  257. package/dist/controllers/admin/runtimes.handlers.d.ts +6 -0
  258. package/dist/controllers/admin/runtimes.handlers.d.ts.map +1 -0
  259. package/dist/controllers/admin/runtimes.handlers.js +54 -0
  260. package/dist/controllers/admin/runtimes.handlers.js.map +1 -0
  261. package/dist/controllers/admin/types.d.ts +7 -0
  262. package/dist/controllers/admin/types.d.ts.map +1 -0
  263. package/dist/controllers/admin/types.js +3 -0
  264. package/dist/controllers/admin/types.js.map +1 -0
  265. package/dist/controllers/admin.controller.d.ts +87 -0
  266. package/dist/controllers/admin.controller.d.ts.map +1 -0
  267. package/dist/controllers/admin.controller.js +58 -0
  268. package/dist/controllers/admin.controller.js.map +1 -0
  269. package/dist/controllers/anthropic.controller.d.ts +5 -0
  270. package/dist/controllers/anthropic.controller.d.ts.map +1 -0
  271. package/dist/controllers/anthropic.controller.js +37 -0
  272. package/dist/controllers/anthropic.controller.js.map +1 -0
  273. package/dist/controllers/api-key.controller.d.ts +7 -0
  274. package/dist/controllers/api-key.controller.d.ts.map +1 -0
  275. package/dist/controllers/api-key.controller.js +51 -0
  276. package/dist/controllers/api-key.controller.js.map +1 -0
  277. package/dist/controllers/assistants.controller.d.ts +13 -0
  278. package/dist/controllers/assistants.controller.d.ts.map +1 -0
  279. package/dist/controllers/assistants.controller.js +75 -0
  280. package/dist/controllers/assistants.controller.js.map +1 -0
  281. package/dist/controllers/audio.controller.d.ts +10 -0
  282. package/dist/controllers/audio.controller.d.ts.map +1 -0
  283. package/dist/controllers/audio.controller.js +43 -0
  284. package/dist/controllers/audio.controller.js.map +1 -0
  285. package/dist/controllers/chat.controller.d.ts +5 -0
  286. package/dist/controllers/chat.controller.d.ts.map +1 -0
  287. package/dist/controllers/chat.controller.js +34 -0
  288. package/dist/controllers/chat.controller.js.map +1 -0
  289. package/dist/controllers/document.controller.d.ts +8 -0
  290. package/dist/controllers/document.controller.d.ts.map +1 -0
  291. package/dist/controllers/document.controller.js +54 -0
  292. package/dist/controllers/document.controller.js.map +1 -0
  293. package/dist/controllers/files.controller.d.ts +12 -0
  294. package/dist/controllers/files.controller.d.ts.map +1 -0
  295. package/dist/controllers/files.controller.js +144 -0
  296. package/dist/controllers/files.controller.js.map +1 -0
  297. package/dist/controllers/health.controller.d.ts +6 -0
  298. package/dist/controllers/health.controller.d.ts.map +1 -0
  299. package/dist/controllers/health.controller.js +39 -0
  300. package/dist/controllers/health.controller.js.map +1 -0
  301. package/dist/controllers/images.controller.d.ts +6 -0
  302. package/dist/controllers/images.controller.d.ts.map +1 -0
  303. package/dist/controllers/images.controller.js +66 -0
  304. package/dist/controllers/images.controller.js.map +1 -0
  305. package/dist/controllers/media-assets.controller.d.ts +6 -0
  306. package/dist/controllers/media-assets.controller.d.ts.map +1 -0
  307. package/dist/controllers/media-assets.controller.js +51 -0
  308. package/dist/controllers/media-assets.controller.js.map +1 -0
  309. package/dist/controllers/models.controller.d.ts +7 -0
  310. package/dist/controllers/models.controller.d.ts.map +1 -0
  311. package/dist/controllers/models.controller.js +44 -0
  312. package/dist/controllers/models.controller.js.map +1 -0
  313. package/dist/controllers/responses.controller.d.ts +7 -0
  314. package/dist/controllers/responses.controller.d.ts.map +1 -0
  315. package/dist/controllers/responses.controller.js +83 -0
  316. package/dist/controllers/responses.controller.js.map +1 -0
  317. package/dist/controllers/videos.controller.d.ts +7 -0
  318. package/dist/controllers/videos.controller.d.ts.map +1 -0
  319. package/dist/controllers/videos.controller.js +46 -0
  320. package/dist/controllers/videos.controller.js.map +1 -0
  321. package/dist/dto/admin-auth.dto.d.ts +10 -0
  322. package/dist/dto/admin-auth.dto.d.ts.map +1 -0
  323. package/dist/dto/admin-auth.dto.js +12 -0
  324. package/dist/dto/admin-auth.dto.js.map +1 -0
  325. package/dist/dto/admin.dto.d.ts +153 -0
  326. package/dist/dto/admin.dto.d.ts.map +1 -0
  327. package/dist/dto/admin.dto.js +78 -0
  328. package/dist/dto/admin.dto.js.map +1 -0
  329. package/dist/dto/anthropic-messages.dto.d.ts +77 -0
  330. package/dist/dto/anthropic-messages.dto.d.ts.map +1 -0
  331. package/dist/dto/anthropic-messages.dto.js +65 -0
  332. package/dist/dto/anthropic-messages.dto.js.map +1 -0
  333. package/dist/dto/api-key.dto.d.ts +27 -0
  334. package/dist/dto/api-key.dto.d.ts.map +1 -0
  335. package/dist/dto/api-key.dto.js +15 -0
  336. package/dist/dto/api-key.dto.js.map +1 -0
  337. package/dist/dto/audio.dto.d.ts +64 -0
  338. package/dist/dto/audio.dto.d.ts.map +1 -0
  339. package/dist/dto/audio.dto.js +29 -0
  340. package/dist/dto/audio.dto.js.map +1 -0
  341. package/dist/dto/chat.dto.d.ts +451 -0
  342. package/dist/dto/chat.dto.d.ts.map +1 -0
  343. package/dist/dto/chat.dto.js +116 -0
  344. package/dist/dto/chat.dto.js.map +1 -0
  345. package/dist/dto/conversation.dto.d.ts +286 -0
  346. package/dist/dto/conversation.dto.d.ts.map +1 -0
  347. package/dist/dto/conversation.dto.js +78 -0
  348. package/dist/dto/conversation.dto.js.map +1 -0
  349. package/dist/dto/ddos.dto.d.ts +191 -0
  350. package/dist/dto/ddos.dto.d.ts.map +1 -0
  351. package/dist/dto/ddos.dto.js +57 -0
  352. package/dist/dto/ddos.dto.js.map +1 -0
  353. package/dist/dto/document.dto.d.ts +21 -0
  354. package/dist/dto/document.dto.d.ts.map +1 -0
  355. package/dist/dto/document.dto.js +12 -0
  356. package/dist/dto/document.dto.js.map +1 -0
  357. package/dist/dto/files.dto.d.ts +17 -0
  358. package/dist/dto/files.dto.d.ts.map +1 -0
  359. package/dist/dto/files.dto.js +21 -0
  360. package/dist/dto/files.dto.js.map +1 -0
  361. package/dist/dto/images.dto.d.ts +68 -0
  362. package/dist/dto/images.dto.d.ts.map +1 -0
  363. package/dist/dto/images.dto.js +40 -0
  364. package/dist/dto/images.dto.js.map +1 -0
  365. package/dist/dto/index.d.ts +13 -0
  366. package/dist/dto/index.d.ts.map +1 -0
  367. package/dist/dto/index.js +44 -0
  368. package/dist/dto/index.js.map +1 -0
  369. package/dist/dto/queue.dto.d.ts +126 -0
  370. package/dist/dto/queue.dto.d.ts.map +1 -0
  371. package/dist/dto/queue.dto.js +33 -0
  372. package/dist/dto/queue.dto.js.map +1 -0
  373. package/dist/dto/responses.dto.d.ts +76 -0
  374. package/dist/dto/responses.dto.d.ts.map +1 -0
  375. package/dist/dto/responses.dto.js +139 -0
  376. package/dist/dto/responses.dto.js.map +1 -0
  377. package/dist/dto/videos.dto.d.ts +46 -0
  378. package/dist/dto/videos.dto.d.ts.map +1 -0
  379. package/dist/dto/videos.dto.js +38 -0
  380. package/dist/dto/videos.dto.js.map +1 -0
  381. package/dist/entities/api-key-created.entity.d.ts +6 -0
  382. package/dist/entities/api-key-created.entity.d.ts.map +1 -0
  383. package/dist/entities/api-key-created.entity.js +3 -0
  384. package/dist/entities/api-key-created.entity.js.map +1 -0
  385. package/dist/entities/api-key-public.entity.d.ts +20 -0
  386. package/dist/entities/api-key-public.entity.d.ts.map +1 -0
  387. package/dist/entities/api-key-public.entity.js +3 -0
  388. package/dist/entities/api-key-public.entity.js.map +1 -0
  389. package/dist/entities/api-key.entity.d.ts +21 -0
  390. package/dist/entities/api-key.entity.d.ts.map +1 -0
  391. package/dist/entities/api-key.entity.js +3 -0
  392. package/dist/entities/api-key.entity.js.map +1 -0
  393. package/dist/entities/audit-log-create-input.entity.d.ts +9 -0
  394. package/dist/entities/audit-log-create-input.entity.d.ts.map +1 -0
  395. package/dist/entities/audit-log-create-input.entity.js +3 -0
  396. package/dist/entities/audit-log-create-input.entity.js.map +1 -0
  397. package/dist/entities/audit-log.entity.d.ts +12 -0
  398. package/dist/entities/audit-log.entity.d.ts.map +1 -0
  399. package/dist/entities/audit-log.entity.js +3 -0
  400. package/dist/entities/audit-log.entity.js.map +1 -0
  401. package/dist/entities/chat-request-status.type.d.ts +2 -0
  402. package/dist/entities/chat-request-status.type.d.ts.map +1 -0
  403. package/dist/entities/chat-request-status.type.js +3 -0
  404. package/dist/entities/chat-request-status.type.js.map +1 -0
  405. package/dist/entities/chat-request.entity.d.ts +18 -0
  406. package/dist/entities/chat-request.entity.d.ts.map +1 -0
  407. package/dist/entities/chat-request.entity.js +3 -0
  408. package/dist/entities/chat-request.entity.js.map +1 -0
  409. package/dist/entities/document-public.entity.d.ts +9 -0
  410. package/dist/entities/document-public.entity.d.ts.map +1 -0
  411. package/dist/entities/document-public.entity.js +3 -0
  412. package/dist/entities/document-public.entity.js.map +1 -0
  413. package/dist/entities/document-storage-type.type.d.ts +2 -0
  414. package/dist/entities/document-storage-type.type.d.ts.map +1 -0
  415. package/dist/entities/document-storage-type.type.js +3 -0
  416. package/dist/entities/document-storage-type.type.js.map +1 -0
  417. package/dist/entities/document.entity.d.ts +16 -0
  418. package/dist/entities/document.entity.d.ts.map +1 -0
  419. package/dist/entities/document.entity.js +3 -0
  420. package/dist/entities/document.entity.js.map +1 -0
  421. package/dist/entities/encrypted-payload.entity.d.ts +6 -0
  422. package/dist/entities/encrypted-payload.entity.d.ts.map +1 -0
  423. package/dist/entities/encrypted-payload.entity.js +3 -0
  424. package/dist/entities/encrypted-payload.entity.js.map +1 -0
  425. package/dist/entities/index.d.ts +12 -0
  426. package/dist/entities/index.d.ts.map +1 -0
  427. package/dist/entities/index.js +3 -0
  428. package/dist/entities/index.js.map +1 -0
  429. package/dist/exceptions/error-codes.d.ts +30 -0
  430. package/dist/exceptions/error-codes.d.ts.map +1 -0
  431. package/dist/exceptions/error-codes.js +32 -0
  432. package/dist/exceptions/error-codes.js.map +1 -0
  433. package/dist/exceptions/exception.factory.d.ts +33 -0
  434. package/dist/exceptions/exception.factory.d.ts.map +1 -0
  435. package/dist/exceptions/exception.factory.js +90 -0
  436. package/dist/exceptions/exception.factory.js.map +1 -0
  437. package/dist/exceptions/http.exception.d.ts +28 -0
  438. package/dist/exceptions/http.exception.d.ts.map +1 -0
  439. package/dist/exceptions/http.exception.js +75 -0
  440. package/dist/exceptions/http.exception.js.map +1 -0
  441. package/dist/interfaces/anthropic-message.interface.d.ts +27 -0
  442. package/dist/interfaces/anthropic-message.interface.d.ts.map +1 -0
  443. package/dist/interfaces/anthropic-message.interface.js +4 -0
  444. package/dist/interfaces/anthropic-message.interface.js.map +1 -0
  445. package/dist/interfaces/api-features.type.d.ts +45 -0
  446. package/dist/interfaces/api-features.type.d.ts.map +1 -0
  447. package/dist/interfaces/api-features.type.js +61 -0
  448. package/dist/interfaces/api-features.type.js.map +1 -0
  449. package/dist/interfaces/api-key-mode.type.d.ts +8 -0
  450. package/dist/interfaces/api-key-mode.type.d.ts.map +1 -0
  451. package/dist/interfaces/api-key-mode.type.js +3 -0
  452. package/dist/interfaces/api-key-mode.type.js.map +1 -0
  453. package/dist/interfaces/api-key-role.type.d.ts +3 -0
  454. package/dist/interfaces/api-key-role.type.d.ts.map +1 -0
  455. package/dist/interfaces/api-key-role.type.js +3 -0
  456. package/dist/interfaces/api-key-role.type.js.map +1 -0
  457. package/dist/interfaces/app-settings.type.d.ts +10 -0
  458. package/dist/interfaces/app-settings.type.d.ts.map +1 -0
  459. package/dist/interfaces/app-settings.type.js +3 -0
  460. package/dist/interfaces/app-settings.type.js.map +1 -0
  461. package/dist/interfaces/auth.interface.d.ts +5 -0
  462. package/dist/interfaces/auth.interface.d.ts.map +1 -0
  463. package/dist/interfaces/auth.interface.js +3 -0
  464. package/dist/interfaces/auth.interface.js.map +1 -0
  465. package/dist/interfaces/authenticated-api-key.interface.d.ts +18 -0
  466. package/dist/interfaces/authenticated-api-key.interface.d.ts.map +1 -0
  467. package/dist/interfaces/authenticated-api-key.interface.js +3 -0
  468. package/dist/interfaces/authenticated-api-key.interface.js.map +1 -0
  469. package/dist/interfaces/auto-ban-event.interface.d.ts +11 -0
  470. package/dist/interfaces/auto-ban-event.interface.d.ts.map +1 -0
  471. package/dist/interfaces/auto-ban-event.interface.js +3 -0
  472. package/dist/interfaces/auto-ban-event.interface.js.map +1 -0
  473. package/dist/interfaces/built-engine-request.interface.d.ts +19 -0
  474. package/dist/interfaces/built-engine-request.interface.d.ts.map +1 -0
  475. package/dist/interfaces/built-engine-request.interface.js +3 -0
  476. package/dist/interfaces/built-engine-request.interface.js.map +1 -0
  477. package/dist/interfaces/chat-context.interface.d.ts +9 -0
  478. package/dist/interfaces/chat-context.interface.d.ts.map +1 -0
  479. package/dist/interfaces/chat-context.interface.js +3 -0
  480. package/dist/interfaces/chat-context.interface.js.map +1 -0
  481. package/dist/interfaces/chat-job-payload.interface.d.ts +28 -0
  482. package/dist/interfaces/chat-job-payload.interface.d.ts.map +1 -0
  483. package/dist/interfaces/chat-job-payload.interface.js +3 -0
  484. package/dist/interfaces/chat-job-payload.interface.js.map +1 -0
  485. package/dist/interfaces/chat-list-query.interface.d.ts +16 -0
  486. package/dist/interfaces/chat-list-query.interface.d.ts.map +1 -0
  487. package/dist/interfaces/chat-list-query.interface.js +3 -0
  488. package/dist/interfaces/chat-list-query.interface.js.map +1 -0
  489. package/dist/interfaces/document-context-result.interface.d.ts +7 -0
  490. package/dist/interfaces/document-context-result.interface.d.ts.map +1 -0
  491. package/dist/interfaces/document-context-result.interface.js +3 -0
  492. package/dist/interfaces/document-context-result.interface.js.map +1 -0
  493. package/dist/interfaces/engine-collected-output.interface.d.ts +33 -0
  494. package/dist/interfaces/engine-collected-output.interface.d.ts.map +1 -0
  495. package/dist/interfaces/engine-collected-output.interface.js +3 -0
  496. package/dist/interfaces/engine-collected-output.interface.js.map +1 -0
  497. package/dist/interfaces/engine-json-result.interface.d.ts +7 -0
  498. package/dist/interfaces/engine-json-result.interface.d.ts.map +1 -0
  499. package/dist/interfaces/engine-json-result.interface.js +3 -0
  500. package/dist/interfaces/engine-json-result.interface.js.map +1 -0
  501. package/dist/interfaces/engine-response-meta.interface.d.ts +14 -0
  502. package/dist/interfaces/engine-response-meta.interface.d.ts.map +1 -0
  503. package/dist/interfaces/engine-response-meta.interface.js +3 -0
  504. package/dist/interfaces/engine-response-meta.interface.js.map +1 -0
  505. package/dist/interfaces/engine-run-options.interface.d.ts +66 -0
  506. package/dist/interfaces/engine-run-options.interface.d.ts.map +1 -0
  507. package/dist/interfaces/engine-run-options.interface.js +3 -0
  508. package/dist/interfaces/engine-run-options.interface.js.map +1 -0
  509. package/dist/interfaces/engine-run-result.interface.d.ts +8 -0
  510. package/dist/interfaces/engine-run-result.interface.d.ts.map +1 -0
  511. package/dist/interfaces/engine-run-result.interface.js +3 -0
  512. package/dist/interfaces/engine-run-result.interface.js.map +1 -0
  513. package/dist/interfaces/engine-stream-event.type.d.ts +20 -0
  514. package/dist/interfaces/engine-stream-event.type.d.ts.map +1 -0
  515. package/dist/interfaces/engine-stream-event.type.js +3 -0
  516. package/dist/interfaces/engine-stream-event.type.js.map +1 -0
  517. package/dist/interfaces/engine.interface.d.ts +6 -0
  518. package/dist/interfaces/engine.interface.d.ts.map +1 -0
  519. package/dist/interfaces/engine.interface.js +3 -0
  520. package/dist/interfaces/engine.interface.js.map +1 -0
  521. package/dist/interfaces/execute-completion-options.interface.d.ts +17 -0
  522. package/dist/interfaces/execute-completion-options.interface.d.ts.map +1 -0
  523. package/dist/interfaces/execute-completion-options.interface.js +3 -0
  524. package/dist/interfaces/execute-completion-options.interface.js.map +1 -0
  525. package/dist/interfaces/express.interface.d.ts +13 -0
  526. package/dist/interfaces/express.interface.d.ts.map +1 -0
  527. package/dist/interfaces/express.interface.js +3 -0
  528. package/dist/interfaces/express.interface.js.map +1 -0
  529. package/dist/interfaces/index.d.ts +47 -0
  530. package/dist/interfaces/index.d.ts.map +1 -0
  531. package/dist/interfaces/index.js +7 -0
  532. package/dist/interfaces/index.js.map +1 -0
  533. package/dist/interfaces/install-channel.type.d.ts +2 -0
  534. package/dist/interfaces/install-channel.type.d.ts.map +1 -0
  535. package/dist/interfaces/install-channel.type.js +3 -0
  536. package/dist/interfaces/install-channel.type.js.map +1 -0
  537. package/dist/interfaces/map-completion-options.interface.d.ts +20 -0
  538. package/dist/interfaces/map-completion-options.interface.d.ts.map +1 -0
  539. package/dist/interfaces/map-completion-options.interface.js +3 -0
  540. package/dist/interfaces/map-completion-options.interface.js.map +1 -0
  541. package/dist/interfaces/materialized-document.interface.d.ts +10 -0
  542. package/dist/interfaces/materialized-document.interface.d.ts.map +1 -0
  543. package/dist/interfaces/materialized-document.interface.js +3 -0
  544. package/dist/interfaces/materialized-document.interface.js.map +1 -0
  545. package/dist/interfaces/open-ai-chat-completion-choice.interface.d.ts +25 -0
  546. package/dist/interfaces/open-ai-chat-completion-choice.interface.d.ts.map +1 -0
  547. package/dist/interfaces/open-ai-chat-completion-choice.interface.js +3 -0
  548. package/dist/interfaces/open-ai-chat-completion-choice.interface.js.map +1 -0
  549. package/dist/interfaces/open-ai-chat-completion-chunk.interface.d.ts +51 -0
  550. package/dist/interfaces/open-ai-chat-completion-chunk.interface.d.ts.map +1 -0
  551. package/dist/interfaces/open-ai-chat-completion-chunk.interface.js +3 -0
  552. package/dist/interfaces/open-ai-chat-completion-chunk.interface.js.map +1 -0
  553. package/dist/interfaces/open-ai-chat-completion-request.interface.d.ts +55 -0
  554. package/dist/interfaces/open-ai-chat-completion-request.interface.d.ts.map +1 -0
  555. package/dist/interfaces/open-ai-chat-completion-request.interface.js +3 -0
  556. package/dist/interfaces/open-ai-chat-completion-request.interface.js.map +1 -0
  557. package/dist/interfaces/open-ai-chat-completion.interface.d.ts +21 -0
  558. package/dist/interfaces/open-ai-chat-completion.interface.d.ts.map +1 -0
  559. package/dist/interfaces/open-ai-chat-completion.interface.js +3 -0
  560. package/dist/interfaces/open-ai-chat-completion.interface.js.map +1 -0
  561. package/dist/interfaces/open-ai-chat-message.interface.d.ts +9 -0
  562. package/dist/interfaces/open-ai-chat-message.interface.d.ts.map +1 -0
  563. package/dist/interfaces/open-ai-chat-message.interface.js +3 -0
  564. package/dist/interfaces/open-ai-chat-message.interface.js.map +1 -0
  565. package/dist/interfaces/open-ai-model-list.interface.d.ts +6 -0
  566. package/dist/interfaces/open-ai-model-list.interface.d.ts.map +1 -0
  567. package/dist/interfaces/open-ai-model-list.interface.js +3 -0
  568. package/dist/interfaces/open-ai-model-list.interface.js.map +1 -0
  569. package/dist/interfaces/open-ai-model.interface.d.ts +10 -0
  570. package/dist/interfaces/open-ai-model.interface.d.ts.map +1 -0
  571. package/dist/interfaces/open-ai-model.interface.js +3 -0
  572. package/dist/interfaces/open-ai-model.interface.js.map +1 -0
  573. package/dist/interfaces/open-ai-response.interface.d.ts +32 -0
  574. package/dist/interfaces/open-ai-response.interface.d.ts.map +1 -0
  575. package/dist/interfaces/open-ai-response.interface.js +3 -0
  576. package/dist/interfaces/open-ai-response.interface.js.map +1 -0
  577. package/dist/interfaces/open-ai-role.type.d.ts +2 -0
  578. package/dist/interfaces/open-ai-role.type.d.ts.map +1 -0
  579. package/dist/interfaces/open-ai-role.type.js +3 -0
  580. package/dist/interfaces/open-ai-role.type.js.map +1 -0
  581. package/dist/interfaces/openai.interface.d.ts +11 -0
  582. package/dist/interfaces/openai.interface.d.ts.map +1 -0
  583. package/dist/interfaces/openai.interface.js +3 -0
  584. package/dist/interfaces/openai.interface.js.map +1 -0
  585. package/dist/interfaces/pm2-runtime-config.interface.d.ts +24 -0
  586. package/dist/interfaces/pm2-runtime-config.interface.d.ts.map +1 -0
  587. package/dist/interfaces/pm2-runtime-config.interface.js +3 -0
  588. package/dist/interfaces/pm2-runtime-config.interface.js.map +1 -0
  589. package/dist/interfaces/proxy-ip-config.interface.d.ts +12 -0
  590. package/dist/interfaces/proxy-ip-config.interface.d.ts.map +1 -0
  591. package/dist/interfaces/proxy-ip-config.interface.js +3 -0
  592. package/dist/interfaces/proxy-ip-config.interface.js.map +1 -0
  593. package/dist/interfaces/proxy-ip-source.type.d.ts +7 -0
  594. package/dist/interfaces/proxy-ip-source.type.d.ts.map +1 -0
  595. package/dist/interfaces/proxy-ip-source.type.js +3 -0
  596. package/dist/interfaces/proxy-ip-source.type.js.map +1 -0
  597. package/dist/interfaces/resolved-policy.interface.d.ts +15 -0
  598. package/dist/interfaces/resolved-policy.interface.d.ts.map +1 -0
  599. package/dist/interfaces/resolved-policy.interface.js +3 -0
  600. package/dist/interfaces/resolved-policy.interface.js.map +1 -0
  601. package/dist/interfaces/runner-mode.type.d.ts +2 -0
  602. package/dist/interfaces/runner-mode.type.d.ts.map +1 -0
  603. package/dist/interfaces/runner-mode.type.js +3 -0
  604. package/dist/interfaces/runner-mode.type.js.map +1 -0
  605. package/dist/interfaces/software-check.interface.d.ts +14 -0
  606. package/dist/interfaces/software-check.interface.d.ts.map +1 -0
  607. package/dist/interfaces/software-check.interface.js +3 -0
  608. package/dist/interfaces/software-check.interface.js.map +1 -0
  609. package/dist/interfaces/software-id.type.d.ts +2 -0
  610. package/dist/interfaces/software-id.type.d.ts.map +1 -0
  611. package/dist/interfaces/software-id.type.js +3 -0
  612. package/dist/interfaces/software-id.type.js.map +1 -0
  613. package/dist/interfaces/software-level.type.d.ts +2 -0
  614. package/dist/interfaces/software-level.type.d.ts.map +1 -0
  615. package/dist/interfaces/software-level.type.js +3 -0
  616. package/dist/interfaces/software-level.type.js.map +1 -0
  617. package/dist/interfaces/system-software-report.interface.d.ts +6 -0
  618. package/dist/interfaces/system-software-report.interface.d.ts.map +1 -0
  619. package/dist/interfaces/system-software-report.interface.js +3 -0
  620. package/dist/interfaces/system-software-report.interface.js.map +1 -0
  621. package/dist/interfaces/tracked-connection.interface.d.ts +16 -0
  622. package/dist/interfaces/tracked-connection.interface.d.ts.map +1 -0
  623. package/dist/interfaces/tracked-connection.interface.js +3 -0
  624. package/dist/interfaces/tracked-connection.interface.js.map +1 -0
  625. package/dist/interfaces/update-progress.type.d.ts +16 -0
  626. package/dist/interfaces/update-progress.type.d.ts.map +1 -0
  627. package/dist/interfaces/update-progress.type.js +3 -0
  628. package/dist/interfaces/update-progress.type.js.map +1 -0
  629. package/dist/interfaces/update-result.interface.d.ts +11 -0
  630. package/dist/interfaces/update-result.interface.d.ts.map +1 -0
  631. package/dist/interfaces/update-result.interface.js +3 -0
  632. package/dist/interfaces/update-result.interface.js.map +1 -0
  633. package/dist/interfaces/version-info.interface.d.ts +21 -0
  634. package/dist/interfaces/version-info.interface.d.ts.map +1 -0
  635. package/dist/interfaces/version-info.interface.js +3 -0
  636. package/dist/interfaces/version-info.interface.js.map +1 -0
  637. package/dist/interfaces/version-status.type.d.ts +3 -0
  638. package/dist/interfaces/version-status.type.d.ts.map +1 -0
  639. package/dist/interfaces/version-status.type.js +3 -0
  640. package/dist/interfaces/version-status.type.js.map +1 -0
  641. package/dist/middlewares/auth.middleware.d.ts +13 -0
  642. package/dist/middlewares/auth.middleware.d.ts.map +1 -0
  643. package/dist/middlewares/auth.middleware.js +147 -0
  644. package/dist/middlewares/auth.middleware.js.map +1 -0
  645. package/dist/middlewares/client-ip.middleware.d.ts +11 -0
  646. package/dist/middlewares/client-ip.middleware.d.ts.map +1 -0
  647. package/dist/middlewares/client-ip.middleware.js +19 -0
  648. package/dist/middlewares/client-ip.middleware.js.map +1 -0
  649. package/dist/middlewares/concurrency.middleware.d.ts +6 -0
  650. package/dist/middlewares/concurrency.middleware.d.ts.map +1 -0
  651. package/dist/middlewares/concurrency.middleware.js +16 -0
  652. package/dist/middlewares/concurrency.middleware.js.map +1 -0
  653. package/dist/middlewares/connection-tracker.middleware.d.ts +33 -0
  654. package/dist/middlewares/connection-tracker.middleware.d.ts.map +1 -0
  655. package/dist/middlewares/connection-tracker.middleware.js +99 -0
  656. package/dist/middlewares/connection-tracker.middleware.js.map +1 -0
  657. package/dist/middlewares/error.middleware.d.ts +4 -0
  658. package/dist/middlewares/error.middleware.d.ts.map +1 -0
  659. package/dist/middlewares/error.middleware.js +42 -0
  660. package/dist/middlewares/error.middleware.js.map +1 -0
  661. package/dist/middlewares/index.d.ts +11 -0
  662. package/dist/middlewares/index.d.ts.map +1 -0
  663. package/dist/middlewares/index.js +35 -0
  664. package/dist/middlewares/index.js.map +1 -0
  665. package/dist/middlewares/rate-limit.middleware.d.ts +11 -0
  666. package/dist/middlewares/rate-limit.middleware.d.ts.map +1 -0
  667. package/dist/middlewares/rate-limit.middleware.js +152 -0
  668. package/dist/middlewares/rate-limit.middleware.js.map +1 -0
  669. package/dist/middlewares/request-id.middleware.d.ts +3 -0
  670. package/dist/middlewares/request-id.middleware.d.ts.map +1 -0
  671. package/dist/middlewares/request-id.middleware.js +12 -0
  672. package/dist/middlewares/request-id.middleware.js.map +1 -0
  673. package/dist/middlewares/upload-images.middleware.d.ts +3 -0
  674. package/dist/middlewares/upload-images.middleware.d.ts.map +1 -0
  675. package/dist/middlewares/upload-images.middleware.js +29 -0
  676. package/dist/middlewares/upload-images.middleware.js.map +1 -0
  677. package/dist/middlewares/upload.middleware.d.ts +2 -0
  678. package/dist/middlewares/upload.middleware.d.ts.map +1 -0
  679. package/dist/middlewares/upload.middleware.js +26 -0
  680. package/dist/middlewares/upload.middleware.js.map +1 -0
  681. package/dist/middlewares/validate.middleware.d.ts +6 -0
  682. package/dist/middlewares/validate.middleware.d.ts.map +1 -0
  683. package/dist/middlewares/validate.middleware.js +40 -0
  684. package/dist/middlewares/validate.middleware.js.map +1 -0
  685. package/dist/routes/admin.routes.d.ts +3 -0
  686. package/dist/routes/admin.routes.d.ts.map +1 -0
  687. package/dist/routes/admin.routes.js +136 -0
  688. package/dist/routes/admin.routes.js.map +1 -0
  689. package/dist/routes/index.d.ts +3 -0
  690. package/dist/routes/index.d.ts.map +1 -0
  691. package/dist/routes/index.js +46 -0
  692. package/dist/routes/index.js.map +1 -0
  693. package/dist/routes/v1/api-keys.routes.d.ts +3 -0
  694. package/dist/routes/v1/api-keys.routes.d.ts.map +1 -0
  695. package/dist/routes/v1/api-keys.routes.js +13 -0
  696. package/dist/routes/v1/api-keys.routes.js.map +1 -0
  697. package/dist/routes/v1/assistants.routes.d.ts +3 -0
  698. package/dist/routes/v1/assistants.routes.d.ts.map +1 -0
  699. package/dist/routes/v1/assistants.routes.js +13 -0
  700. package/dist/routes/v1/assistants.routes.js.map +1 -0
  701. package/dist/routes/v1/audio.routes.d.ts +3 -0
  702. package/dist/routes/v1/audio.routes.d.ts.map +1 -0
  703. package/dist/routes/v1/audio.routes.js +14 -0
  704. package/dist/routes/v1/audio.routes.js.map +1 -0
  705. package/dist/routes/v1/chat.routes.d.ts +3 -0
  706. package/dist/routes/v1/chat.routes.d.ts.map +1 -0
  707. package/dist/routes/v1/chat.routes.js +13 -0
  708. package/dist/routes/v1/chat.routes.js.map +1 -0
  709. package/dist/routes/v1/documents.routes.d.ts +3 -0
  710. package/dist/routes/v1/documents.routes.d.ts.map +1 -0
  711. package/dist/routes/v1/documents.routes.js +15 -0
  712. package/dist/routes/v1/documents.routes.js.map +1 -0
  713. package/dist/routes/v1/files.routes.d.ts +3 -0
  714. package/dist/routes/v1/files.routes.d.ts.map +1 -0
  715. package/dist/routes/v1/files.routes.js +16 -0
  716. package/dist/routes/v1/files.routes.js.map +1 -0
  717. package/dist/routes/v1/images.routes.d.ts +3 -0
  718. package/dist/routes/v1/images.routes.d.ts.map +1 -0
  719. package/dist/routes/v1/images.routes.js +14 -0
  720. package/dist/routes/v1/images.routes.js.map +1 -0
  721. package/dist/routes/v1/media-assets.routes.d.ts +3 -0
  722. package/dist/routes/v1/media-assets.routes.d.ts.map +1 -0
  723. package/dist/routes/v1/media-assets.routes.js +12 -0
  724. package/dist/routes/v1/media-assets.routes.js.map +1 -0
  725. package/dist/routes/v1/messages.routes.d.ts +3 -0
  726. package/dist/routes/v1/messages.routes.d.ts.map +1 -0
  727. package/dist/routes/v1/messages.routes.js +13 -0
  728. package/dist/routes/v1/messages.routes.js.map +1 -0
  729. package/dist/routes/v1/models.routes.d.ts +3 -0
  730. package/dist/routes/v1/models.routes.d.ts.map +1 -0
  731. package/dist/routes/v1/models.routes.js +11 -0
  732. package/dist/routes/v1/models.routes.js.map +1 -0
  733. package/dist/routes/v1/responses.routes.d.ts +3 -0
  734. package/dist/routes/v1/responses.routes.d.ts.map +1 -0
  735. package/dist/routes/v1/responses.routes.js +15 -0
  736. package/dist/routes/v1/responses.routes.js.map +1 -0
  737. package/dist/routes/v1/threads.routes.d.ts +3 -0
  738. package/dist/routes/v1/threads.routes.d.ts.map +1 -0
  739. package/dist/routes/v1/threads.routes.js +15 -0
  740. package/dist/routes/v1/threads.routes.js.map +1 -0
  741. package/dist/routes/v1/videos.routes.d.ts +3 -0
  742. package/dist/routes/v1/videos.routes.d.ts.map +1 -0
  743. package/dist/routes/v1/videos.routes.js +14 -0
  744. package/dist/routes/v1/videos.routes.js.map +1 -0
  745. package/dist/server.d.ts +2 -0
  746. package/dist/server.d.ts.map +1 -0
  747. package/dist/server.js +121 -0
  748. package/dist/server.js.map +1 -0
  749. package/dist/services/abuse-guard.service.d.ts +19 -0
  750. package/dist/services/abuse-guard.service.d.ts.map +1 -0
  751. package/dist/services/abuse-guard.service.js +243 -0
  752. package/dist/services/abuse-guard.service.js.map +1 -0
  753. package/dist/services/admin-auth.service.d.ts +32 -0
  754. package/dist/services/admin-auth.service.d.ts.map +1 -0
  755. package/dist/services/admin-auth.service.js +202 -0
  756. package/dist/services/admin-auth.service.js.map +1 -0
  757. package/dist/services/api-features.service.d.ts +15 -0
  758. package/dist/services/api-features.service.d.ts.map +1 -0
  759. package/dist/services/api-features.service.js +92 -0
  760. package/dist/services/api-features.service.js.map +1 -0
  761. package/dist/services/api-key.service.d.ts +52 -0
  762. package/dist/services/api-key.service.d.ts.map +1 -0
  763. package/dist/services/api-key.service.js +296 -0
  764. package/dist/services/api-key.service.js.map +1 -0
  765. package/dist/services/assistants.service.d.ts +130 -0
  766. package/dist/services/assistants.service.d.ts.map +1 -0
  767. package/dist/services/assistants.service.js +329 -0
  768. package/dist/services/assistants.service.js.map +1 -0
  769. package/dist/services/audit.service.d.ts +10 -0
  770. package/dist/services/audit.service.d.ts.map +1 -0
  771. package/dist/services/audit.service.js +38 -0
  772. package/dist/services/audit.service.js.map +1 -0
  773. package/dist/services/chat-admin.service.d.ts +76 -0
  774. package/dist/services/chat-admin.service.d.ts.map +1 -0
  775. package/dist/services/chat-admin.service.js +220 -0
  776. package/dist/services/chat-admin.service.js.map +1 -0
  777. package/dist/services/chat-request-builder.service.d.ts +23 -0
  778. package/dist/services/chat-request-builder.service.d.ts.map +1 -0
  779. package/dist/services/chat-request-builder.service.js +325 -0
  780. package/dist/services/chat-request-builder.service.js.map +1 -0
  781. package/dist/services/chat.service.d.ts +27 -0
  782. package/dist/services/chat.service.d.ts.map +1 -0
  783. package/dist/services/chat.service.js +1088 -0
  784. package/dist/services/chat.service.js.map +1 -0
  785. package/dist/services/conversation.service.d.ts +104 -0
  786. package/dist/services/conversation.service.d.ts.map +1 -0
  787. package/dist/services/conversation.service.js +254 -0
  788. package/dist/services/conversation.service.js.map +1 -0
  789. package/dist/services/ddos-policy.service.d.ts +41 -0
  790. package/dist/services/ddos-policy.service.d.ts.map +1 -0
  791. package/dist/services/ddos-policy.service.js +263 -0
  792. package/dist/services/ddos-policy.service.js.map +1 -0
  793. package/dist/services/document.service.d.ts +62 -0
  794. package/dist/services/document.service.d.ts.map +1 -0
  795. package/dist/services/document.service.js +344 -0
  796. package/dist/services/document.service.js.map +1 -0
  797. package/dist/services/encryption.service.d.ts +8 -0
  798. package/dist/services/encryption.service.d.ts.map +1 -0
  799. package/dist/services/encryption.service.js +34 -0
  800. package/dist/services/encryption.service.js.map +1 -0
  801. package/dist/services/engine-session-map.service.d.ts +11 -0
  802. package/dist/services/engine-session-map.service.d.ts.map +1 -0
  803. package/dist/services/engine-session-map.service.js +59 -0
  804. package/dist/services/engine-session-map.service.js.map +1 -0
  805. package/dist/services/engine-slot.service.d.ts +21 -0
  806. package/dist/services/engine-slot.service.d.ts.map +1 -0
  807. package/dist/services/engine-slot.service.js +55 -0
  808. package/dist/services/engine-slot.service.js.map +1 -0
  809. package/dist/services/hf/client.d.ts +18 -0
  810. package/dist/services/hf/client.d.ts.map +1 -0
  811. package/dist/services/hf/client.js +202 -0
  812. package/dist/services/hf/client.js.map +1 -0
  813. package/dist/services/hf/delete-local.d.ts +5 -0
  814. package/dist/services/hf/delete-local.d.ts.map +1 -0
  815. package/dist/services/hf/delete-local.js +46 -0
  816. package/dist/services/hf/delete-local.js.map +1 -0
  817. package/dist/services/hf/hub-search.d.ts +66 -0
  818. package/dist/services/hf/hub-search.d.ts.map +1 -0
  819. package/dist/services/hf/hub-search.js +272 -0
  820. package/dist/services/hf/hub-search.js.map +1 -0
  821. package/dist/services/hf/record-pull.d.ts +6 -0
  822. package/dist/services/hf/record-pull.d.ts.map +1 -0
  823. package/dist/services/hf/record-pull.js +80 -0
  824. package/dist/services/hf/record-pull.js.map +1 -0
  825. package/dist/services/hf/registry.d.ts +27 -0
  826. package/dist/services/hf/registry.d.ts.map +1 -0
  827. package/dist/services/hf/registry.js +77 -0
  828. package/dist/services/hf/registry.js.map +1 -0
  829. package/dist/services/hf/spec.d.ts +33 -0
  830. package/dist/services/hf/spec.d.ts.map +1 -0
  831. package/dist/services/hf/spec.js +175 -0
  832. package/dist/services/hf/spec.js.map +1 -0
  833. package/dist/services/ip-blacklist.service.d.ts +44 -0
  834. package/dist/services/ip-blacklist.service.d.ts.map +1 -0
  835. package/dist/services/ip-blacklist.service.js +145 -0
  836. package/dist/services/ip-blacklist.service.js.map +1 -0
  837. package/dist/services/media/audio-worker.d.ts +23 -0
  838. package/dist/services/media/audio-worker.d.ts.map +1 -0
  839. package/dist/services/media/audio-worker.js +81 -0
  840. package/dist/services/media/audio-worker.js.map +1 -0
  841. package/dist/services/media/format-convert.d.ts +37 -0
  842. package/dist/services/media/format-convert.d.ts.map +1 -0
  843. package/dist/services/media/format-convert.js +215 -0
  844. package/dist/services/media/format-convert.js.map +1 -0
  845. package/dist/services/media/media-jobs.service.d.ts +46 -0
  846. package/dist/services/media/media-jobs.service.d.ts.map +1 -0
  847. package/dist/services/media/media-jobs.service.js +193 -0
  848. package/dist/services/media/media-jobs.service.js.map +1 -0
  849. package/dist/services/media/media-orchestrator.service.d.ts +53 -0
  850. package/dist/services/media/media-orchestrator.service.d.ts.map +1 -0
  851. package/dist/services/media/media-orchestrator.service.js +228 -0
  852. package/dist/services/media/media-orchestrator.service.js.map +1 -0
  853. package/dist/services/media/media-store.service.d.ts +39 -0
  854. package/dist/services/media/media-store.service.d.ts.map +1 -0
  855. package/dist/services/media/media-store.service.js +154 -0
  856. package/dist/services/media/media-store.service.js.map +1 -0
  857. package/dist/services/media/providers/http-worker.provider.d.ts +9 -0
  858. package/dist/services/media/providers/http-worker.provider.d.ts.map +1 -0
  859. package/dist/services/media/providers/http-worker.provider.js +73 -0
  860. package/dist/services/media/providers/http-worker.provider.js.map +1 -0
  861. package/dist/services/media/providers/media-provider.interface.d.ts +44 -0
  862. package/dist/services/media/providers/media-provider.interface.d.ts.map +1 -0
  863. package/dist/services/media/providers/media-provider.interface.js +4 -0
  864. package/dist/services/media/providers/media-provider.interface.js.map +1 -0
  865. package/dist/services/media/providers/mock.provider.d.ts +8 -0
  866. package/dist/services/media/providers/mock.provider.d.ts.map +1 -0
  867. package/dist/services/media/providers/mock.provider.js +43 -0
  868. package/dist/services/media/providers/mock.provider.js.map +1 -0
  869. package/dist/services/media/providers/stub.provider.d.ts +8 -0
  870. package/dist/services/media/providers/stub.provider.d.ts.map +1 -0
  871. package/dist/services/media/providers/stub.provider.js +14 -0
  872. package/dist/services/media/providers/stub.provider.js.map +1 -0
  873. package/dist/services/media/video-fixture.d.ts +3 -0
  874. package/dist/services/media/video-fixture.d.ts.map +1 -0
  875. package/dist/services/media/video-fixture.js +40 -0
  876. package/dist/services/media/video-fixture.js.map +1 -0
  877. package/dist/services/models.service.d.ts +49 -0
  878. package/dist/services/models.service.d.ts.map +1 -0
  879. package/dist/services/models.service.js +162 -0
  880. package/dist/services/models.service.js.map +1 -0
  881. package/dist/services/pm2-config.d.ts +12 -0
  882. package/dist/services/pm2-config.d.ts.map +1 -0
  883. package/dist/services/pm2-config.js +156 -0
  884. package/dist/services/pm2-config.js.map +1 -0
  885. package/dist/services/pm2.service.d.ts +207 -0
  886. package/dist/services/pm2.service.d.ts.map +1 -0
  887. package/dist/services/pm2.service.js +789 -0
  888. package/dist/services/pm2.service.js.map +1 -0
  889. package/dist/services/policy.service.d.ts +8 -0
  890. package/dist/services/policy.service.d.ts.map +1 -0
  891. package/dist/services/policy.service.js +112 -0
  892. package/dist/services/policy.service.js.map +1 -0
  893. package/dist/services/queue/chat-queue.service.d.ts +107 -0
  894. package/dist/services/queue/chat-queue.service.d.ts.map +1 -0
  895. package/dist/services/queue/chat-queue.service.js +557 -0
  896. package/dist/services/queue/chat-queue.service.js.map +1 -0
  897. package/dist/services/queue/chat-worker.service.d.ts +12 -0
  898. package/dist/services/queue/chat-worker.service.d.ts.map +1 -0
  899. package/dist/services/queue/chat-worker.service.js +136 -0
  900. package/dist/services/queue/chat-worker.service.js.map +1 -0
  901. package/dist/services/queue/fair-claim.d.ts +41 -0
  902. package/dist/services/queue/fair-claim.d.ts.map +1 -0
  903. package/dist/services/queue/fair-claim.js +54 -0
  904. package/dist/services/queue/fair-claim.js.map +1 -0
  905. package/dist/services/queue/job-waiter.d.ts +40 -0
  906. package/dist/services/queue/job-waiter.d.ts.map +1 -0
  907. package/dist/services/queue/job-waiter.js +77 -0
  908. package/dist/services/queue/job-waiter.js.map +1 -0
  909. package/dist/services/queue/queue-backend.factory.d.ts +12 -0
  910. package/dist/services/queue/queue-backend.factory.d.ts.map +1 -0
  911. package/dist/services/queue/queue-backend.factory.js +41 -0
  912. package/dist/services/queue/queue-backend.factory.js.map +1 -0
  913. package/dist/services/queue/queue-backend.interface.d.ts +67 -0
  914. package/dist/services/queue/queue-backend.interface.d.ts.map +1 -0
  915. package/dist/services/queue/queue-backend.interface.js +19 -0
  916. package/dist/services/queue/queue-backend.interface.js.map +1 -0
  917. package/dist/services/queue/queue-policy.service.d.ts +19 -0
  918. package/dist/services/queue/queue-policy.service.d.ts.map +1 -0
  919. package/dist/services/queue/queue-policy.service.js +99 -0
  920. package/dist/services/queue/queue-policy.service.js.map +1 -0
  921. package/dist/services/response-store.service.d.ts +14 -0
  922. package/dist/services/response-store.service.d.ts.map +1 -0
  923. package/dist/services/response-store.service.js +77 -0
  924. package/dist/services/response-store.service.js.map +1 -0
  925. package/dist/services/role-normalize.service.d.ts +5 -0
  926. package/dist/services/role-normalize.service.d.ts.map +1 -0
  927. package/dist/services/role-normalize.service.js +22 -0
  928. package/dist/services/role-normalize.service.js.map +1 -0
  929. package/dist/services/runtimes/echo.d.ts +17 -0
  930. package/dist/services/runtimes/echo.d.ts.map +1 -0
  931. package/dist/services/runtimes/echo.js +40 -0
  932. package/dist/services/runtimes/echo.js.map +1 -0
  933. package/dist/services/runtimes/engine-manager.d.ts +47 -0
  934. package/dist/services/runtimes/engine-manager.d.ts.map +1 -0
  935. package/dist/services/runtimes/engine-manager.js +191 -0
  936. package/dist/services/runtimes/engine-manager.js.map +1 -0
  937. package/dist/services/runtimes/llama-server.d.ts +37 -0
  938. package/dist/services/runtimes/llama-server.d.ts.map +1 -0
  939. package/dist/services/runtimes/llama-server.js +153 -0
  940. package/dist/services/runtimes/llama-server.js.map +1 -0
  941. package/dist/services/runtimes/runtime-catalog.d.ts +49 -0
  942. package/dist/services/runtimes/runtime-catalog.d.ts.map +1 -0
  943. package/dist/services/runtimes/runtime-catalog.js +510 -0
  944. package/dist/services/runtimes/runtime-catalog.js.map +1 -0
  945. package/dist/services/runtimes/runtime-install.d.ts +45 -0
  946. package/dist/services/runtimes/runtime-install.d.ts.map +1 -0
  947. package/dist/services/runtimes/runtime-install.js +159 -0
  948. package/dist/services/runtimes/runtime-install.js.map +1 -0
  949. package/dist/services/runtimes/vllm.d.ts +14 -0
  950. package/dist/services/runtimes/vllm.d.ts.map +1 -0
  951. package/dist/services/runtimes/vllm.js +105 -0
  952. package/dist/services/runtimes/vllm.js.map +1 -0
  953. package/dist/services/settings.service.d.ts +7 -0
  954. package/dist/services/settings.service.d.ts.map +1 -0
  955. package/dist/services/settings.service.js +87 -0
  956. package/dist/services/settings.service.js.map +1 -0
  957. package/dist/services/stats.service.d.ts +104 -0
  958. package/dist/services/stats.service.d.ts.map +1 -0
  959. package/dist/services/stats.service.js +218 -0
  960. package/dist/services/stats.service.js.map +1 -0
  961. package/dist/services/system-health.service.d.ts +15 -0
  962. package/dist/services/system-health.service.d.ts.map +1 -0
  963. package/dist/services/system-health.service.js +259 -0
  964. package/dist/services/system-health.service.js.map +1 -0
  965. package/dist/services/update.service.d.ts +35 -0
  966. package/dist/services/update.service.d.ts.map +1 -0
  967. package/dist/services/update.service.js +449 -0
  968. package/dist/services/update.service.js.map +1 -0
  969. package/dist/services/usage.service.d.ts +49 -0
  970. package/dist/services/usage.service.d.ts.map +1 -0
  971. package/dist/services/usage.service.js +175 -0
  972. package/dist/services/usage.service.js.map +1 -0
  973. package/dist/services/vram-scheduler.d.ts +39 -0
  974. package/dist/services/vram-scheduler.d.ts.map +1 -0
  975. package/dist/services/vram-scheduler.js +84 -0
  976. package/dist/services/vram-scheduler.js.map +1 -0
  977. package/dist/utils/anthropic-mapper.d.ts +20 -0
  978. package/dist/utils/anthropic-mapper.d.ts.map +1 -0
  979. package/dist/utils/anthropic-mapper.js +254 -0
  980. package/dist/utils/anthropic-mapper.js.map +1 -0
  981. package/dist/utils/api-key-crypto.d.ts +10 -0
  982. package/dist/utils/api-key-crypto.d.ts.map +1 -0
  983. package/dist/utils/api-key-crypto.js +52 -0
  984. package/dist/utils/api-key-crypto.js.map +1 -0
  985. package/dist/utils/api-key-id.d.ts +13 -0
  986. package/dist/utils/api-key-id.d.ts.map +1 -0
  987. package/dist/utils/api-key-id.js +51 -0
  988. package/dist/utils/api-key-id.js.map +1 -0
  989. package/dist/utils/async-handler.d.ts +5 -0
  990. package/dist/utils/async-handler.d.ts.map +1 -0
  991. package/dist/utils/async-handler.js +9 -0
  992. package/dist/utils/async-handler.js.map +1 -0
  993. package/dist/utils/client-ip.d.ts +28 -0
  994. package/dist/utils/client-ip.d.ts.map +1 -0
  995. package/dist/utils/client-ip.js +184 -0
  996. package/dist/utils/client-ip.js.map +1 -0
  997. package/dist/utils/engine-event-parse.d.ts +24 -0
  998. package/dist/utils/engine-event-parse.d.ts.map +1 -0
  999. package/dist/utils/engine-event-parse.js +192 -0
  1000. package/dist/utils/engine-event-parse.js.map +1 -0
  1001. package/dist/utils/engine-session.d.ts +25 -0
  1002. package/dist/utils/engine-session.d.ts.map +1 -0
  1003. package/dist/utils/engine-session.js +80 -0
  1004. package/dist/utils/engine-session.js.map +1 -0
  1005. package/dist/utils/file-sniff.d.ts +16 -0
  1006. package/dist/utils/file-sniff.d.ts.map +1 -0
  1007. package/dist/utils/file-sniff.js +151 -0
  1008. package/dist/utils/file-sniff.js.map +1 -0
  1009. package/dist/utils/fs-safe.d.ts +5 -0
  1010. package/dist/utils/fs-safe.d.ts.map +1 -0
  1011. package/dist/utils/fs-safe.js +26 -0
  1012. package/dist/utils/fs-safe.js.map +1 -0
  1013. package/dist/utils/id.d.ts +7 -0
  1014. package/dist/utils/id.d.ts.map +1 -0
  1015. package/dist/utils/id.js +28 -0
  1016. package/dist/utils/id.js.map +1 -0
  1017. package/dist/utils/index.d.ts +14 -0
  1018. package/dist/utils/index.d.ts.map +1 -0
  1019. package/dist/utils/index.js +56 -0
  1020. package/dist/utils/index.js.map +1 -0
  1021. package/dist/utils/ip-match.d.ts +15 -0
  1022. package/dist/utils/ip-match.d.ts.map +1 -0
  1023. package/dist/utils/ip-match.js +133 -0
  1024. package/dist/utils/ip-match.js.map +1 -0
  1025. package/dist/utils/list-sort.d.ts +14 -0
  1026. package/dist/utils/list-sort.d.ts.map +1 -0
  1027. package/dist/utils/list-sort.js +58 -0
  1028. package/dist/utils/list-sort.js.map +1 -0
  1029. package/dist/utils/logger.d.ts +3 -0
  1030. package/dist/utils/logger.d.ts.map +1 -0
  1031. package/dist/utils/logger.js +38 -0
  1032. package/dist/utils/logger.js.map +1 -0
  1033. package/dist/utils/message-content.d.ts +24 -0
  1034. package/dist/utils/message-content.d.ts.map +1 -0
  1035. package/dist/utils/message-content.js +68 -0
  1036. package/dist/utils/message-content.js.map +1 -0
  1037. package/dist/utils/model-allowlist.d.ts +14 -0
  1038. package/dist/utils/model-allowlist.d.ts.map +1 -0
  1039. package/dist/utils/model-allowlist.js +84 -0
  1040. package/dist/utils/model-allowlist.js.map +1 -0
  1041. package/dist/utils/openai-mapper.d.ts +19 -0
  1042. package/dist/utils/openai-mapper.d.ts.map +1 -0
  1043. package/dist/utils/openai-mapper.js +182 -0
  1044. package/dist/utils/openai-mapper.js.map +1 -0
  1045. package/dist/utils/path-safe.d.ts +4 -0
  1046. package/dist/utils/path-safe.d.ts.map +1 -0
  1047. package/dist/utils/path-safe.js +49 -0
  1048. package/dist/utils/path-safe.js.map +1 -0
  1049. package/dist/utils/prisma-bytes.d.ts +8 -0
  1050. package/dist/utils/prisma-bytes.d.ts.map +1 -0
  1051. package/dist/utils/prisma-bytes.js +14 -0
  1052. package/dist/utils/prisma-bytes.js.map +1 -0
  1053. package/dist/utils/request-meta.d.ts +12 -0
  1054. package/dist/utils/request-meta.d.ts.map +1 -0
  1055. package/dist/utils/request-meta.js +26 -0
  1056. package/dist/utils/request-meta.js.map +1 -0
  1057. package/dist/utils/responses-mapper.d.ts +9 -0
  1058. package/dist/utils/responses-mapper.d.ts.map +1 -0
  1059. package/dist/utils/responses-mapper.js +56 -0
  1060. package/dist/utils/responses-mapper.js.map +1 -0
  1061. package/dist/utils/role-normalize.d.ts +9 -0
  1062. package/dist/utils/role-normalize.d.ts.map +1 -0
  1063. package/dist/utils/role-normalize.js +29 -0
  1064. package/dist/utils/role-normalize.js.map +1 -0
  1065. package/dist/utils/ssrf.d.ts +11 -0
  1066. package/dist/utils/ssrf.d.ts.map +1 -0
  1067. package/dist/utils/ssrf.js +114 -0
  1068. package/dist/utils/ssrf.js.map +1 -0
  1069. package/dist/utils/stream.d.ts +7 -0
  1070. package/dist/utils/stream.d.ts.map +1 -0
  1071. package/dist/utils/stream.js +70 -0
  1072. package/dist/utils/stream.js.map +1 -0
  1073. package/dist/utils/vision-remote.d.ts +28 -0
  1074. package/dist/utils/vision-remote.d.ts.map +1 -0
  1075. package/dist/utils/vision-remote.js +206 -0
  1076. package/dist/utils/vision-remote.js.map +1 -0
  1077. package/docs/en/README.md +25 -0
  1078. package/docs/en/admin.md +44 -0
  1079. package/docs/en/api.md +78 -0
  1080. package/docs/en/architecture.md +44 -0
  1081. package/docs/en/catalog.md +30 -0
  1082. package/docs/en/cli.md +180 -0
  1083. package/docs/en/configuration.md +52 -0
  1084. package/docs/en/development.md +49 -0
  1085. package/docs/en/getting-started.md +64 -0
  1086. package/docs/en/keys.md +30 -0
  1087. package/docs/en/media.md +38 -0
  1088. package/docs/en/operations.md +40 -0
  1089. package/docs/en/runtimes.md +20 -0
  1090. package/docs/zh/README.md +25 -0
  1091. package/docs/zh/admin.md +44 -0
  1092. package/docs/zh/api.md +78 -0
  1093. package/docs/zh/architecture.md +44 -0
  1094. package/docs/zh/catalog.md +30 -0
  1095. package/docs/zh/cli.md +180 -0
  1096. package/docs/zh/configuration.md +52 -0
  1097. package/docs/zh/development.md +49 -0
  1098. package/docs/zh/getting-started.md +62 -0
  1099. package/docs/zh/keys.md +30 -0
  1100. package/docs/zh/media.md +38 -0
  1101. package/docs/zh/operations.md +40 -0
  1102. package/docs/zh/runtimes.md +20 -0
  1103. package/package.json +108 -0
  1104. package/prisma/migrations/20260714084159_init_sqlite/migration.sql +106 -0
  1105. package/prisma/migrations/20260714090338_safe_mode_admin/migration.sql +36 -0
  1106. package/prisma/migrations/20260714120000_ip_whitelist_blacklist/migration.sql +19 -0
  1107. package/prisma/migrations/20260714220000_chat_conversations/migration.sql +22 -0
  1108. package/prisma/migrations/20260714230000_conversation_context/migration.sql +6 -0
  1109. package/prisma/migrations/20260715140000_admin_otp_session/migration.sql +29 -0
  1110. package/prisma/migrations/20260715150000_chat_jobs/migration.sql +33 -0
  1111. package/prisma/migrations/20260715161921_api_responses_assistants/migration.sql +80 -0
  1112. package/prisma/migrations/20260716060000_media_assets/migration.sql +25 -0
  1113. package/prisma/migrations/20260716070000_media_jobs/migration.sql +17 -0
  1114. package/prisma/migrations/20260813160000_grok_session_aliases/migration.sql +14 -0
  1115. package/prisma/migrations/20260924180000_api_key_allowed_models/migration.sql +2 -0
  1116. package/prisma/migrations/20260924190000_rename_grok_session_columns/migration.sql +5 -0
  1117. package/prisma/migrations/migration_lock.toml +3 -0
  1118. package/prisma/schema.prisma +391 -0
  1119. package/prisma/seed.ts +71 -0
  1120. package/public/admin/allowed-extensions.js +41 -0
  1121. package/public/admin/app.js +9980 -0
  1122. package/public/admin/assets/logo.svg +37 -0
  1123. package/public/admin/boot.js +2551 -0
  1124. package/public/admin/boot.js.map +1 -0
  1125. package/public/admin/disabled.html +131 -0
  1126. package/public/admin/i18n.js +2442 -0
  1127. package/public/admin/index.html +26 -0
  1128. package/public/admin/styles.css +5764 -0
  1129. package/public/admin/vendor/marked.min.js +6 -0
  1130. package/public/admin/vendor/purify.min.js +3 -0
  1131. package/scripts/api-audit-run.sh +52 -0
  1132. package/scripts/cli-audit-run.sh +214 -0
  1133. package/scripts/generate-allowed-extensions.cjs +23 -0
  1134. package/scripts/install.sh +34 -0
  1135. package/scripts/omni-openai-worker.mjs +144 -0
  1136. package/scripts/postinstall.cjs +5 -0
  1137. package/scripts/prepare.cjs +102 -0
  1138. package/scripts/smoke.sh +32 -0
  1139. package/scripts/start-tiny-media-worker.sh +14 -0
  1140. package/scripts/tiny-media-worker.py +491 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boot.js","sources":["../../admin/src/full/i18n.js","../../admin/src/full/allowed-extensions.js","../../admin/src/full/app.js"],"sourcesContent":["/** Admin i18n — default: system zh* → zh-Hant, else en; manual choice wins. */\nconst LANG_KEY = 'gog_admin_lang';\n\nconst dict = {\n en: {\n brand: 'YSK Omni',\n brandSub: 'Admin Panel',\n loginTitle: 'Admin',\n loginLabel: 'API Key',\n loginOtpLabel: 'One-time login code',\n loginBtn: 'Sign in',\n loginCmdHint: 'Get a key from the terminal:',\n loginOtpHint: 'Generate a code in terminal (required every login):',\n loginOtpExpiry: 'Code expires in 5 minutes and can be used only once.',\n loginOtpFail: 'Invalid or expired code',\n loginLostKey: 'Lost old key? Create a new admin key (plaintext is not stored).',\n loginCopy: 'Copy',\n loginCopied: 'Copied',\n needKey: 'Enter API key',\n needOtp: 'Enter the one-time code from the terminal',\n logout: 'Log out',\n shell: {\n menu: 'Open menu',\n closeMenu: 'Close menu',\n },\n nav: {\n dashboard: 'Dashboard',\n chat: 'Chat',\n chats: 'Chat logs',\n keys: 'API Keys',\n documents: 'Documents',\n media: 'Media',\n catalog: 'Catalog',\n runtimes: 'Runtimes',\n audit: 'Audit Logs',\n settings: 'Safety',\n apiFeatures: 'API features',\n usage: 'Usage & Limits',\n ddos: 'DDoS Center',\n queue: 'Queue',\n pm2: 'PM2',\n system: 'System',\n support: 'Support',\n },\n queue: {\n title: 'Chat queue',\n subtitle: 'Pause, drain, requeue, and tune concurrency.',\n paused: 'Paused',\n running: 'Consuming',\n drain: 'Drain mode',\n mode: 'Mode',\n modeOff: 'Disabled',\n depth: 'Depth',\n queued: 'Queued',\n leased: 'Leased',\n activeJobs: 'Running',\n dead: 'Dead letter',\n oldest: 'Oldest wait',\n concurrency: 'Per-key / global',\n worker: 'In-process workers',\n workerInstance: 'Worker instance',\n workerInstanceHint: 'This process’s consumer ID (lease owner). Changes on restart.',\n kpiActiveSub: '{n} active in this process',\n consumer: 'Consumer',\n admission: 'Admission',\n accepting: 'Accepting jobs',\n pause: 'Pause',\n resume: 'Resume',\n drainBtn: 'Drain',\n undrain: 'Stop drain',\n savePolicy: 'Save policy',\n refresh: 'Refresh',\n jobs: 'Jobs',\n tabOverview: 'Overview',\n tabJobs: 'Jobs',\n tabPolicy: 'Policy',\n jobsMeta: '{n} matching',\n cancel: 'Cancel',\n requeue: 'Requeue',\n purgeDead: 'Purge DLQ & old jobs',\n purgeTitle: 'Purge finished jobs?',\n purgeConfirm:\n 'Deletes all dead-letter (DLQ) jobs now, plus succeeded / failed / cancelled jobs finished more than 24 hours ago.',\n purgeConfirmBtn: 'Delete',\n purgeDoneTitle: 'Purge complete',\n purgeDoneMsg: 'Deleted {n} job(s).',\n cancelConfirm: 'Cancel this job? If it is running, cancellation is cooperative.',\n empty: 'No jobs match this filter',\n enabled: 'Queue enabled',\n masterOn: 'Queue on',\n masterOff: 'Queue off',\n masterHint: 'Master switch for the durable chat queue. Applies immediately.',\n disabledBanner:\n 'Queue is disabled — new chat requests bypass the queue and run immediately (subject to concurrency limits).',\n globalConcurrency: 'Global concurrency',\n perKeyConcurrency: 'Per-key concurrency',\n maxDepth: 'Max queue depth',\n maxDepthKey: 'Max per key',\n fairness: 'Fairness',\n fifo: 'Global FIFO',\n wrr: 'Weighted round-robin',\n playgroundPriority: 'Playground priority (lower first)',\n defaultPriority: 'Default priority',\n leaseMs: 'Lease (ms)',\n maxWaitMs: 'Max wait (ms)',\n filterTitle: 'Filter jobs',\n filterHint: 'Filter by status. Auto-refreshes.',\n filterStatus: 'Status',\n allStatuses: 'All statuses',\n filterDead: 'Dead letter (DLQ)',\n filterQueued: 'Queued',\n filterRunning: 'Running / leased',\n filterFailed: 'Failed',\n filterSucceeded: 'Succeeded',\n filterCancelled: 'Cancelled',\n errorCol: 'Error',\n priorityBtn: 'Priority',\n priorityPh: 'Priority (0–1000, lower first)',\n dlqTitle: 'Dead letter queue',\n dlqHint: 'Jobs that exhausted retries — requeue or purge when ready.',\n viewDlq: 'View DLQ',\n statusPanel: 'Runtime status',\n statusPanelHint: 'Live consumer, admission, and worker identity. Auto-refreshes every few seconds.',\n policyTitle: 'Queue policy',\n policyHint: 'Pick a scheme or fine-tune values. Save to apply. Editing pauses auto-refresh.',\n presetTitle: 'Policy schemes',\n presetHint: 'One-click presets. Active = matches form · Saved = currently stored.',\n presetRelaxed: 'Relaxed',\n presetBalanced: 'Balanced',\n presetStrict: 'Strict',\n presetCustom: 'Custom',\n presetRelaxedHint:\n 'Higher concurrency and deeper queues — better for multi-key playgrounds and burst traffic.',\n presetBalancedHint:\n 'Default production balance: fair round-robin, moderate depth, one job per key.',\n presetStrictHint:\n 'Tight limits + global FIFO — protects the host when traffic is untrusted or resource is scarce.',\n presetCustomHint: 'Values do not match a built-in scheme. Adjust fields or pick a scheme above.',\n presetActiveLabel: 'Active: {name}',\n presetFormLabel: 'Draft: {name}',\n presetTagActive: 'Active',\n presetTagDraft: 'Draft',\n presetTagSaved: 'Saved',\n hintGlobalConc: 'Max jobs running at once across all keys',\n hintPerKeyConc: 'Max concurrent jobs for a single API key',\n hintMaxDepth: 'Reject new jobs when total queue is full',\n hintMaxDepthKey: 'Reject when this key has too many waiting/running jobs',\n hintFairness: 'WRR shares capacity across keys; FIFO is global order by priority/time',\n hintLease: 'How long a worker holds a job before reclaim',\n hintMaxWait: 'Client wait timeout while queued',\n colJob: 'Job / request',\n colSource: 'Source',\n colStatus: 'Status',\n colModel: 'Model',\n colPri: 'Pri',\n colKey: 'API key',\n colTry: 'Try',\n colTime: 'Queued',\n stQueued: 'queued',\n stLeased: 'leased',\n stRunning: 'running',\n stSucceeded: 'succeeded',\n stFailed: 'failed',\n stDead: 'dead',\n stCancelled: 'cancelled',\n srcV1: 'API',\n srcPlayground: 'Playground',\n kpiDepthSub: '{q} queued · {l} leased',\n kpiQueuedSub: 'Waiting for a worker',\n kpiDeadSub: 'Exhausted attempts',\n kpiOldestSub: 'Head of queue wait',\n wait: 'Wait',\n started: 'Started',\n cancelReq: 'Cancel requested',\n },\n chat: {\n title: 'Chat',\n new: 'New chat',\n send: 'Send',\n stop: 'Stop',\n stopped: 'stopped',\n placeholder: 'Message… (Enter to send, Shift+Enter newline)',\n keyMode: 'API key',\n keySelect: 'API key',\n useSessionKey: 'Signed-in admin key',\n useCustomKey: 'Custom key',\n customKey: 'Key',\n includeReasoning: 'Show reasoning',\n resume: 'Resume',\n resumePh: 'Session UUID',\n resumeHint: 'Continue a previous text-engine session',\n fork: 'Fork',\n memory: 'Memory',\n noPlan: 'No plan',\n permission: 'Permission',\n effort: 'Effort',\n effortDefault: 'Default',\n effort_none: 'None',\n effort_minimal: 'Minimal',\n effort_low: 'Low',\n effort_medium: 'Medium',\n effort_high: 'High',\n effort_xhigh: 'X high',\n effort_max: 'Max',\n tokens: 'Tokens',\n cacheTokens: 'cache',\n cost: 'Cost',\n reasoning: 'Thinking',\n needKey: 'Enter or select an API key',\n attach: 'Upload',\n attachLibrary: 'From library',\n attachHint: 'Drop files anywhere on this page, upload, or pick from library',\n dropTitle: 'Drop files to attach',\n dropHint: 'Release to upload — same formats as the attach button',\n formatsLabel: 'Formats',\n formatsHint:\n 'txt, md, csv, json, xml, html, pdf, images (png/jpg/webp/gif), code (js/ts/py/go/rs/java/c/cpp/css/yml/sql/sh…)',\n formatsReject: 'Unsupported type: {name}. Allowed: {formats}',\n libraryTitle: 'Previously uploaded files',\n librarySubtitle: 'Select files owned by the current API key (same formats as upload).',\n librarySearch: 'Search by name…',\n libraryEmpty: 'No matching files for this key',\n libraryAdd: 'Add selected',\n librarySelected: '{n} selected',\n libraryAlready: 'Already attached',\n libraryLoadFail: 'Could not load documents',\n uploading: 'Uploading…',\n uploadFail: 'Upload failed',\n uploadProgress: 'Uploading {name}',\n uploadProgressMulti: 'Uploading {name} ({i}/{n})',\n emptyTitle: 'Start a conversation',\n emptyHint:\n 'Send a message or attach files. Choose an image, video, or speech model to generate media in the conversation.',\n needContent: 'Type a message or attach at least one file',\n needAudioAttach: 'Attach an audio file to transcribe',\n mediaBusy_image: 'Generating image…',\n mediaBusy_video: 'Generating video…',\n mediaBusy_tts: 'Generating speech…',\n mediaBusy_stt: 'Transcribing…',\n mediaDone_image: 'Image saved to the media library.',\n mediaDone_video: 'Video saved to the media library.',\n mediaDone_tts: 'Speech saved to the media library.',\n mediaDone_stt: 'Transcription saved.',\n openInLibrary: 'Open in library',\n modelKind_text: 'Text',\n modelKind_image: 'Image',\n modelKind_video: 'Video',\n modelKind_tts: 'Speech',\n modelKind_stt: 'Transcribe',\n tooManyFiles: 'Too many files (max 10 per message)',\n fileOnlyPrompt: 'Please review the attached files.',\n removeFile: 'Remove',\n docs: 'Attachments',\n you: 'You',\n assistant: 'Assistant',\n streaming: 'Streaming…',\n emptyReply: '(empty reply)',\n systemPrompt: 'System prompt',\n systemPlaceholder: 'Optional system instructions for the model…',\n systemHint: 'Sent as a system message on every turn. Not shown in the chat bubbles.',\n history: 'History',\n historyEmpty: 'No saved conversations yet',\n historySearch: 'Search topics…',\n historyOpen: 'Show history',\n historyClose: 'Close history',\n rename: 'Rename',\n renamePh: 'Conversation topic',\n untitled: 'Untitled chat',\n deleteConversation: 'Delete',\n deleteConfirm: 'Delete this conversation? This cannot be undone.',\n saveFail: 'Could not save conversation',\n loadFail: 'Could not load conversation',\n historyPrev: 'Previous',\n historyNext: 'Next',\n historyPage: 'Page {n} / {total}',\n msgs: '{n} messages',\n settings: 'Settings',\n settingsHide: 'Hide settings',\n compress: 'Summarize for context',\n compressConfirm:\n 'Generate a conversation summary for later turns? Your full chat history stays on screen. Only the model context is shortened. This uses one model call.',\n compressing: 'Summarizing…',\n compressNeedMore:\n 'Need at least 3 messages (or 2 long ones) to summarize. Continue chatting, then try again.',\n compressFail: 'Could not create summary',\n compressNeedSummary: 'Create a summary first (Summarize for context).',\n compressedBadge: 'Summary',\n compressOk: 'Summary ready — full history kept. Context mode set to summary.',\n compressBusy: 'Wait for the current reply to finish',\n compressResultTitle: 'Conversation summary',\n compressView: 'View summary',\n summaryMeta: 'Created: {when} · Based on {n} messages',\n ctxPolicyTitle: 'Model context',\n ctxRemark:\n 'Full messages stay visible. This only controls what is sent to the model next.',\n ctxMode: 'Context',\n ctxModeFull: 'Full history',\n ctxModeSummary: 'Summary + recent',\n ctxModeRecent: 'Recent only',\n ctxModeFullLabel: 'Sending full history to the model',\n ctxModeSummaryLabel: 'Sending summary + last {n} messages',\n ctxModeRecentLabel: 'Sending last {n} messages only',\n ctxRecentN: 'Recent N',\n ctxLongHint:\n 'Long thread detected — consider Summary or Recent to reduce tokens and lag.',\n loadOlder: 'Load {n} earlier messages',\n showMore: 'Show more',\n showLess: 'Show less',\n copy: 'Copy',\n copied: 'Copied',\n copyFail: 'Copy failed',\n },\n status: {\n success: 'success',\n error: 'error',\n timeout: 'timeout',\n pending: 'pending',\n active: 'active',\n finished: 'finished',\n online: 'online',\n stopped: 'stopped',\n },\n dash: {\n title: 'Dashboard',\n subtitle: 'Traffic, queue, safety, and protection at a glance.',\n last24: 'Requests (24h)',\n totalChat: 'Total chats',\n success: 'Success',\n errors: 'Errors / timeout',\n docs: 'Documents',\n keys: 'Active keys',\n concurrent: 'Engine concurrency',\n recent: 'Recent API chats',\n empty: 'No data yet',\n emptyModels: 'No model traffic in the last 24h',\n updated: 'Updated',\n refresh: 'Refresh',\n viewAll: 'View all',\n openDdos: 'DDoS center',\n openSettings: 'Safety',\n openQueue: 'Open queue',\n kpi24h: 'Requests (24h)',\n kpi24hSub: '{ok} ok · {err} errors',\n kpiSuccessRate: 'Success rate (24h)',\n kpiSuccessRateSub: 'All-time {all}%',\n kpiErrors: 'Errors (24h)',\n kpiErrorsSub: 'All-time {all}',\n kpiKeys: 'API keys',\n kpiKeysSub: 'Active / total',\n kpiDocs: 'Documents',\n kpiMedia: 'Media assets',\n kpiMediaSub: '{n} in 24h',\n kpiDocsSub: 'Stored files',\n kpiConv: 'Playground threads',\n kpiConvSub: '{n} updated in 24h',\n kpiSessions: 'OTP sessions',\n kpiSessionsSub: 'Active admin logins',\n kpiConcurrent: 'Engine concurrency',\n kpiConcurrentSub: 'Active / max slots',\n kpiQueue: 'Chat queue',\n kpiQueueSub: 'Depth · running / max · dead',\n kpiQueueSubLive: '{run}/{max} run · {dead} dead{wait}',\n kpiQueuePaused: 'Paused',\n kpiQueueDrain: 'Drain',\n kpiQueueOff: 'Disabled',\n kpiSafe: 'Global safe',\n kpiSafeOn: 'On',\n kpiSafeOff: 'Off',\n kpiSafeSub: '{tools} · turns {turns} · {model}',\n kpiSafeSubEmpty: 'Settings unavailable',\n queuePanel: 'Chat queue',\n queueState: 'State',\n queueLive: 'Live',\n qQueued: 'Queued',\n qRunning: 'Running',\n qDead: 'Dead',\n qSucceeded: 'Succeeded',\n qWorker: 'Worker',\n qWorkerActive: 'active slots',\n qOldest: 'oldest wait',\n qUnavailable: 'Queue stats unavailable',\n safety: 'Safety settings',\n globalSafe: 'Global safe mode',\n safeTools: 'Tools',\n safeTurns: 'Max turns',\n safeTimeout: 'Timeout',\n defaultModel: 'Default model',\n safetyHint:\n 'Affects safe-mode keys and forced-safe traffic. Playground OTP sessions use agent mode unless global safe is on.',\n protection: 'Protection',\n autoBan: 'Auto-ban',\n on: 'On',\n off: 'Off',\n ruleAuth: 'Auth',\n ruleRate: '429',\n ruleConn: 'Conn',\n ruleVelocity: 'Velocity',\n bans: 'Blacklist',\n blocked: 'Blocked hits',\n rateHits: 'Rate-limit hits',\n liveConn: 'Live connections',\n proxy: 'Proxy IP',\n hops: 'hops',\n limits: 'Key/IP limits',\n models24h: 'Models (24h)',\n runtime: 'Runtime',\n port: 'Listen port',\n defaultPort: 'default',\n env: 'Environment',\n authMode: 'Admin auth',\n authOtp: 'OTP session',\n encryption: 'Encryption',\n ready: 'Ready',\n notReady: 'Not ready',\n },\n chats: {\n title: 'Chat history',\n total: 'Total',\n decrypt: 'Open a row to view decrypted content.',\n search: 'Search',\n searchPh: 'Request ID, key name, model…',\n filterTitle: 'Search & filters',\n filterHint: 'Filter, then open a row for full detail.',\n status: 'Status',\n allStatus: 'All statuses',\n model: 'Model',\n allModels: 'All models',\n apiKey: 'API key',\n allKeys: 'All keys',\n from: 'From',\n to: 'To',\n mode: 'Mode',\n allModes: 'All modes',\n hasDocs: 'Has attachments',\n filter: 'Apply filters',\n reset: 'Reset',\n request: 'Request',\n prompt: 'Prompt',\n response: 'Response',\n time: 'Time',\n attachments: 'Attachments',\n page: 'Page',\n prev: 'Previous',\n next: 'Next',\n perPage: 'Per page',\n detail: 'Chat detail',\n noAttach: 'No attachments',\n openFile: 'Open / preview',\n close: 'Close',\n copyPrompt: 'Copy prompt',\n copyContent: 'Copy content',\n copySystem: 'Copy system prompt',\n copyRawPrompt: 'Copy raw prompt',\n duration: 'Duration',\n stream: 'Stream',\n reasoning: 'Reasoning / thought',\n content: 'Content (output)',\n raw: 'Raw stored response',\n rawPrompt: 'Raw stored prompt',\n userPrompt: 'User / conversation prompt',\n systemPrompt: 'System prompt',\n systemHint: 'Extracted from the stored prompt (system role messages).',\n noSystem: 'No system prompt in this request.',\n hasSystem: 'Has system',\n none: '(none)',\n file: 'file',\n img: 'img',\n previewFailed: 'Preview failed',\n },\n keys: {\n title: 'API Keys',\n new: 'New key',\n searchPh: 'Name or key prefix…',\n name: 'Name',\n role: 'Role',\n mode: 'Mode',\n rate: 'Rate / min',\n status: 'Status',\n created: 'Created',\n edit: 'Edit',\n revoke: 'Revoke',\n confirmRevoke: 'Revoke this key?',\n empty: 'No keys',\n usage24: '24h use',\n maxTurns: 'Max turns',\n timeoutMs: 'Timeout (ms)',\n ipWhitelist: 'IP whitelist',\n ipWhitelistHint: 'One IP or CIDR per line. Empty = allow all IPs.',\n ipWhitelistCol: 'IP allow',\n ipAll: 'All IPs',\n keyOnce: 'Store this key securely — shown once:',\n roleClient: 'client',\n roleAdmin: 'admin',\n roleClientBadge: 'client',\n roleAdminBadge: 'admin',\n modeSafe: 'safe (external)',\n modeAgent: 'agent (full tools)',\n modeSafeBadge: 'safe',\n modeAgentBadge: 'agent',\n ipCount: '{n} IPs',\n ipPlaceholder: '127.0.0.1\\n203.0.113.0/24',\n allowedModels: 'Allowed models',\n allowedModelsHint: 'Select models this key may use. Empty = no restriction. Users list them with GET /v1/models.',\n allowedModelsCol: 'Models',\n modelsAll: 'All models',\n modelsCount: '{n} models',\n modelsExtra: 'Additional model ids',\n modelsExtraHint: 'One model id per line for ids not listed above.',\n modelsPlaceholder: 'org/repo:Q4_K_M',\n },\n docs: {\n title: 'Documents',\n total: 'Total',\n file: 'File',\n mime: 'MIME',\n size: 'Size',\n time: 'Time',\n storage: 'Storage',\n storageDb: 'Database (encrypted)',\n storageFs: 'Filesystem (encrypted)',\n storageHint:\n 'Encrypted storage · DB under {dbMax}, files in {dir} · max {upMax}.',\n download: 'Download',\n downloadFail: 'Download failed',\n binaryPreview:\n 'This is a binary file (e.g. PDF). Preview is not available — please use Download.',\n delete: 'Delete',\n confirmDel: 'Delete this document?',\n detail: 'Document detail',\n preview: 'Preview',\n copy: 'Copy content',\n empty: 'No documents',\n searchPh: 'File name or MIME…',\n page: 'Page',\n prev: 'Previous',\n next: 'Next',\n },\n audit: {\n title: 'Audit logs',\n searchPh: 'Action, resource, IP, key…',\n time: 'Time',\n action: 'Action',\n resource: 'Resource',\n key: 'Key',\n meta: 'Meta',\n empty: 'No logs',\n id: 'ID',\n // keys use _ instead of . so t('audit.actions.xxx') path lookup works\n actions: {\n chat_create: 'Chat create',\n document_upload: 'Document upload',\n document_delete: 'Document delete',\n document_list: 'Document list',\n document_read: 'Document read',\n document_download: 'Document download',\n api_key_create: 'API key create',\n api_key_update: 'API key update',\n api_key_delete: 'API key revoke',\n api_key_list: 'API key list',\n settings_update: 'Settings update',\n chat_admin_view: 'Chat admin view',\n system_update: 'System update',\n system_update_check: 'Update check',\n ip_ban: 'IP ban',\n ip_unban: 'IP unban',\n ddos_policy_update: 'DDoS policy update',\n pm2_start: 'PM2 start',\n pm2_stop: 'PM2 stop',\n pm2_restart: 'PM2 restart',\n pm2_reload: 'PM2 reload',\n pm2_config: 'PM2 config',\n pm2_switch: 'PM2 switch runner',\n playground_chat: 'Playground chat',\n playground_upload: 'Playground upload',\n },\n resources: {\n document: 'Document',\n chat: 'Chat',\n api_key: 'API key',\n settings: 'Settings',\n system: 'System',\n pm2: 'PM2',\n playground: 'Playground',\n ip: 'IP',\n },\n metaStorage: 'Storage',\n metaAsKey: 'As key id',\n metaAsKeyName: 'As key name',\n },\n settings: {\n title: 'Safety settings',\n hint: 'Global safe mode for all keys.',\n globalSafe: 'Global safe mode',\n globalSafeHint: 'On = all keys safe. Off = each key’s own mode.',\n masterOn: 'Safe mode on',\n masterOff: 'Safe mode off',\n disabledBanner: 'Global safe is off — keys use their own safe/agent mode.',\n tools: 'Tools mode',\n toolsHint: 'none: no shell/web/write. readonly: read/search only.',\n toolsNone: 'none',\n toolsReadonly: 'readonly',\n maxTurns: 'Max turns',\n maxTurnsHint: 'Safe-mode steps. Chat 3–6 · API 8–12 · multi-step 15–40.',\n timeout: 'Timeout (ms)',\n timeoutHint: 'Safe-mode deadline. 60s–120s normal · 300s–600s long jobs.',\n defaultModel: 'Default model',\n defaultModelHint: 'When client omits model.',\n modelSource: 'Local engines',\n refreshModels: 'Refresh models',\n panel: 'Admin Panel',\n save: 'Save',\n saved: 'Saved',\n guideTitle: 'Presets',\n guideIntro: 'Apply, then tweak if needed.',\n guideApply: 'Apply',\n guideActive: 'Applied',\n guideApplyConfirm: 'Apply “{name}” and save? Current values will be replaced.',\n guideApplied: 'Preset saved',\n chipGlobalOn: 'Safe: On',\n chipGlobalOff: 'Safe: Off',\n scLocalTitle: 'Local playground',\n scLocalDesc: 'Full tools on your machine.',\n scLocalDetail: 'Safe OFF · agent keys.',\n scProdTitle: 'Public API',\n scProdDesc: 'Least privilege for apps/customers.',\n scProdDetail: 'Safe ON · tools none · turns 8–12 · 60–120s.',\n scCodeTitle: 'Coding agent',\n scCodeDesc: 'Trusted host only — edit & run.',\n scCodeDetail: 'Safe OFF · agent keys.',\n scReadTitle: 'Read-only',\n scReadDesc: 'Explain/search code, no writes.',\n scReadDetail: 'Safe ON · tools readonly · turns 8–15 · 120–180s.',\n scChatTitle: 'Q&A only',\n scChatDesc: 'Text answers, no tools.',\n scChatDetail: 'Safe ON · tools none · turns 3–6 · 60s.',\n scLongTitle: 'Long safe tasks',\n scLongDesc: 'Many steps without max-turns fail.',\n scLongDetail: 'Safe ON · none/readonly · turns 20–40 · 300–600s.',\n dangerTitle: 'Danger zone',\n disablePanel: 'Disable Admin Panel',\n disablePanelConfirm:\n 'Disable panel and sign out? Re-enable: ysk-omni admin on',\n disablePanelDone: 'Panel disabled. Re-enable: ysk-omni admin on',\n panelOffHint: 'Turn off here. Re-enable on server: ysk-omni admin on',\n panelStatus: 'Status',\n panelOn: 'On',\n panelOff: 'Off',\n },\n apiFeatures: {\n title: 'API features',\n intro: 'Toggle protocols & capabilities · applies in ~2s · no restart.',\n tabProtocols: 'Protocols',\n tabMedia: 'Media',\n tabCaps: 'Capabilities',\n tabEmu: 'Emulation',\n kpiEnabled: 'Enabled',\n kpiEnabledSub: 'Flags currently on',\n groupMeta: '{on} / {n} enabled',\n groupProtocols: 'Protocol surfaces',\n groupMedia: 'Media APIs (OpenAI-compatible)',\n groupCaps: 'Engine capabilities',\n groupEmu: 'Emulation & safety',\n presetOpen: 'Preset: Open',\n presetLocked: 'Preset: Locked',\n presetDev: 'Preset: Dev',\n presetConfirm:\n 'Apply feature preset “{name}”? This overwrites all API feature flags.',\n flag: {\n openaiChat: 'OpenAI Chat Completions',\n openaiResponses: 'OpenAI Responses',\n anthropicMessages: 'Anthropic Messages',\n imagesApi: 'Images API',\n filesOpenAiAlias: 'Files API alias',\n videoApi: 'Videos API (async jobs)',\n audioApi: 'Audio API (speech / STT)',\n tools: 'Tools / function calling',\n structuredOutput: 'Structured output (--json-schema)',\n vision: 'Vision / image parts (--prompt-json)',\n reasoningEffort: 'Reasoning effort',\n webSearch: 'Web search tools',\n subagents: 'Subagents',\n planMode: 'Plan mode',\n memory: 'Cross-session memory',\n sessionResume: 'Session resume / continue',\n bestOfN: 'best-of-n (removed)',\n checkLoop: 'Self-check loop (removed)',\n systemOverride: 'System prompt override',\n rules: 'Extra rules',\n permissionMode: 'Permission mode',\n sandbox: 'Sandbox profile',\n usageEstimate: 'Estimate token usage',\n assistantsEmulation: 'Assistants-lite (local)',\n strictSampling: 'Strict sampling (reject temperature…)',\n forceDisableToolsInSafe: 'Force tool limits in safe mode',\n },\n hint: {\n openaiChat: 'POST /v1/chat/completions',\n openaiResponses: 'POST /v1/responses',\n anthropicMessages: 'POST /v1/messages',\n imagesApi: 'POST /v1/images/generations + /edits (agent key)',\n filesOpenAiAlias: 'POST/GET /v1/files → documents + media store',\n videoApi: 'POST /v1/videos + poll GET /v1/videos/:id',\n audioApi: 'POST /v1/audio/speech + /transcriptions (needs provider)',\n tools: 'Maps tools to the local engine tool list',\n structuredOutput: 'response_format / json_schema',\n vision: 'image_url content parts',\n reasoningEffort: '--reasoning-effort',\n webSearch: 'When off: --disable-web-search',\n subagents: '--no-subagents when off',\n planMode: '--no-plan when off',\n memory: '--experimental-memory',\n sessionResume: '--resume / --continue',\n bestOfN: 'Deprecated — this flag is rejected',\n checkLoop: 'Deprecated — this flag is rejected',\n systemOverride: '--system-prompt-override',\n rules: '--rules',\n permissionMode: '--permission-mode',\n sandbox: '--sandbox',\n usageEstimate: 'Fill usage with char/4 estimates',\n assistantsEmulation: 'Local /v1/assistants + /v1/threads',\n strictSampling: '400 if temperature/top_p/stop sent',\n forceDisableToolsInSafe: 'Keep safe-mode tool policy',\n },\n },\n catalog: {\n title: 'Catalog',\n intro: 'Search and pull models from Hugging Face, then load a local GGUF into llama-server.',\n tabPacks: 'Curated packs',\n tabLocal: 'Local models',\n tabHub: 'Hugging Face',\n kpiLoaded: 'Loaded',\n kpiLoadedSub: 'Engines in VRAM',\n kpiLoadedNone: 'None loaded',\n kpiVram: 'VRAM',\n kpiVramSub: '{used} / {budget} MB estimated',\n kpiLocal: 'On disk',\n kpiLocalSub: 'Registry entries',\n kpiPacks: 'Packs',\n kpiPacksSub: 'Curated catalog',\n filterModality: 'Modality',\n filterAll: 'All',\n colName: 'Model',\n colModality: 'Modality',\n colRuntime: 'Runtime',\n colQuant: 'Quant',\n colVram: 'VRAM',\n colSize: 'Size',\n sizeEst: 'est.',\n colStatus: 'Status',\n colPath: 'Path',\n pull: 'Pull',\n pulling: 'Pulling…',\n pullingBanner: 'Downloading {id}',\n dlQueue: 'Download queue',\n dlQueued: 'Queued',\n dlActive: 'Downloading',\n dlDone: 'Completed',\n dlError: 'Failed',\n dlEta: 'About {time} remaining',\n dlEtaCalc: 'Calculating time remaining',\n dlSpeed: '{speed}/s',\n dlWaiting: 'Waiting for the current download to finish',\n pullAgain: 'Pull again',\n onDisk: 'On disk',\n load: 'Load',\n unload: 'Unload',\n delete: 'Delete',\n deleteConfirm: 'Delete {id} from disk and the local registry?',\n pullSpec: 'Pull a specific model',\n pullSpecPh: 'org/repo or org/repo:Q4_K_M',\n pullSpecBtn: 'Pull',\n pullSpecHint: 'Paste a Hub id. This downloads weights into the local registry.',\n hubBrowse: 'Browse Hub',\n hubBrowseHint:\n 'Search models this gateway can run (llama.cpp, vLLM, diffusion, whisper).',\n hubSearchBtn: 'Search',\n loaded: 'Loaded',\n idle: 'Idle',\n emptyPacks: 'No packs in this filter',\n emptyLocal: 'The local registry is empty — pull a model from Hugging Face',\n emptyLocalHint: 'Open Hugging Face, search or paste org/repo, then Pull.',\n hubHint:\n 'Live Hugging Face Hub REST API (/api/models). Paginated with Link cursors. There is no RSS/Atom feed for the model index.',\n hubSearch: 'Search Hub',\n hubSearchPh: 'Qwen, llama, flux, whisper…',\n hubEmpty: 'No Hub results',\n hubMore: 'Load more',\n hubLoading: 'Loading…',\n downloads: 'Downloads',\n unsupported: 'No local runtime',\n hubFail: 'Hub search failed',\n sync: 'Sync popular',\n syncing: 'Syncing…',\n syncOk: 'Synced {n} popular GGUF models',\n syncAt: 'Last sync {when}',\n syncHint:\n 'Adds the 50 most-downloaded GGUF ids to the list. This does not download files; Pull a row to fetch weights.',\n noQuant: '—',\n pullFail: 'Pull failed',\n pullNoGguf: 'No GGUF file in this repository. It was not added to local models.',\n loadFail: 'Load failed',\n unloadFail: 'Unload failed',\n mod: {\n text: 'Text',\n image: 'Image',\n video: 'Video',\n tts: 'Speech',\n stt: 'Transcribe',\n },\n },\n runtimes: {\n title: 'Runtimes',\n intro:\n 'Install or uninstall inference engines on this host. One-click runs Homebrew, pip, winget, or Docker for this OS. The gateway does not use sudo.',\n kpiInstalled: 'Ready',\n kpiMissing: 'Not installed',\n kpiHost: 'This host',\n kpiArch: 'Architecture',\n filterOs: 'Operating system',\n filterHost: 'This host',\n filterAll: 'All systems',\n osMac: 'macOS',\n osLinux: 'Linux',\n osWin: 'Windows',\n filterMod: 'Modality',\n statusInstalled: 'Installed',\n statusConfigured: 'URL configured',\n statusMissing: 'Not installed',\n statusUnsupported: 'Not for this OS',\n supportFull: 'Supported',\n supportPartial: 'Partial',\n supportNone: 'Not supported',\n copyCmd: 'Copy install command',\n install: 'Install',\n reinstall: 'Reinstall',\n installing: 'Installing…',\n installDone: 'Installed',\n installFail: 'Install failed',\n installLog: 'Install log',\n uninstall: 'Uninstall',\n uninstalling: 'Uninstalling…',\n uninstallDone: 'Uninstalled',\n uninstallFail: 'Uninstall failed',\n uninstallConfirm:\n 'This will run the package manager to remove {name}. The gateway does not use sudo.',\n docs: 'Documentation',\n refresh: 'Re-scan PATH',\n path: 'Detected',\n cmdFor: 'Install on {os}',\n empty: 'No runtimes match this filter',\n llamacpp: 'Local GGUF text via llama-server',\n vllm: 'High-throughput GPU serving for Hugging Face safetensors',\n mlx: 'Native Apple Silicon text (mlx_lm.server)',\n ollama: 'Convenient GGUF runner with an OpenAI /v1 port',\n ffmpeg: 'Media transcode and playable video fixtures',\n whisper: 'Speech-to-text worker (OpenAI transcriptions)',\n kokoro: 'Text-to-speech worker (OpenAI speech)',\n comfy: 'Image and video worker behind an OpenAI-compat adapter',\n },\n media: {\n title: 'Media library',\n intro: 'Studio, assets, and video jobs. Needs imagesApi / tools (videoApi for video).',\n tabStudio: 'Studio',\n tabAssets: 'Assets',\n tabJobs: 'Jobs',\n kpiAssetsSub: 'Stored media files',\n kpiJobsSub: 'Video generation jobs',\n kpiStudioSub: 'Generate, edit, or image-to-video',\n assets: 'Assets',\n jobs: 'Video jobs',\n empty: 'No media assets yet',\n jobsEmpty: 'No video jobs yet',\n kind: 'Kind',\n bytes: 'Size',\n provider: 'Provider',\n providerPh: 'Provider name…',\n prompt: 'Prompt',\n created: 'Created',\n status: 'Status',\n preview: 'Preview',\n previewUnsupported: 'This format cannot be previewed in the browser. Please download the file.',\n previewFail: 'Failed to load preview',\n previewTruncated: 'preview truncated',\n download: 'Download',\n delete: 'Delete',\n deleteConfirm: 'Soft-delete this media asset?',\n allKinds: 'All kinds',\n searchPh: 'Prompt, filename, MIME, provider, or ID…',\n from: 'From',\n to: 'To',\n generate: 'Generate image',\n generateTitle: 'Generate image',\n studioTitle: 'Media studio',\n studioHint:\n 'Create images, speech, transcriptions, edit images, or start video jobs. Execution limits follow Safety settings. Requires imagesApi and tools (audioApi for speech/transcription, videoApi for video).',\n generateHint:\n 'Uses the local media worker (image, speech, transcription, video).',\n generatePrompt: 'Prompt',\n generatePromptPh: 'Describe the image you want to create…',\n generateSize: 'Size',\n aspectRatio: 'Aspect ratio',\n aspectHint: 'aspect_ratio values (not OpenAI pixel sizes)',\n generateN: 'Count',\n outputFormat: 'File format',\n outputFormatHint: 'The gateway converts automatically after generation',\n nHint: 'The gateway runs sequential generations (1–4)',\n generateKey: 'API key',\n generateKeySession: 'Signed-in admin session',\n generateSubmit: 'Generate',\n generateBusy: 'Generating… this may take a minute',\n generateOk: 'Image generated. See the assets list below.',\n generateFail: 'Image generation failed',\n generateNeedPrompt: 'Please enter a prompt',\n modeGenerate: 'Generate',\n modeEdit: 'Edit',\n modeVideo: 'Video',\n modeSpeech: 'Speech',\n modeTranscribe: 'Transcribe',\n speechSubmit: 'Generate speech',\n speechBusy: 'Synthesizing speech…',\n speechOk: 'Speech saved. See the assets list.',\n speechPromptPh: 'Text to speak…',\n transcribeSubmit: 'Transcribe',\n transcribeBusy: 'Transcribing…',\n transcribeOk: 'Transcription saved. See the assets list.',\n transcribeNeedAudio: 'Select or drop an audio file to transcribe',\n dropTitleAudio: 'Drop an audio file here',\n dropHintAudio: 'WAV, MP3, M4A, OGG, or FLAC',\n sourceNeedAudio: 'Please provide an audio file',\n libraryFormatsAudio: 'Audio only (WAV, MP3, M4A, OGG, FLAC…)',\n modelDefault: 'system default',\n modelEmpty: 'No local models reported',\n modelHint: 'All local registry models; system default is pre-selected',\n editSubmit: 'Edit image',\n editBusy: 'Editing…',\n editOk: 'Image edited. See the assets list below.',\n editNeedImage: 'Select or drop a source image to edit',\n editImage: 'Source image',\n editImageHint: 'Required for image_edit',\n editPromptPh: 'Describe the changes to apply…',\n videoSubmit: 'Create video job',\n videoBusy: 'Queuing video job…',\n videoOk: 'Video job queued. See the Jobs tab.',\n videoVoice: 'Voice',\n videoVoiceNone: 'No speech',\n videoVoiceHint: 'Optional preset voice — uses reference_to_video',\n videoDuration: 'Duration',\n videoDurationHint: 'Video duration: 1–15 seconds',\n videoSource: 'Source frame (optional)',\n videoSourceHint:\n 'Optional. If omitted, a frame is generated from the prompt first, then animated.',\n videoNoSource: 'Auto-generate frame from prompt',\n videoPromptPh: 'Describe camera motion and the shot…',\n sourceTitle: 'Source image',\n sourceHint:\n 'Drag and drop an image, choose a local file, or pick any image from Documents or Media assets.',\n dropzoneAria: 'Drop zone for source image',\n dropTitle: 'Drop an image here',\n dropHint: 'Or choose a local file / pick from the system library',\n dropTitleVideo: 'Drop a source frame (optional)',\n dropHintVideo:\n 'Optional for video. Empty source generates a frame from the prompt first.',\n pickFile: 'Choose file',\n pickLibrary: 'System library',\n clearSource: 'Clear',\n sourceNeedImage: 'Please provide an image file (PNG, JPEG, WebP, GIF…)',\n sourceKindUpload: 'Upload',\n sourceKindAsset: 'Media asset',\n sourceKindDocument: 'Document',\n libraryTitle: 'Select source file',\n librarySubtitle:\n 'Any image stored in Documents or Media assets on this gateway.',\n libraryTabDocs: 'Documents',\n libraryTabAssets: 'Media assets',\n librarySearch: 'Search by name, MIME, or ID…',\n libraryFormats: 'Images only (PNG, JPEG, WebP, GIF, …)',\n libraryEmpty: 'No matching files',\n librarySelect: 'Use selected',\n libraryLoadFail: 'Failed to load library',\n },\n usage: {\n title: 'Usage & anti-abuse',\n window: 'Window',\n requests: 'Requests',\n success: 'Success',\n errors: 'Errors',\n errorRate: 'Error rate',\n byModel: 'By model',\n byKey: 'Per API key',\n rateLimit: 'Limit / min',\n util: 'Est. utilization',\n lastUsed: 'Last used',\n limits: 'Gateway limits',\n global: 'Global max / window',\n ipMax: 'Unauth IP max',\n burst: 'Chat burst (10s)',\n block: 'Auth fail block threshold',\n concurrent: 'Max concurrent engines',\n refresh: 'Refresh',\n },\n ddos: {\n title: 'DDoS control center',\n tabPolicy: 'Policy',\n tabLive: 'Traffic',\n tabBlacklist: 'Blacklist',\n tabEvents: 'Events',\n live: 'Live connections',\n recent: 'Recent requests',\n blacklist: 'IP blacklist',\n stats: 'Abuse stats',\n refresh: 'Refresh',\n pause: 'Pause auto-refresh',\n resume: 'Resume auto-refresh',\n ban: 'Ban IP',\n unban: 'Unban',\n banConfirm: 'Ban this IP?',\n banWhitelistWarn: 'This IP is on the auto-ban whitelist. Ban anyway?',\n unbanConfirm: 'Remove this IP from blacklist?',\n ip: 'IP',\n method: 'Method',\n path: 'Path',\n key: 'API key',\n duration: 'Duration',\n state: 'State',\n ua: 'User-Agent',\n reason: 'Reason',\n source: 'Source',\n expires: 'Expires',\n permanent: 'Permanent',\n addBan: 'Add ban',\n ttl: 'TTL',\n ttlPerm: 'Permanent',\n ttl1h: '1 hour',\n ttl24h: '24 hours',\n ttl7d: '7 days',\n activeConn: 'Active',\n rateHits: 'Rate-limit hits',\n blockedHits: 'Blocked hits',\n autoBans: 'Auto bans',\n topIps: 'Top IPs (recent)',\n emptyLive: 'No active connections',\n emptyBan: 'Blacklist is empty',\n emptyEvents: 'No auto-ban events yet',\n reasonPh: 'Optional reason',\n banReasonDefault: 'manual from admin',\n ipPlaceholder: '1.2.3.4',\n policyTitle: 'Protection policy',\n policyHint:\n 'All thresholds are live — no restart. Env values are only the initial defaults.',\n autoOn: 'Auto-judgment ON',\n autoOff: 'Auto-judgment OFF',\n autoBanMaster: 'Enable automatic IP bans',\n autoBanMasterHint: 'When off, rate limits still apply but IPs are never auto-banned.',\n masterOn: 'Auto-ban on',\n masterOff: 'Auto-ban off',\n disabledBanner:\n 'Automatic IP bans are off — rate limits still apply, but IPs will not be auto-blacklisted.',\n presetTitle: 'Policy profile',\n presetHint: 'Pick a profile or edit fields — custom is detected automatically.',\n presetRelaxed: 'Relaxed',\n presetBalanced: 'Balanced',\n presetStrict: 'Strict',\n presetCustom: 'Custom',\n presetActiveLabel: 'Active: {name}',\n presetFormLabel: 'Form: {name} (unsaved)',\n presetTagActive: 'Active',\n presetTagDraft: 'Draft',\n presetTagSaved: 'Saved',\n presetActiveHint: 'Current profile: {name}. Click Save if you changed other fields.',\n presetCustomHint:\n 'Values do not match Relaxed / Balanced / Strict — treated as Custom.',\n presetUnsavedHint:\n 'Form shows {form}; server still has {saved}. Click Save policy to apply.',\n savePolicy: 'Save policy',\n resetPolicy: 'Reset to env defaults',\n policySaved: 'Protection policy saved. Rate limiters reloaded.',\n policyReset: 'Policy reset to environment defaults.',\n confirmReset: 'Reset all DDoS policy fields to .env defaults?',\n sectionProxy: 'Reverse proxy / CDN',\n proxyHint:\n 'When traffic passes through nginx or Cloudflare, enable trust hops so bans, rate limits, and audit logs use the real client IP — not the proxy IP.',\n proxyTrustHops: 'Trusted proxy hops',\n proxyTrustHopsHint:\n '0 = direct only (ignore headers). 1 = nginx or Cloudflare→app. 2 = Cloudflare→nginx→app.',\n proxyIpSource: 'Client IP source',\n proxyIpSourceHint:\n 'auto tries CF-Connecting-IP, then X-Real-IP, then X-Forwarded-For. Use “socket” only for direct connections.',\n proxySrcAuto: 'Auto (recommended)',\n proxySrcCf: 'Cloudflare (CF-Connecting-IP)',\n proxySrcNginx: 'nginx (X-Real-IP)',\n proxySrcXff: 'X-Forwarded-For only',\n proxySrcSocket: 'TCP socket only (no proxy)',\n trustedProxies: 'Trusted proxy IPs / CIDRs',\n trustedProxiesHint:\n 'Only these peers may set CF-Connecting-IP / X-Real-IP / XFF. Default 127.0.0.1 — add your nginx/LB host if remote. Direct clients cannot spoof headers.',\n sectionLimits: 'Rate limits',\n sectionAuth: 'Failed authentication',\n sectionRate: 'Rate-limit abuse (429)',\n sectionConn: 'Connection flood',\n sectionVelocity: 'Request velocity',\n sectionEscalate: 'Repeat offender escalation',\n sectionWhitelist: 'Auto-ban whitelist',\n whitelistHint: 'One IP or CIDR per line. These IPs are never auto-banned.',\n rateWindow: 'Window (sec)',\n rateMaxKey: 'Max / key',\n rateMaxIp: 'Max / IP (no key)',\n burstWindow: 'Burst window (sec)',\n burstMax: 'Burst max',\n enableRule: 'Enabled',\n threshold: 'Threshold',\n windowSec: 'Window (sec)',\n banMin: 'Ban duration (min)',\n escalateAfter: 'Escalate after N auto-bans',\n escalateMin: 'Escalated ban (min)',\n maxConcurrent: 'Max concurrent / IP',\n velocityMax: 'Max requests',\n eventsTitle: 'Recent auto-ban events',\n eventTime: 'When',\n eventSource: 'Rule',\n eventDuration: 'Ban for',\n sources: {\n manual: 'Manual',\n 'auto-auth': 'Auto · auth',\n 'auto-rate': 'Auto · 429',\n 'auto-conn': 'Auto · concurrent',\n 'auto-velocity': 'Auto · velocity',\n 'auto-escalate': 'Auto · escalated',\n },\n },\n pm2: {\n title: 'PM2 control',\n tabRunner: 'Runner',\n tabPort: 'Port',\n tabConfig: 'Config',\n tabLogs: 'Logs',\n status: 'Process status',\n start: 'Start with PM2',\n stop: 'Stop PM2',\n restart: 'Restart',\n reload: 'Reload',\n logs: 'Logs',\n logsHint: 'Error log first',\n clearLogs: 'Clear logs',\n confirmClearLogs:\n 'Clear PM2 and ysk-omni log files? This cannot be undone (files are truncated).',\n logsCleared: 'Cleared {n} log file(s).',\n logsAutoTrim:\n 'Auto-trim over {maxMb} MB → keep last ~{keepKb} KB (on each log read).',\n refresh: 'Refresh',\n confirmStop: 'Stop the PM2 process?',\n confirmRestart: 'Restart under PM2? Port will be handed over cleanly.',\n unavailable: 'PM2 not available',\n disabled: 'PM2 admin is disabled',\n app: 'App name',\n pid: 'PID',\n uptime: 'Uptime',\n memory: 'Memory',\n cpu: 'CPU',\n restarts: 'Restarts',\n portBusy: 'Port in use',\n port: 'Port',\n portTitle: 'Listen port',\n portHint:\n 'HTTP port for the gateway Admin UI and API. Changing the port updates .env and restarts the runner so the new port takes effect.',\n fieldPort: 'Port',\n portDefaultNote: 'Default is 3850. Valid range: 1–65535.',\n savePort: 'Save port & restart',\n useDefaultPort: 'Use default (3850)',\n portInvalid: 'Enter a valid port number (1–65535).',\n confirmPortChange:\n 'Change listen port to {port} and restart the gateway? You will need to open Admin on the new port (e.g. http://localhost:{port}/admin).',\n portChangedMsg: 'Port updated: {from} → {to}.',\n portSavedNeedRestart:\n 'Port {port} saved to .env. Restart the gateway for it to take effect.',\n portAfterRestart:\n 'After restart, open Admin at http://localhost:{port}/admin',\n hint: 'Run with PM2 or detached ysk-omni. Switch anytime here or via CLI.',\n switchTitle: 'Runner',\n switchHint: 'Only one runner should bind the port.',\n currentRunner: 'Current runner',\n runnerPm2: 'PM2',\n runnerGctoac: 'ysk-omni (detached)',\n runnerNone: 'Not running',\n runnerUnknown: 'Unknown / mixed',\n switchToPm2: 'Switch to PM2',\n switchToGctoac: 'Switch to ysk-omni',\n confirmSwitchPm2: 'Switch to PM2? Gateway restarts under PM2 in a few seconds.',\n confirmSwitchGctoac: 'Switch to ysk-omni? Gateway restarts as a detached process in a few seconds.',\n switchScheduled: 'Switch scheduled. Admin will refresh automatically in about 10 seconds.',\n autoRefreshIn: 'This page will reload automatically in {n} seconds…',\n autoRefreshNow: 'Reloading…',\n omniPid: 'ysk-omni PID',\n configTitle: 'PM2 config',\n configHint: 'Saved to pm2.runtime.json and applied via ecosystem.config.cjs. Save & apply restarts PM2 if it is the active runner.',\n saveConfig: 'Save & apply',\n saveOnly: 'Save only',\n resetConfig: 'Reset defaults',\n confirmReset: 'Reset PM2 config to defaults?',\n configSaved: 'Config saved',\n fieldName: 'App name',\n fieldScript: 'Script',\n fieldCwd: 'Working directory (cwd)',\n fieldInstances: 'Instances',\n fieldExecMode: 'Exec mode',\n fieldAutorestart: 'Autorestart',\n fieldWatch: 'Watch',\n fieldMaxMem: 'Max memory restart',\n fieldMaxRestarts: 'Max restarts',\n fieldMinUptime: 'Min uptime',\n fieldRestartDelay: 'Restart delay (ms)',\n fieldBackoff: 'Exp backoff restart delay (ms)',\n fieldMergeLogs: 'Merge logs',\n fieldTime: 'Log timestamps',\n fieldErrorFile: 'Error log file',\n fieldOutFile: 'Out log file',\n fieldEnvExtra: 'Extra env (KEY=value per line)',\n fieldPreferred: 'Preferred runner',\n empty: 'App not in pm2 list',\n modeFork: 'fork',\n modeCluster: 'cluster',\n phCwd: '(package root)',\n phInstances: '1 or max',\n phEnv: 'NODE_ENV=production',\n statusOnline: 'online',\n statusErrored: 'errored',\n statusStopped: 'stopped',\n // status API message keys\n msgOk: 'OK',\n msgDisabled: 'PM2 admin is disabled (PM2_ADMIN_ENABLED=false).',\n msgBinaryMissing: 'pm2 not found on PATH. Install: npm install -g pm2',\n msgNotInList:\n 'App \"{app}\" is not in the PM2 list — use Start with PM2 or Switch to PM2.',\n msgPortGctoac:\n 'Port {port} is held by ysk-omni (pid {pid}). Use “Switch to PM2” to hand over.',\n msgPortBusy: 'Port {port} is in use (pid {pids}).',\n msgErrored:\n 'PM2 process errored — check logs / config, then Restart or fix port conflicts.',\n msgBothRunners:\n 'Both runners detected; ysk-omni pid {pid} also holds resources. Prefer one via Switch.',\n msgError: 'PM2 error: {error}',\n msgSwitchPm2:\n 'Switching to PM2… The gateway will restart under PM2 in a few seconds.',\n msgSwitchGctoac:\n 'Switching to ysk-omni… The gateway will restart as a detached process in a few seconds.',\n },\n system: {\n title: 'System',\n tabSoftware: 'Software',\n tabPackage: 'Package',\n tabEnv: 'Environment',\n envHint: 'Runtime env & version snapshot.',\n checkUpdate: 'Check for updates',\n oneClick: 'Update package & restart',\n selfUpdate: 'Package version',\n selfHint: 'Compare versions · update package restarts the gateway.',\n current: 'This install',\n npm: 'npm latest',\n github: 'GitHub latest',\n install: 'Install channel',\n confirmUpdate: 'Update the package and restart the gateway? API will be briefly unavailable.',\n scheduled: 'Update scheduled. Refresh this page in ~30s.',\n database: 'Database',\n textEngine: 'Text engine',\n concurrency: 'Concurrency',\n runtime: 'Runtime health',\n software: 'Required software',\n softwareHint: 'Required tools and installed versions.',\n softName: 'Software',\n softLevel: 'Need',\n softInstalled: 'Installed',\n softVersion: 'Version',\n softStatus: 'Status',\n softDetail: 'Note',\n levelRequired: 'Required',\n levelRecommended: 'Recommended',\n levelOptional: 'Optional',\n levelBundled: 'Bundled',\n softOk: 'OK',\n softMissing: 'Missing',\n softWarn: 'Warning',\n envTitle: 'Environment',\n up: 'Up',\n down: 'Down',\n yes: 'Yes',\n no: 'No',\n // Version badge meanings (top cards + package panel)\n badgeUpdate: 'Update available',\n badgeOk: 'Up to date',\n badgeAhead: 'Newer than npm',\n badgeUnknown: 'Unknown',\n statusHintUpdate: 'A newer published version is available. Use “Update package & restart”.',\n statusHintOk: 'This install matches the latest known release.',\n statusHintAhead:\n 'Local version is newer than npm (typical for git / dev). “Update package” still pulls latest git commits if on the git channel.',\n statusHintUnknown: 'Could not reach npm/GitHub to compare versions.',\n checkResult: 'Version check',\n channelGit: 'git (dev tree)',\n channelNpmGlobal: 'npm global',\n channelNpmLocal: 'npm local',\n channelUnknown: 'unknown',\n encryption: 'Encryption',\n ready: 'Ready',\n notReady: 'Not ready',\n allRequiredOk: 'All required software present',\n requiredMissing: 'Some required software is missing',\n },\n support: {\n title: 'Support',\n subtitle: 'Creator, sponsors, and YSK Limited — free product, real help',\n pillSupport: 'Support',\n pillSponsor: 'Sponsor · Linktree',\n pillHelp: 'Questions? email@ysk.hk',\n creatorTitle: 'Creator',\n creatorBody:\n 'This OpenAI-compatible gateway is a free open-source product for running local models as an API. The project is maintained in the open; your feedback and bug reports matter.',\n sponsorTitle: 'Support / sponsor',\n sponsorBody:\n 'If this gateway saves you time, consider sponsoring development. Every bit helps keep it free for everyone.',\n githubSponsors: 'GitHub Sponsors',\n linktree: 'Linktree',\n walletsTitle: 'Crypto / Web3 addresses',\n walletsHint: 'Send only on the matching network. Double-check the address before you transfer.',\n net: 'Network',\n addr: 'Address',\n copy: 'Copy',\n netEvm: 'EVM (ETH/BSC/AVAX)',\n netNear: 'NEAR',\n netAda: 'ADA (Cardano)',\n yskTitle: 'YSK Limited',\n yskBody: 'Need hands-on help beyond the free Admin panel? YSK Limited can provide:',\n yskLi1: 'Server install, hardening, and day-to-day ops',\n yskLi2: 'Hosting stack (web, email, DNS, databases)',\n yskLi3: 'Migration, automation, and custom integration',\n yskLi4: 'Incident response and go-live checks',\n yskPrice: 'No public price list — email us and we will scope it to your setup.',\n site: 'ysk.hk',\n helpTitle: 'Have a problem?',\n helpBody:\n 'Email with OS, install / log path, and expected vs actual result. Every message is read.',\n docs: 'Full docs are in the repo README',\n },\n common: {\n empty: 'No data',\n active: 'active',\n revoked: 'revoked',\n save: 'Save',\n cancel: 'Close',\n loading: 'Loading…',\n powered: 'Powered by',\n actions: 'Actions',\n yes: 'Yes',\n no: 'No',\n ok: 'OK',\n confirm: 'Confirm',\n notice: 'Notice',\n confirmTitle: 'Please confirm',\n dangerTitle: 'Confirm action',\n apply: 'Apply',\n reset: 'Reset',\n search: 'Search',\n prev: 'Previous',\n next: 'Next',\n perPage: 'Per page',\n pagerTotal: 'Total {n}',\n pagerPage: 'Page {n} / {total}',\n filterTitle: 'Search & filters',\n filterHint: 'Narrow results, then apply',\n sortHint: 'Click to sort (API). Default: newest first',\n all: 'All',\n requestFailed: 'Request failed',\n featureOff: 'Off',\n ms: '{n} ms',\n perMin: '{n}/min',\n minutes: '{n} min',\n mb: '{n} MB',\n percent: '{n}%',\n ipLabel: 'IP',\n uaLabel: 'UA',\n httpStatus: 'HTTP',\n },\n /** API error.code → user-facing message (Admin SPA) */\n errors: {\n unauthorized: 'Invalid or missing credentials. Please sign in again.',\n forbidden: 'You do not have permission for this action.',\n not_found: 'The requested resource was not found.',\n validation_error: 'Invalid request. Please check your input.',\n rate_limit_exceeded: 'Rate limit exceeded. Please try again later.',\n concurrency_limit_exceeded: 'Too many concurrent engine jobs. Please wait and retry.',\n internal_error: 'An internal server error occurred.',\n engine_error: 'The local engine returned an error.',\n engine_timeout: 'The local engine timed out.',\n engine_not_available: 'No local engine is available on this server.',\n document_too_large: 'The document exceeds the maximum allowed size.',\n document_type_not_allowed: 'This document type is not allowed.',\n invalid_cwd: 'The working directory is not allowed.',\n service_unavailable: 'The service is temporarily unavailable.',\n queue_full: 'The chat queue is full. Please try again later.',\n queue_draining: 'The chat queue is paused or draining.',\n queue_wait_timeout: 'Timed out while waiting in the chat queue.',\n queue_cancelled: 'The chat job was cancelled.',\n media_not_supported: 'This media feature is not available or is disabled.',\n media_provider_unavailable: 'The media provider is not available.',\n media_generation_failed: 'Media generation failed.',\n media_forbidden:\n 'Media generation is not allowed for this API key. Use an agent-mode key or an admin session.',\n feature_disabled: 'This API feature is disabled.',\n feature: {\n imagesApi:\n 'Images API is disabled. Enable it under Admin → API features → Images API.',\n videoApi:\n 'Video API is disabled. Enable it under Admin → API features → Videos API.',\n audioApi:\n 'Audio API is disabled. Enable it under Admin → API features → Audio API.',\n tools:\n 'Tools are disabled. Enable Tools under Admin → API features (required for image generation).',\n filesOpenAiAlias:\n 'OpenAI Files API alias is disabled. Enable it under Admin → API features → Files API alias.',\n },\n media: {\n agent_or_admin_required:\n 'Image generation requires an agent-mode API key or an admin session. Safe-mode keys cannot use image tools.',\n source_required:\n 'Provide an image file, a media asset, or a document as the source.',\n source_must_be_image:\n 'The selected source must be an image for edit or video generation.',\n no_image_in_sandbox:\n 'Generation finished but no image file was found. This is not an imagesApi or API-key problem.',\n no_video_in_sandbox:\n 'Generation finished but no video file was found.',\n provider_no_edit: 'The current media provider does not support image edits.',\n },\n },\n },\n 'zh-Hant': {\n brand: 'YSK Omni',\n brandSub: '管理面板',\n loginTitle: '管理員登入',\n loginLabel: 'API 金鑰',\n loginOtpLabel: '一次性登入碼',\n loginBtn: '登入',\n loginCmdHint: '請於終端機取得金鑰:',\n loginOtpHint: '每次登入請在終端機產生新碼:',\n loginOtpExpiry: '登入碼 5 分鐘內有效,且只能使用一次。',\n loginOtpFail: '登入碼無效或已過期',\n loginLostKey: '舊金鑰無法找回(系統只儲存雜湊),請建立新的管理員金鑰。',\n loginCopy: '複製',\n loginCopied: '已複製',\n needKey: '請輸入 API 金鑰',\n needOtp: '請輸入終端機產生的一次性登入碼',\n logout: '登出',\n shell: {\n menu: '開啟選單',\n closeMenu: '關閉選單',\n },\n nav: {\n dashboard: '儀表板',\n chat: '對話',\n chats: '對話記錄',\n keys: 'API 金鑰',\n documents: '文件',\n media: '媒體庫',\n catalog: '目錄',\n runtimes: '執行環境',\n audit: '審計日誌',\n settings: '安全設定',\n apiFeatures: 'API 能力',\n usage: '用量與防護',\n ddos: 'DDoS 中心',\n queue: '佇列',\n pm2: 'PM2',\n system: '系統狀態',\n support: '支援',\n },\n queue: {\n title: '對話佇列',\n subtitle: '暫停、排空、重新入隊,並調整併發。',\n paused: '已暫停',\n running: '消費中',\n drain: '排空模式',\n mode: '模式',\n modeOff: '已停用',\n depth: '佇列深度',\n queued: '排隊中',\n leased: '已認領',\n activeJobs: '執行中',\n dead: '死信',\n oldest: '最長等待',\n concurrency: '每 Key / 全域',\n worker: '進程內 worker',\n workerInstance: 'Worker 實例',\n workerInstanceHint: '本進程消費者 ID(租約持有者)。重啟後會變更。',\n kpiActiveSub: '本進程進行中 {n} 個',\n consumer: '消費者',\n admission: '接單',\n accepting: '接受新單',\n pause: '暫停消費',\n resume: '恢復消費',\n drainBtn: '排空',\n undrain: '停止排空',\n savePolicy: '儲存政策',\n refresh: '重新整理',\n jobs: '工作列表',\n tabOverview: '總覽',\n tabJobs: '工作列表',\n tabPolicy: '政策',\n jobsMeta: '共 {n} 筆',\n cancel: '取消',\n requeue: '重新入隊',\n purgeDead: '清理死信與舊工作',\n purgeTitle: '確認清理工作?',\n purgeConfirm:\n '會立即刪除全部死信(DLQ),以及完成已超過 24 小時的成功/失敗/取消工作。',\n purgeConfirmBtn: '確認刪除',\n purgeDoneTitle: '清理完成',\n purgeDoneMsg: '已刪除 {n} 筆工作。',\n cancelConfirm: '取消此工作?若正在執行,取消為協作式(cooperative)。',\n empty: '沒有符合篩選的工作',\n enabled: '啟用佇列',\n masterOn: '佇列已開',\n masterOff: '佇列已關',\n masterHint: '對話佇列總開關,即時生效。',\n disabledBanner:\n '佇列已關閉 — 新對話會跳過排隊、即時執行(仍受併發上限約束)。',\n globalConcurrency: '全域併發',\n perKeyConcurrency: '每 Key 併發',\n maxDepth: '全域佇列上限',\n maxDepthKey: '每 Key 上限',\n fairness: '公平策略',\n fifo: '全域 FIFO',\n wrr: '加權輪詢',\n playgroundPriority: 'Playground 優先級(越小越先)',\n defaultPriority: '預設優先級',\n leaseMs: '租約(ms)',\n maxWaitMs: '最長等待(ms)',\n filterTitle: '篩選工作',\n filterHint: '依狀態篩選。會自動重新整理。',\n filterStatus: '狀態',\n allStatuses: '全部狀態',\n filterDead: '死信(DLQ)',\n filterQueued: '排隊中',\n filterRunning: '執行中 / 已認領',\n filterFailed: '失敗',\n filterSucceeded: '成功',\n filterCancelled: '已取消',\n errorCol: '錯誤',\n priorityBtn: '優先級',\n priorityPh: '優先級(0–1000,越小越先)',\n dlqTitle: '死信佇列',\n dlqHint: '已用盡重試次數 — 可重新入隊或清理。',\n viewDlq: '查看死信',\n statusPanel: '運行狀態',\n statusPanelHint: '消費者、接單與 worker 實例即時狀態;每隔數秒自動重新整理。',\n policyTitle: '佇列政策',\n policyHint: '可先選方案再微調數值;儲存後生效。編輯時會暫停自動重新整理。',\n presetTitle: '政策方案',\n presetHint: '一鍵套用。Active=表單目前值 · Saved=已儲存。',\n presetRelaxed: '寬鬆',\n presetBalanced: '均衡',\n presetStrict: '嚴格',\n presetCustom: '自訂',\n presetRelaxedHint:\n '較高併發、較深佇列 — 適合多 key/Playground 與突發流量。',\n presetBalancedHint:\n '預設生產平衡:公平輪詢、中等深度、每 key 同時只跑 1 個。',\n presetStrictHint:\n '較低上限 + 全域 FIFO — 流量不可信或主機資源緊張時使用。',\n presetCustomHint: '數值不符合內建方案。可繼續微調,或於上方選取一個方案。',\n presetActiveLabel: '目前:{name}',\n presetFormLabel: '草稿:{name}',\n presetTagActive: '目前',\n presetTagDraft: '草稿',\n presetTagSaved: '已套用',\n hintGlobalConc: '全域同時執行的工作上限',\n hintPerKeyConc: '單一 API key 同時執行上限',\n hintMaxDepth: '佇列總深度滿時拒收新單',\n hintMaxDepthKey: '該 key 排隊/執行過多時拒收',\n hintFairness: 'WRR 按 key 輪流;FIFO 按全域優先級與時間',\n hintLease: 'Worker 持有工作多久未完成會被回收',\n hintMaxWait: '客戶端排隊最長等待時間',\n colJob: '工作 / 請求',\n colSource: '來源',\n colStatus: '狀態',\n colModel: '模型',\n colPri: '優先',\n colKey: 'API 金鑰',\n colTry: '嘗試',\n colTime: '入隊時間',\n stQueued: '排隊',\n stLeased: '已認領',\n stRunning: '執行中',\n stSucceeded: '成功',\n stFailed: '失敗',\n stDead: '死信',\n stCancelled: '已取消',\n srcV1: 'API',\n srcPlayground: 'Playground',\n kpiDepthSub: '{q} 排隊 · {l} 認領',\n kpiQueuedSub: '等待 worker',\n kpiDeadSub: '重試已盡',\n kpiOldestSub: '隊頭等待時間',\n wait: '等待',\n started: '開始',\n cancelReq: '已請求取消',\n },\n chat: {\n title: '對話',\n new: '新對話',\n send: '傳送',\n stop: '停止',\n stopped: '已停止',\n placeholder: '輸入訊息…(Enter 傳送,Shift+Enter 換行)',\n keyMode: 'API 金鑰',\n keySelect: 'API 金鑰',\n useSessionKey: '目前登入的 admin 金鑰',\n useCustomKey: '自訂金鑰',\n customKey: '金鑰',\n includeReasoning: '顯示思考',\n resume: '繼續 session',\n resumePh: 'Session UUID',\n resumeHint: '接續先前文字引擎 session',\n fork: 'Fork',\n memory: '記憶',\n noPlan: '關 plan',\n permission: '權限',\n effort: '推理力度',\n effortDefault: '預設',\n effort_none: '無',\n effort_minimal: '最低',\n effort_low: '低',\n effort_medium: '中',\n effort_high: '高',\n effort_xhigh: '極高',\n effort_max: '最大',\n tokens: 'Tokens',\n cacheTokens: '快取',\n cost: '費用',\n reasoning: '思考過程',\n needKey: '請輸入或選擇 API 金鑰',\n attach: '上傳',\n attachLibrary: '從已上傳選擇',\n attachHint: '可於本頁任意位置拖放檔案、上傳,或從已上傳庫挑選',\n dropTitle: '放開以附加檔案',\n dropHint: '放開即上傳 — 格式與「上傳」按鈕相同',\n formatsLabel: '格式',\n formatsHint:\n 'txt、md、csv、json、xml、html、pdf、圖片(png/jpg/webp/gif)、程式碼(js/ts/py/go/rs/java/c/cpp/css/yml/sql/sh…)',\n formatsReject: '不支援的格式:{name}。允許:{formats}',\n libraryTitle: '已上傳的檔案',\n librarySubtitle: '選擇目前 API 金鑰名下的檔案(格式與上傳相同)。',\n librarySearch: '依檔名搜尋…',\n libraryEmpty: '此金鑰沒有符合的檔案',\n libraryAdd: '加入所選',\n librarySelected: '已選 {n} 個',\n libraryAlready: '已附加',\n libraryLoadFail: '無法載入檔案列表',\n uploading: '上傳中…',\n uploadFail: '上傳失敗',\n uploadProgress: '正在上傳 {name}',\n uploadProgressMulti: '正在上傳 {name}({i}/{n})',\n emptyTitle: '開始對話',\n emptyHint:\n '輸入訊息或附加檔案。選擇圖像、影片或語音模型即可在對話中生成媒體。',\n needContent: '請輸入訊息或至少附加一個檔案',\n needAudioAttach: '請附加音訊檔以進行轉錄',\n mediaBusy_image: '正在生成圖像…',\n mediaBusy_video: '正在生成影片…',\n mediaBusy_tts: '正在合成語音…',\n mediaBusy_stt: '正在轉錄…',\n mediaDone_image: '圖像已儲存至媒體庫。',\n mediaDone_video: '影片已儲存至媒體庫。',\n mediaDone_tts: '語音已儲存至媒體庫。',\n mediaDone_stt: '轉錄已儲存。',\n openInLibrary: '在媒體庫開啟',\n modelKind_text: '文字',\n modelKind_image: '圖像',\n modelKind_video: '影片',\n modelKind_tts: '語音',\n modelKind_stt: '轉錄',\n tooManyFiles: '檔案太多(每則訊息最多 10 個)',\n fileOnlyPrompt: '請查看附加的檔案。',\n removeFile: '移除',\n docs: '附件',\n you: '你',\n assistant: '助理',\n streaming: '串流中…',\n emptyReply: '(無回覆內容)',\n systemPrompt: '系統提示',\n systemPlaceholder: '可選:模型系統指示(system 訊息)…',\n systemHint: '每次傳送會以 system 角色附帶,不會顯示於對話氣泡。',\n history: '歷史對話',\n historyEmpty: '尚未有已儲存的對話',\n historySearch: '搜尋主題…',\n historyOpen: '顯示歷史',\n historyClose: '關閉歷史',\n rename: '重新命名',\n renamePh: '對話主題',\n untitled: '未命名對話',\n deleteConversation: '刪除',\n deleteConfirm: '確定刪除此對話?此操作無法還原。',\n saveFail: '無法儲存對話',\n loadFail: '無法載入對話',\n historyPrev: '上一頁',\n historyNext: '下一頁',\n historyPage: '第 {n} / {total} 頁',\n msgs: '{n} 則訊息',\n settings: '設定',\n settingsHide: '收起設定',\n compress: '產生語境摘要',\n compressConfirm:\n '為之後回合產生對話摘要以節省 token?畫面上的完整對話記錄不會被刪除或改寫,只影響傳送給模型的內容。此操作會呼叫模型一次。',\n compressing: '正在產生摘要…',\n compressNeedMore:\n '至少需要 3 則訊息(或 2 則較長內容)才可產生摘要。請先繼續對話再試。',\n compressFail: '無法產生摘要',\n compressNeedSummary: '請先按「產生語境摘要」建立摘要。',\n compressedBadge: '摘要',\n compressOk: '摘要已就緒(完整記錄仍保留)。已切換為「摘要 + 最近訊息」模式。',\n compressBusy: '請等待目前回覆完成',\n compressResultTitle: '對話摘要',\n compressView: '查看摘要',\n summaryMeta: '產生時間:{when} · 依據 {n} 則訊息',\n ctxPolicyTitle: '模型上下文',\n ctxRemark:\n '完整訊息仍顯示於對話區。此設定只控制下一次傳送給模型的內容。',\n ctxMode: '上下文',\n ctxModeFull: '完整記錄',\n ctxModeSummary: '摘要 + 最近',\n ctxModeRecent: '僅最近',\n ctxModeFullLabel: '目前送出完整對話記錄',\n ctxModeSummaryLabel: '目前送出摘要 + 最近 {n} 則',\n ctxModeRecentLabel: '目前只送出最近 {n} 則',\n ctxRecentN: '最近則數',\n ctxLongHint:\n '對話較長 — 建議改用「摘要 + 最近」或「僅最近」,以減少 token 並避免介面卡頓。',\n loadOlder: '載入較早的 {n} 則訊息',\n showMore: '顯示更多',\n showLess: '收合',\n copy: '複製',\n copied: '已複製',\n copyFail: '複製失敗',\n },\n status: {\n success: '成功',\n error: '錯誤',\n timeout: '逾時',\n pending: '處理中',\n active: '進行中',\n finished: '已完成',\n online: '運行中',\n stopped: '已停止',\n },\n dash: {\n title: '儀表板',\n subtitle: '流量、佇列、安全與防護一覽。',\n last24: '最近 24h 請求',\n totalChat: '總對話',\n success: '成功',\n errors: '錯誤/逾時',\n docs: '文件',\n keys: '活躍金鑰',\n concurrent: '引擎併發',\n recent: '最近 API 請求',\n empty: '暫無資料',\n emptyModels: '最近 24h 尚無模型用量',\n updated: '更新於',\n refresh: '重新整理',\n viewAll: '查看全部',\n openDdos: 'DDoS 中心',\n openSettings: '安全設定',\n openQueue: '開啟佇列',\n kpi24h: '請求(24h)',\n kpi24hSub: '{ok} 成功 · {err} 錯誤',\n kpiSuccessRate: '成功率(24h)',\n kpiSuccessRateSub: '全部時間 {all}%',\n kpiErrors: '錯誤(24h)',\n kpiErrorsSub: '全部時間 {all}',\n kpiKeys: 'API 金鑰',\n kpiKeysSub: '活躍 / 總數',\n kpiDocs: '文件',\n kpiMedia: '媒體資產',\n kpiMediaSub: '24 小時 {n} 個',\n kpiDocsSub: '已儲存檔案',\n kpiConv: 'Playground 對話',\n kpiConvSub: '24h 內更新 {n} 則',\n kpiSessions: 'OTP 工作階段',\n kpiSessionsSub: '目前有效的管理員登入',\n kpiConcurrent: '引擎併發',\n kpiConcurrentSub: '進行中 / 上限',\n kpiQueue: '對話佇列',\n kpiQueueSub: '深度 · 執行 / 上限 · 死信',\n kpiQueueSubLive: '{run}/{max} 執行 · {dead} 死信{wait}',\n kpiQueuePaused: '已暫停',\n kpiQueueDrain: '排空',\n kpiQueueOff: '已停用',\n kpiSafe: '全域安全',\n kpiSafeOn: '開',\n kpiSafeOff: '關',\n kpiSafeSub: '{tools} · turns {turns} · {model}',\n kpiSafeSubEmpty: '無法讀取設定',\n queuePanel: '對話佇列',\n queueState: '狀態',\n queueLive: '運作中',\n qQueued: '排隊中',\n qRunning: '執行中',\n qDead: '死信',\n qSucceeded: '已成功',\n qWorker: 'Worker',\n qWorkerActive: '活躍槽',\n qOldest: '最舊等待',\n qUnavailable: '無法取得佇列統計',\n safety: '安全設定',\n globalSafe: '全域安全模式',\n safeTools: '工具',\n safeTurns: '最大 turns',\n safeTimeout: '逾時',\n defaultModel: '預設模型',\n safetyHint:\n '影響 safe 模式金鑰與強制 safe 的流量。Playground OTP 預設 agent;開啟全域安全後會套用 safe 限制。',\n protection: '防護狀態',\n autoBan: '自動封鎖',\n on: '開',\n off: '關',\n ruleAuth: '認證',\n ruleRate: '429',\n ruleConn: '並發',\n ruleVelocity: '速率',\n bans: '黑名單',\n blocked: '已攔截',\n rateHits: '限流次數',\n liveConn: '即時連線',\n proxy: '代理 IP',\n hops: '層數',\n limits: '金鑰/IP 上限',\n models24h: '模型用量(24h)',\n runtime: '運行環境',\n port: '監聽連接埠',\n defaultPort: '預設',\n env: '環境',\n authMode: '管理登入',\n authOtp: 'OTP 工作階段',\n encryption: '加密',\n ready: '就緒',\n notReady: '未就緒',\n },\n chats: {\n title: '對話記錄',\n total: '共',\n decrypt: '點選列項可查看解密後內容。',\n search: '搜尋',\n searchPh: '請求 ID、金鑰名稱、模型…',\n filterTitle: '搜尋與篩選',\n filterHint: '篩選後點列項查看詳情。',\n status: '狀態',\n allStatus: '全部狀態',\n model: '模型',\n allModels: '全部模型',\n apiKey: 'API 金鑰',\n allKeys: '全部金鑰',\n from: '由',\n to: '至',\n mode: '模式',\n allModes: '全部模式',\n hasDocs: '有附件',\n filter: '套用篩選',\n reset: '重設',\n request: '請求',\n prompt: '提示',\n response: '回覆',\n time: '時間',\n attachments: '附件',\n page: '頁',\n prev: '上一頁',\n next: '下一頁',\n perPage: '每頁',\n detail: '對話詳情',\n noAttach: '無附件',\n openFile: '開啟 / 預覽',\n close: '關閉',\n copyPrompt: '複製提示',\n copyContent: '複製內容',\n copySystem: '複製 system prompt',\n copyRawPrompt: '複製原始 prompt',\n duration: '耗時',\n stream: '串流',\n reasoning: '思考過程',\n content: '輸出內容',\n raw: '原始儲存回覆',\n rawPrompt: '原始儲存 prompt',\n userPrompt: '用戶/對話 prompt',\n systemPrompt: 'System prompt',\n systemHint: '從已儲存 prompt 中抽出 system 角色內容。',\n noSystem: '此請求沒有 system prompt。',\n hasSystem: '有 system',\n none: '(無)',\n file: '檔案',\n img: '圖片',\n previewFailed: '預覽失敗',\n },\n keys: {\n title: 'API 金鑰',\n new: '新增金鑰',\n searchPh: '名稱或 key 前綴…',\n name: '名稱',\n role: '角色',\n mode: '模式',\n rate: '速率 / 分',\n status: '狀態',\n created: '建立',\n edit: '編輯',\n revoke: '撤銷',\n confirmRevoke: '確定撤銷此金鑰?',\n empty: '暫無',\n usage24: '24h 用量',\n maxTurns: '最大 turns',\n timeoutMs: '逾時 (ms)',\n ipWhitelist: 'IP 白名單',\n ipWhitelistHint: '每行一個 IP 或 CIDR。留空 = 不限制 IP。',\n ipWhitelistCol: 'IP 允許',\n ipAll: '全部 IP',\n keyOnce: '請妥善保存(明文只顯示一次):',\n roleClient: '用戶 (client)',\n roleAdmin: '管理員 (admin)',\n roleClientBadge: '用戶',\n roleAdminBadge: '管理員',\n modeSafe: 'safe(對外)',\n modeAgent: 'agent(全能力)',\n modeSafeBadge: '安全',\n modeAgentBadge: '代理',\n ipCount: '{n} 個 IP',\n ipPlaceholder: '127.0.0.1\\n203.0.113.0/24',\n allowedModels: '可用模型',\n allowedModelsHint: '勾選此金鑰可使用的模型。留空 = 不限制。用戶可透過 GET /v1/models 查詢可用模型清單。',\n allowedModelsCol: '模型',\n modelsAll: '全部模型',\n modelsCount: '{n} 個模型',\n modelsExtra: '其他模型 id',\n modelsExtraHint: '每行一個模型 id,用於上方未列出的識別名稱。',\n modelsPlaceholder: 'org/repo:Q4_K_M',\n },\n docs: {\n title: '文件',\n total: '共',\n file: '檔名',\n mime: '類型',\n size: '大小',\n time: '時間',\n storage: '儲存位置',\n storageDb: '資料庫(加密)',\n storageFs: '檔案系統(加密)',\n storageHint: '加密儲存 · 小於 {dbMax} 入 DB,其餘於 {dir} · 上限 {upMax}。',\n download: '下載',\n downloadFail: '下載失敗',\n binaryPreview: '此為二進位檔(例如 PDF),無法在此預覽,請使用「下載」。',\n delete: '刪除',\n confirmDel: '確定刪除此文件?',\n detail: '文件詳情',\n preview: '預覽',\n copy: '複製內容',\n empty: '暫無',\n searchPh: '檔名或 MIME…',\n page: '頁',\n prev: '上一頁',\n next: '下一頁',\n },\n audit: {\n title: '審計日誌',\n searchPh: '動作、資源、IP、金鑰…',\n time: '時間',\n action: '動作',\n resource: '資源',\n key: '金鑰',\n meta: '詳情',\n empty: '暫無日誌',\n id: '識別碼',\n actions: {\n chat_create: '建立對話',\n document_upload: '上傳文件',\n document_delete: '刪除文件',\n document_list: '列出文件',\n document_read: '讀取文件',\n document_download: '下載文件',\n api_key_create: '建立金鑰',\n api_key_update: '更新金鑰',\n api_key_delete: '撤銷金鑰',\n api_key_list: '列出金鑰',\n settings_update: '更新設定',\n chat_admin_view: '管理員查看對話',\n system_update: '系統更新',\n system_update_check: '檢查更新',\n ip_ban: '封鎖 IP',\n ip_unban: '解除 IP 封鎖',\n ddos_policy_update: 'DDoS 策略更新',\n pm2_start: 'PM2 啟動',\n pm2_stop: 'PM2 停止',\n pm2_restart: 'PM2 重啟',\n pm2_reload: 'PM2 重載',\n pm2_config: 'PM2 設定',\n pm2_switch: 'PM2 切換 runner',\n playground_chat: '對話試玩',\n playground_upload: '試玩上傳',\n },\n resources: {\n document: '文件',\n chat: '對話',\n api_key: 'API 金鑰',\n settings: '設定',\n system: '系統',\n pm2: 'PM2',\n playground: '試玩',\n ip: 'IP',\n },\n metaStorage: '儲存方式',\n metaAsKey: '代行金鑰 ID',\n metaAsKeyName: '代行金鑰名稱',\n },\n settings: {\n title: '安全設定',\n hint: '全域安全模式,套用至所有金鑰。',\n globalSafe: '全域安全模式',\n globalSafeHint: '開=全部 safe。關=跟各金鑰自身模式。',\n masterOn: '安全模式:開',\n masterOff: '安全模式:關',\n disabledBanner: '全域安全已關 — 各金鑰用自身 safe/agent 設定。',\n tools: '工具模式',\n toolsHint: 'none:禁 shell/上網/寫入。readonly:只讀搜尋。',\n toolsNone: 'none',\n toolsReadonly: 'readonly',\n maxTurns: '最大 turns',\n maxTurnsHint: 'safe 步數。問答 3–6 · API 8–12 · 多步驟 15–40。',\n timeout: '逾時(ms)',\n timeoutHint: 'safe 時限。一般 60–120s · 長任務 300–600s。',\n defaultModel: '預設模型',\n defaultModelHint: '客戶端未指定 model 時使用。',\n modelSource: '本機引擎',\n refreshModels: '重新整理模型',\n panel: '管理面板',\n save: '儲存',\n saved: '已儲存',\n guideTitle: '建議預設',\n guideIntro: '套用後可再微調。',\n guideApply: '套用',\n guideActive: '已應用',\n guideApplyConfirm: '套用「{name}」並儲存?會覆寫目前數值。',\n guideApplied: '已套用',\n chipGlobalOn: '安全:開',\n chipGlobalOff: '安全:關',\n scLocalTitle: '本機試用',\n scLocalDesc: '本機完整能力。',\n scLocalDetail: '安全關 · agent 金鑰。',\n scProdTitle: '對外 API',\n scProdDesc: '產品端點,最小權限。',\n scProdDetail: '安全開 · none · turns 8–12 · 60–120s。',\n scCodeTitle: '程式代理',\n scCodeDesc: '可信主機改檔/跑指令。',\n scCodeDetail: '安全關 · agent 金鑰。',\n scReadTitle: '只讀分析',\n scReadDesc: '解碼/搜尋,不寫入。',\n scReadDetail: '安全開 · readonly · turns 8–15 · 120–180s。',\n scChatTitle: '純問答',\n scChatDesc: '只回覆文字,不需使用工具。',\n scChatDetail: '安全開 · none · turns 3–6 · 60s。',\n scLongTitle: '長任務(safe)',\n scLongDesc: '多步驟,減少 max turns 失敗。',\n scLongDetail: '安全開 · none/readonly · turns 20–40 · 300–600s。',\n dangerTitle: '危險操作',\n disablePanel: '關閉管理面板',\n disablePanelConfirm: '關閉面板並登出?重開:ysk-omni admin on',\n disablePanelDone: '面板已關。重開:ysk-omni admin on',\n panelOffHint: '此處可關閉。重開請在伺服器執行 ysk-omni admin on。',\n panelStatus: '狀態',\n panelOn: '開',\n panelOff: '關',\n },\n apiFeatures: {\n title: 'API 能力',\n intro: '開關協議與能力 · 約 2 秒生效 · 無需重啟。',\n tabProtocols: '協議',\n tabMedia: '媒體',\n tabCaps: '能力',\n tabEmu: '模擬',\n kpiEnabled: '已啟用',\n kpiEnabledSub: '目前開啟的開關',\n groupMeta: '已開 {on} / {n}',\n groupProtocols: '協議表面',\n groupMedia: '媒體 API(OpenAI 兼容)',\n groupCaps: '引擎能力',\n groupEmu: '模擬與安全',\n presetOpen: '預設:開放',\n presetLocked: '預設:鎖定',\n presetDev: '預設:開發',\n presetConfirm: '套用能力預設「{name}」?會覆寫全部 API 開關。',\n flag: {\n openaiChat: 'OpenAI Chat Completions',\n openaiResponses: 'OpenAI Responses',\n anthropicMessages: 'Anthropic Messages',\n imagesApi: 'Images API',\n filesOpenAiAlias: 'Files API 別名',\n videoApi: 'Videos API(異步 job)',\n audioApi: 'Audio API(語音 / STT)',\n tools: 'Tools / function calling',\n structuredOutput: '結構化輸出 (--json-schema)',\n vision: '視覺 / 圖片 (--prompt-json)',\n reasoningEffort: '推理力度',\n webSearch: '網絡搜尋工具',\n subagents: '子代理',\n planMode: 'Plan 模式',\n memory: '跨 session 記憶',\n sessionResume: '恢復 session',\n bestOfN: 'best-of-n(已移除)',\n checkLoop: '自我檢查迴圈(已移除)',\n systemOverride: 'System prompt 覆寫',\n rules: '額外 rules',\n permissionMode: '權限模式',\n sandbox: 'Sandbox profile',\n usageEstimate: '估算 token usage',\n assistantsEmulation: 'Assistants-lite(本機)',\n strictSampling: '嚴格採樣(拒絕 temperature…)',\n forceDisableToolsInSafe: 'Safe 模式強制工具限制',\n },\n hint: {\n openaiChat: 'POST /v1/chat/completions',\n openaiResponses: 'POST /v1/responses',\n anthropicMessages: 'POST /v1/messages',\n imagesApi: 'POST /v1/images/generations + /edits(要 agent key)',\n filesOpenAiAlias: 'POST/GET /v1/files → documents + media',\n videoApi: 'POST /v1/videos + poll GET /v1/videos/:id',\n audioApi: 'POST /v1/audio/speech + /transcriptions(要 provider)',\n tools: '映射 tools 至本機引擎工具清單',\n structuredOutput: 'response_format / json_schema',\n vision: 'image_url content parts',\n reasoningEffort: '--reasoning-effort',\n webSearch: '關閉時加 --disable-web-search',\n subagents: '關閉時 --no-subagents',\n planMode: '關閉時 --no-plan',\n memory: '--experimental-memory',\n sessionResume: '--resume / --continue',\n bestOfN: '已棄用 — 閘道會拒絕此 flag',\n checkLoop: '已棄用 — 閘道會拒絕此 flag',\n systemOverride: '--system-prompt-override',\n rules: '--rules',\n permissionMode: '--permission-mode',\n sandbox: '--sandbox',\n usageEstimate: 'usage 用字元/4 估算',\n assistantsEmulation: '本機 /v1/assistants + /v1/threads',\n strictSampling: '帶 temperature 等則 400',\n forceDisableToolsInSafe: '維持 safe 工具政策',\n },\n },\n catalog: {\n title: '目錄',\n intro: '從 Hugging Face 搜尋並拉取模型,再以 llama-server 載入本機 GGUF。',\n tabPacks: '精選包',\n tabLocal: '本機模型',\n tabHub: 'Hugging Face',\n kpiLoaded: '已載入',\n kpiLoadedSub: '佔用 VRAM 的引擎',\n kpiLoadedNone: '尚未載入',\n kpiVram: 'VRAM',\n kpiVramSub: '估計 {used} / {budget} MB',\n kpiLocal: '磁碟',\n kpiLocalSub: '本機登錄',\n kpiPacks: '精選',\n kpiPacksSub: '策展目錄',\n filterModality: '模態',\n filterAll: '全部',\n colName: '模型',\n colModality: '模態',\n colRuntime: '執行環境',\n colQuant: '量化',\n colVram: 'VRAM',\n colSize: '大小',\n sizeEst: '估計',\n colStatus: '狀態',\n colPath: '路徑',\n pull: 'Pull',\n pulling: '拉取中…',\n pullingBanner: '正在下載 {id}',\n dlQueue: '下載佇列',\n dlQueued: '排隊中',\n dlActive: '下載中',\n dlDone: '已完成',\n dlError: '失敗',\n dlEta: '預計尚餘 {time}',\n dlEtaCalc: '正在計算剩餘時間',\n dlSpeed: '{speed}/秒',\n dlWaiting: '等候目前下載完成',\n pullAgain: '再拉一次',\n onDisk: '已下載',\n load: 'Load',\n unload: 'Unload',\n delete: '刪除',\n deleteConfirm: '確定從磁碟及本機登錄刪除 {id}?',\n pullSpec: '指定模型下載',\n pullSpecPh: 'org/repo 或 org/repo:Q4_K_M',\n pullSpecBtn: 'Pull',\n pullSpecHint: '貼上 Hub 識別碼。此操作會將權重下載至本機登錄。',\n hubBrowse: '瀏覽 Hub',\n hubBrowseHint:\n '搜尋本閘道可執行的模型(llama.cpp、vLLM、diffusion、whisper)。',\n hubSearchBtn: '搜尋',\n loaded: '已載入',\n idle: '待命',\n emptyPacks: '此篩選沒有精選包',\n emptyLocal: '本機登錄為空,請從 Hugging Face 拉取模型',\n emptyLocalHint: '開啟 Hugging Face,搜尋或貼上 org/repo,然後按 Pull。',\n hubHint:\n '即時查官方 Hub REST(/api/models),用 Link cursor 翻頁。模型索引沒有 RSS/Atom。',\n hubSearch: '搜尋 Hub',\n hubSearchPh: 'Qwen、llama、flux、whisper…',\n hubEmpty: '沒有 Hub 結果',\n hubMore: '載入更多',\n hubLoading: '載入中…',\n downloads: '下載數',\n unsupported: '無本機 runtime',\n hubFail: 'Hub 搜尋失敗',\n sync: '同步熱門',\n syncing: '同步中…',\n syncOk: '已同步 {n} 個熱門 GGUF',\n syncAt: '上次同步 {when}',\n syncHint:\n '將下載次數最高的 50 個 GGUF 識別碼加入清單。此步驟不會下載檔案,請自行按 Pull 取得權重。',\n noQuant: '—',\n pullFail: '拉取失敗',\n pullNoGguf: '此儲存庫沒有 GGUF 檔,因此未加入本機模型。',\n loadFail: '載入失敗',\n unloadFail: '卸載失敗',\n mod: {\n text: '文字',\n image: '圖像',\n video: '影片',\n tts: '語音',\n stt: '轉錄',\n },\n },\n runtimes: {\n title: '執行環境',\n intro:\n '在此主機安裝或解除安裝推論引擎。可一鍵執行本作業系統的套件管理員(Homebrew、pip、winget 或 Docker)。閘道不會使用 sudo。',\n kpiInstalled: '已就緒',\n kpiMissing: '未安裝',\n kpiHost: '本機',\n kpiArch: '架構',\n filterOs: '作業系統',\n filterHost: '本機',\n filterAll: '全部系統',\n osMac: 'macOS',\n osLinux: 'Linux',\n osWin: 'Windows',\n filterMod: '模態',\n statusInstalled: '已安裝',\n statusConfigured: '已設定 URL',\n statusMissing: '未安裝',\n statusUnsupported: '此作業系統不適用',\n supportFull: '支援',\n supportPartial: '部分支援',\n supportNone: '不支援',\n copyCmd: '複製安裝指令',\n install: '安裝',\n reinstall: '重新安裝',\n installing: '安裝中…',\n installDone: '安裝完成',\n installFail: '安裝失敗',\n installLog: '安裝紀錄',\n uninstall: '解除安裝',\n uninstalling: '解除安裝中…',\n uninstallDone: '已解除安裝',\n uninstallFail: '解除安裝失敗',\n uninstallConfirm:\n '將以套件管理員移除「{name}」。閘道不會使用 sudo。',\n docs: '文件',\n refresh: '重新偵測 PATH',\n path: '偵測結果',\n cmdFor: '於 {os} 安裝',\n empty: '沒有符合篩選的執行環境',\n llamacpp: '以 llama-server 提供本機 GGUF 文字推論',\n vllm: '以 GPU 高吞吐服務 Hugging Face safetensors',\n mlx: 'Apple Silicon 原生文字(mlx_lm.server)',\n ollama: '便利的 GGUF 執行器,提供 OpenAI /v1',\n ffmpeg: '媒體轉碼與可播放影片樣本',\n whisper: '語音轉文字 worker(OpenAI transcriptions)',\n kokoro: '文字轉語音 worker(OpenAI speech)',\n comfy: '圖像/影片 worker,需 OpenAI 相容轉接層',\n },\n media: {\n title: '媒體庫',\n intro: '工作室、資產與影片工作。需 imagesApi/tools(影片另需 videoApi)。',\n tabStudio: '工作室',\n tabAssets: '資產',\n tabJobs: '工作',\n kpiAssetsSub: '已儲存的媒體檔案',\n kpiJobsSub: '影片生成工作',\n kpiStudioSub: '生成、編輯或圖生影片',\n assets: '資產',\n jobs: '影片工作',\n empty: '尚無媒體資產',\n jobsEmpty: '尚無影片工作',\n kind: '類型',\n bytes: '大小',\n provider: '提供者',\n providerPh: '提供者名稱…',\n prompt: '提示詞',\n created: '建立時間',\n status: '狀態',\n preview: '預覽',\n previewUnsupported: '瀏覽器無法預覽此格式,請下載檔案後開啟。',\n previewFail: '無法載入預覽',\n previewTruncated: '預覽已截斷',\n download: '下載',\n delete: '刪除',\n deleteConfirm: '確定要軟刪除此媒體資產?',\n allKinds: '全部類型',\n searchPh: '提示詞、檔名、MIME、提供者或 ID…',\n from: '開始日期',\n to: '結束日期',\n generate: '生成圖片',\n generateTitle: '生成圖片',\n studioTitle: '媒體工作室',\n studioHint:\n '可生成圖片、語音、轉錄、編輯圖像,或建立影片工作。執行限制依循安全設定。需啟用 imagesApi 與 tools(語音/轉錄另需 audioApi,影片另需 videoApi)。',\n generateHint: '透過本機媒體 worker(圖像、語音、轉錄、影片)。',\n generatePrompt: '提示詞',\n generatePromptPh: '描述你想生成的圖像…',\n generateSize: '尺寸',\n aspectRatio: '長寬比',\n aspectHint: '採用 aspect_ratio(非 OpenAI 像素尺寸)',\n generateN: '數量',\n outputFormat: '檔案格式',\n outputFormatHint: '生成後閘道會自動轉檔',\n nHint: '閘道會依序執行 1–4 次生成',\n generateKey: 'API 金鑰',\n generateKeySession: '目前登入的管理員工作階段',\n generateSubmit: '生成',\n generateBusy: '正在生成,可能需要一分鐘…',\n generateOk: '已生成圖像,請見下方資產列表。',\n generateFail: '圖像生成失敗',\n generateNeedPrompt: '請輸入提示詞',\n modeGenerate: '生成',\n modeEdit: '編輯',\n modeVideo: '影片',\n modeSpeech: '語音',\n modeTranscribe: '轉錄',\n speechSubmit: '產生語音',\n speechBusy: '正在合成語音…',\n speechOk: '語音已儲存,請見資產列表。',\n speechPromptPh: '輸入要朗讀的文字…',\n transcribeSubmit: '轉錄',\n transcribeBusy: '正在轉錄…',\n transcribeOk: '轉錄已儲存,請見資產列表。',\n transcribeNeedAudio: '請選擇或拖放音訊檔後再轉錄',\n dropTitleAudio: '將音訊檔拖放至此',\n dropHintAudio: 'WAV、MP3、M4A、OGG 或 FLAC',\n sourceNeedAudio: '請提供音訊檔',\n libraryFormatsAudio: '僅音訊(WAV、MP3、M4A、OGG、FLAC 等)',\n modelDefault: '系統預設',\n modelEmpty: '本機未回報模型',\n modelHint: '列出本機目錄全部模型,並預選系統預設',\n editSubmit: '編輯圖像',\n editBusy: '正在編輯…',\n editOk: '已編輯圖像,請見下方資產列表。',\n editNeedImage: '請選擇或拖放來源圖像後再編輯',\n editImage: '來源圖像',\n editImageHint: 'image_edit 必須提供來源圖像',\n editPromptPh: '描述要套用的變更…',\n videoSubmit: '建立影片工作',\n videoBusy: '正在將影片工作加入佇列…',\n videoOk: '影片工作已加入佇列,請見「影片工作」分頁。',\n videoVoice: '聲線',\n videoVoiceNone: '不加入對白',\n videoVoiceHint: '可選 preset voice — 會用 reference_to_video',\n videoDuration: '時長',\n videoDurationHint: '影片時長:1–15 秒',\n videoSource: '來源幀(選填)',\n videoSourceHint: '選填。若未提供,會先依提示詞生成畫面,再進行動畫。',\n videoNoSource: '自動依提示詞生成畫面',\n videoPromptPh: '描述鏡頭運動與畫面內容…',\n sourceTitle: '來源圖像',\n sourceHint: '可拖放圖像、選擇本機檔案,或從文件庫/媒體資產中挑選任一圖像。',\n dropzoneAria: '來源圖像拖放區',\n dropTitle: '將圖像拖放至此',\n dropHint: '亦可選擇本機檔案,或從系統庫挑選',\n dropTitleVideo: '拖放來源幀(選填)',\n dropHintVideo: '影片可選填來源。未指定時,會先依提示詞生成畫面。',\n pickFile: '選擇檔案',\n pickLibrary: '系統庫',\n clearSource: '清除',\n sourceNeedImage: '請提供圖像檔(PNG、JPEG、WebP、GIF 等)',\n sourceKindUpload: '上傳',\n sourceKindAsset: '媒體資產',\n sourceKindDocument: '文件',\n libraryTitle: '選擇來源檔案',\n librarySubtitle: '可選取本閘道「文件」或「媒體資產」中的任一圖像。',\n libraryTabDocs: '文件',\n libraryTabAssets: '媒體資產',\n librarySearch: '依名稱、MIME 或 ID 搜尋…',\n libraryFormats: '僅圖像(PNG、JPEG、WebP、GIF 等)',\n libraryEmpty: '沒有符合的檔案',\n librarySelect: '使用所選',\n libraryLoadFail: '無法載入檔案庫',\n },\n usage: {\n title: '用量與防濫用',\n window: '統計區間',\n requests: '請求數',\n success: '成功',\n errors: '錯誤',\n errorRate: '錯誤率',\n byModel: '按模型',\n byKey: '按 API 金鑰',\n rateLimit: '上限 / 分',\n util: '估計使用率',\n lastUsed: '最近使用',\n limits: 'Gateway 限流設定',\n global: '全域上限 / 視窗',\n ipMax: '未認證 IP 上限',\n burst: '對話短窗 burst(10s)',\n block: '認證失敗封鎖門檻',\n concurrent: '引擎最大併發',\n refresh: '重新整理',\n },\n ddos: {\n title: 'DDoS 控制中心',\n tabPolicy: '政策',\n tabLive: '流量',\n tabBlacklist: '黑名單',\n tabEvents: '事件',\n live: '即時連線',\n recent: '最近請求',\n blacklist: 'IP 黑名單',\n stats: '濫用統計',\n refresh: '重新整理',\n pause: '暫停自動刷新',\n resume: '恢復自動刷新',\n ban: '封鎖 IP',\n unban: '解除封鎖',\n banConfirm: '確定封鎖此 IP?',\n banWhitelistWarn: '此 IP 在自動封鎖白名單內。仍要手動封鎖?',\n unbanConfirm: '確定從黑名單移除此 IP?',\n ip: 'IP',\n method: '方法',\n path: '路徑',\n key: 'API 金鑰',\n duration: '耗時',\n state: '狀態',\n ua: '瀏覽器識別 (UA)',\n reason: '原因',\n source: '來源',\n expires: '到期',\n permanent: '永久',\n addBan: '新增封鎖',\n ttl: '有效期',\n ttlPerm: '永久',\n ttl1h: '1 小時',\n ttl24h: '24 小時',\n ttl7d: '7 日',\n activeConn: '進行中',\n rateHits: '限流次數',\n blockedHits: '已封鎖攔截',\n autoBans: '自動封鎖',\n topIps: '熱門 IP(最近)',\n emptyLive: '目前無進行中連線',\n emptyBan: '黑名單為空',\n emptyEvents: '尚無自動封鎖事件',\n reasonPh: '可選原因',\n banReasonDefault: '管理員手動封鎖',\n ipPlaceholder: '1.2.3.4',\n policyTitle: '防護策略',\n policyHint: '所有門檻即時生效,無需重啟。環境變數僅作為初始預設值。',\n autoOn: '自動判斷:開',\n autoOff: '自動判斷:關',\n autoBanMaster: '啟用自動封鎖 IP',\n autoBanMasterHint: '關閉後仍會限流,但不會自動加入黑名單。',\n masterOn: '自動封鎖:開',\n masterOff: '自動封鎖:關',\n disabledBanner:\n '自動封鎖已關閉 — 仍會限流,但 IP 不會被自動加入黑名單。',\n presetTitle: '防護方案',\n presetHint: '點選預設方案,或自行改數值;系統會自動判斷是否為自訂。',\n presetRelaxed: '寬鬆',\n presetBalanced: '均衡',\n presetStrict: '嚴格',\n presetCustom: '自訂',\n presetActiveLabel: '目前:{name}',\n presetFormLabel: '表單:{name}(未儲存)',\n presetTagActive: '使用中',\n presetTagDraft: '草稿',\n presetTagSaved: '已儲存',\n presetActiveHint: '目前方案:{name}。若改動其他欄位請按「儲存策略」。',\n presetCustomHint: '目前數值不屬於寬鬆/均衡/嚴格,已判定為「自訂」。',\n presetUnsavedHint:\n '表單顯示「{form}」,伺服器仍為「{saved}」。請按「儲存策略」先套用。',\n savePolicy: '儲存策略',\n resetPolicy: '重設為環境預設',\n policySaved: '防護策略已儲存,限流器已重新載入。',\n policyReset: '已重設為環境變數預設值。',\n confirmReset: '確定將所有 DDoS 策略欄位重設為 .env 預設?',\n sectionProxy: '反向代理 / CDN',\n proxyHint:\n '流量經 nginx 或 Cloudflare 時,請設定信任層數,令封鎖、限流、審計日誌使用真實用戶 IP,而非代理伺服器 IP。',\n proxyTrustHops: '信任代理層數',\n proxyTrustHopsHint:\n '0 = 直連(忽略 header)。1 = nginx 或 Cloudflare→應用。2 = Cloudflare→nginx→應用。',\n proxyIpSource: '客戶端 IP 來源',\n proxyIpSourceHint:\n 'auto 會依序嘗試 CF-Connecting-IP、X-Real-IP、X-Forwarded-For。僅直連時先選「socket」。',\n proxySrcAuto: '自動(建議)',\n proxySrcCf: 'Cloudflare(CF-Connecting-IP)',\n proxySrcNginx: 'nginx(X-Real-IP)',\n proxySrcXff: '僅 X-Forwarded-For',\n proxySrcSocket: '僅 TCP socket(無代理)',\n trustedProxies: '可信代理 IP / CIDR',\n trustedProxiesHint:\n '只有這些 peer 才可設定 CF-Connecting-IP / X-Real-IP / XFF。預設 127.0.0.1(本機 nginx)。遠端代理請加入其 IP。直連客戶無法偽造 header。',\n sectionLimits: '限流',\n sectionAuth: '失敗認證',\n sectionRate: '限流濫用(429)',\n sectionConn: '連線洪水',\n sectionVelocity: '請求速率',\n sectionEscalate: '累犯升級',\n sectionWhitelist: '自動封鎖白名單',\n whitelistHint: '每行一個 IP 或 CIDR。白名單 IP 永不被自動封鎖。',\n rateWindow: '視窗(秒)',\n rateMaxKey: '金鑰上限',\n rateMaxIp: '未認證 IP 上限',\n burstWindow: 'Burst 視窗(秒)',\n burstMax: 'Burst 上限',\n enableRule: '啟用',\n threshold: '門檻',\n windowSec: '視窗(秒)',\n banMin: '封鎖時長(分)',\n escalateAfter: '累計自動封鎖 N 次後升級',\n escalateMin: '升級後封鎖(分)',\n maxConcurrent: '每 IP 最大並發',\n velocityMax: '最大請求數',\n eventsTitle: '最近自動封鎖事件',\n eventTime: '時間',\n eventSource: '規則',\n eventDuration: '封鎖時長',\n sources: {\n manual: '手動',\n 'auto-auth': '自動 · 認證',\n 'auto-rate': '自動 · 429',\n 'auto-conn': '自動 · 並發',\n 'auto-velocity': '自動 · 速率',\n 'auto-escalate': '自動 · 升級',\n },\n },\n pm2: {\n title: 'PM2 控制',\n tabRunner: '運行方式',\n tabPort: '連接埠',\n tabConfig: '設定',\n tabLogs: '日誌',\n status: '進程狀態',\n start: '用 PM2 啟動',\n stop: '停止 PM2',\n restart: '重啟',\n reload: '重載',\n logs: '日誌',\n logsHint: '優先顯示錯誤日誌',\n clearLogs: '清除日誌',\n confirmClearLogs: '確定清除 PM2 與 ysk-omni 日誌檔?此操作無法復原(檔案會被清空)。',\n logsCleared: '已清除 {n} 個日誌檔。',\n logsAutoTrim: '超過 {maxMb} MB 會自動裁剪,只保留最後約 {keepKb} KB(每次讀取日誌時檢查)。',\n refresh: '重新整理',\n confirmStop: '確定停止 PM2 進程?',\n confirmRestart: '確定以 PM2 重啟?會妥善移交 port。',\n unavailable: 'PM2 不可用',\n disabled: '已停用 PM2 管理',\n app: '應用名稱',\n pid: '進程 ID',\n uptime: '運行時間',\n memory: '記憶體',\n cpu: 'CPU',\n restarts: '重啟次數',\n portBusy: '連接埠佔用中',\n port: '連接埠',\n portTitle: '監聽連接埠',\n portHint:\n 'Gateway Admin 與 API 的 HTTP 連接埠。更改後會寫入 .env 並重啟進程,新連接埠才會生效。',\n fieldPort: '連接埠',\n portDefaultNote: '預設為 3850。有效範圍:1–65535。',\n savePort: '儲存連接埠並重啟',\n useDefaultPort: '使用預設(3850)',\n portInvalid: '請輸入有效連接埠(1–65535)。',\n confirmPortChange:\n '將監聽連接埠改為 {port} 並重啟 Gateway?之後請用新連接埠開啟 Admin(例如 http://localhost:{port}/admin)。',\n portChangedMsg: '連接埠已更新:{from} → {to}。',\n portSavedNeedRestart: '連接埠 {port} 已寫入 .env。請重啟後才會生效。',\n portAfterRestart: '重啟後請開啟 http://localhost:{port}/admin',\n hint: '可用 PM2 或 ysk-omni 運行,可在此或 CLI 切換。',\n switchTitle: '運行方式',\n switchHint: '同一時間只應有一個進程綁定連接埠。',\n currentRunner: '目前 runner',\n runnerPm2: 'PM2',\n runnerGctoac: 'ysk-omni(獨立進程)',\n runnerNone: '未運行',\n runnerUnknown: '未知/混合',\n switchToPm2: '切換到 PM2',\n switchToGctoac: '切換到 ysk-omni',\n confirmSwitchPm2: '確定切換到 PM2?gateway 會在數秒內以 PM2 重啟。',\n confirmSwitchGctoac: '確定切換到 ysk-omni?gateway 會在數秒內以獨立進程重啟。',\n switchScheduled: '已排程切換。管理面板將在約 10 秒後自動重新整理。',\n autoRefreshIn: '本頁將於 {n} 秒後自動重新載入…',\n autoRefreshNow: '正在重新載入…',\n omniPid: 'ysk-omni 進程 ID',\n configTitle: 'PM2 設定',\n configHint: '儲存至 pm2.runtime.json,經 ecosystem.config.cjs 套用。若目前用 PM2 運行,「儲存並套用」會重啟 PM2。',\n saveConfig: '儲存並套用',\n saveOnly: '只儲存',\n resetConfig: '還原預設',\n confirmReset: '確定將 PM2 設定還原為預設?',\n configSaved: '設定已儲存',\n fieldName: '應用名稱',\n fieldScript: '啟動腳本',\n fieldCwd: '工作目錄 (cwd)',\n fieldInstances: '實例數',\n fieldExecMode: '執行模式',\n fieldAutorestart: '自動重啟',\n fieldWatch: '檔案監視 (Watch)',\n fieldMaxMem: '記憶體上限重啟',\n fieldMaxRestarts: '最大重啟次數',\n fieldMinUptime: '最短運行時間',\n fieldRestartDelay: '重啟延遲 (ms)',\n fieldBackoff: '指數退避延遲 (ms)',\n fieldMergeLogs: '合併日誌',\n fieldTime: '日誌時間戳',\n fieldErrorFile: '錯誤日誌檔',\n fieldOutFile: '輸出日誌檔',\n fieldEnvExtra: '額外環境變數(每行 KEY=value)',\n fieldPreferred: '偏好 runner',\n empty: 'pm2 列表中找不到此應用',\n modeFork: 'fork',\n modeCluster: 'cluster',\n phCwd: '(套件根目錄)',\n phInstances: '1 或 max',\n phEnv: 'NODE_ENV=production',\n statusOnline: '運行中',\n statusErrored: '錯誤',\n statusStopped: '已停止',\n msgOk: '正常',\n msgDisabled: 'PM2 管理已停用(PM2_ADMIN_ENABLED=false)。',\n msgBinaryMissing: '找不到 pm2,請執行:npm install -g pm2',\n msgNotInList:\n '應用「{app}」不在 PM2 列表中 — 請用「用 PM2 啟動」或「切換到 PM2」。',\n msgPortGctoac:\n '連接埠 {port} 正由 ysk-omni 佔用(pid {pid})。請按「切換到 PM2」移交。',\n msgPortBusy: '連接埠 {port} 被佔用(pid {pids})。',\n msgErrored:\n 'PM2 進程出錯 — 請查日誌/設定,然後重啟或處理連接埠衝突。',\n msgBothRunners:\n '偵測到兩個 runner;ysk-omni pid {pid} 仍佔用資源。請用「切換」只保留一個。',\n msgError: 'PM2 錯誤:{error}',\n msgSwitchPm2: '正在切換至 PM2… Gateway 將於數秒內以 PM2 重新啟動。',\n msgSwitchGctoac:\n '正在切換至 ysk-omni… Gateway 將於數秒內以獨立進程重新啟動。',\n },\n system: {\n title: '系統狀態',\n tabSoftware: '軟件',\n tabPackage: '套件',\n tabEnv: '環境',\n envHint: '運行環境與版本快照。',\n checkUpdate: '檢查更新',\n oneClick: '更新套件並重啟',\n selfUpdate: '套件版本',\n selfHint: '對比版本 · 更新套件會重啟 gateway。',\n current: '本機版本',\n npm: 'npm 最新版',\n github: 'GitHub 最新版',\n install: '安裝渠道',\n confirmUpdate: '確定更新套件並重啟 gateway?期間 API 會短暫中斷。',\n scheduled: '已排程更新,請約 30 秒後重新整理頁面。',\n database: '資料庫',\n textEngine: '文字引擎',\n concurrency: '併發',\n runtime: '運行狀態',\n software: '系統軟件',\n softwareHint: '所需軟件與已安裝版本。',\n softName: '軟件',\n softLevel: '需求',\n softInstalled: '已安裝',\n softVersion: '版本',\n softStatus: '狀態',\n softDetail: '說明',\n levelRequired: '必須',\n levelRecommended: '建議',\n levelOptional: '可選',\n levelBundled: '內建',\n softOk: '正常',\n softMissing: '未安裝',\n softWarn: '注意',\n envTitle: '環境變數',\n up: '正常',\n down: '異常',\n yes: '是',\n no: '否',\n badgeUpdate: '有新版本',\n badgeOk: '已是最新',\n badgeAhead: '新於 npm',\n badgeUnknown: '無法比較',\n statusHintUpdate: '發佈庫有較新版本,可按「更新套件並重啟」。',\n statusHintOk: '本機版本與目前已知最新發佈版一致。',\n statusHintAhead:\n '本機版本比 npm 新(常見於 git/開發版)。若是 git 安裝,「更新套件」仍可拉取最新 commits。',\n statusHintUnknown: '無法連上 npm/GitHub,未能比較版本。',\n checkResult: '版本檢查結果',\n channelGit: 'git(開發目錄)',\n channelNpmGlobal: 'npm 全域',\n channelNpmLocal: 'npm 本地',\n channelUnknown: '未知',\n encryption: '加密',\n ready: '就緒',\n notReady: '未就緒',\n allRequiredOk: '必須軟件齊全',\n requiredMissing: '有必須軟件缺失',\n },\n support: {\n title: '支援',\n subtitle: '作者、贊助與 YSK Limited — 免費產品,務實支援',\n pillSupport: '支援',\n pillSponsor: '支援/贊助 Linktree',\n pillHelp: '遇到問題? email@ysk.hk',\n creatorTitle: '作者',\n creatorBody:\n '本閘道為免費開源產品,供希望以本機模型提供 API 的使用者。項目以開源方式維護;你的意見與錯誤回報十分重要。',\n sponsorTitle: '支援/贊助',\n sponsorBody:\n '若本閘道為你節省時間,歡迎贊助開發。每一份支援均有助產品繼續免費供所有人使用。',\n githubSponsors: 'GitHub 贊助',\n linktree: 'Linktree',\n walletsTitle: '加密貨幣/Web3 地址',\n walletsHint: '請只在對應網絡轉帳,轉帳前請再次核對地址。',\n net: '網絡',\n addr: '地址',\n copy: '複製',\n netEvm: 'EVM (ETH/BSC/AVAX)',\n netNear: 'NEAR',\n netAda: 'ADA (Cardano)',\n yskTitle: 'YSK Limited',\n yskBody: '需要超出免費面板的人手協助?YSK Limited 可以提供:',\n yskLi1: '伺服器安裝、加固與日常維運',\n yskLi2: '主機架構設計(網站、電郵、DNS、資料庫)',\n yskLi3: '遷移、自動化與客製整合',\n yskLi4: '事故處理與上線就緒檢查',\n yskPrice: '此處不標價 — 請來信,我們會按你的環境商討方案。',\n site: 'ysk.hk',\n helpTitle: '遇到問題?',\n helpBody:\n '請來信說明作業系統、安裝紀錄路徑,以及預期與實際結果。每封來信均會閱讀。',\n docs: '完整文件見倉庫 README',\n },\n common: {\n empty: '暫無資料',\n active: '啟用',\n revoked: '已撤銷',\n save: '儲存',\n cancel: '關閉',\n loading: '載入中…',\n powered: '技術支援',\n actions: '操作',\n yes: '是',\n no: '否',\n ok: '確定',\n confirm: '確定',\n notice: '提示',\n confirmTitle: '請確認',\n dangerTitle: '確認操作',\n apply: '套用',\n reset: '重設',\n search: '搜尋',\n prev: '上一頁',\n next: '下一頁',\n perPage: '每頁',\n pagerTotal: '共 {n} 筆',\n pagerPage: '第 {n} / {total} 頁',\n filterTitle: '搜尋與篩選',\n filterHint: '設定條件後按「套用」',\n sortHint: '點擊欄位以 API 排序(預設:最新在前)',\n featureOff: '已關閉',\n all: '全部',\n requestFailed: '請求失敗',\n ms: '{n} 毫秒',\n perMin: '{n}/分',\n minutes: '{n} 分鐘',\n mb: '{n} MB',\n percent: '{n}%',\n ipLabel: 'IP',\n uaLabel: 'UA',\n httpStatus: 'HTTP',\n },\n /** API error.code → 使用者可見訊息(管理面板) */\n errors: {\n unauthorized: '憑證無效或缺失,請重新登入。',\n forbidden: '你沒有執行此操作的權限。',\n not_found: '找不到請求的資源。',\n validation_error: '請求無效,請檢查輸入內容。',\n rate_limit_exceeded: '已超過速率限制,請稍後再試。',\n concurrency_limit_exceeded: '引擎並行工作過多,請稍候再試。',\n internal_error: '伺服器發生內部錯誤。',\n engine_error: '本機引擎回傳錯誤。',\n engine_timeout: '本機引擎執行逾時。',\n engine_not_available: '此伺服器沒有可用的本機引擎。',\n document_too_large: '文件大小超過允許上限。',\n document_type_not_allowed: '不允許此文件類型。',\n invalid_cwd: '不允許使用此工作目錄。',\n service_unavailable: '服務暫時無法使用。',\n queue_full: '對話佇列已滿,請稍後再試。',\n queue_draining: '對話佇列已暫停或正在排空。',\n queue_wait_timeout: '在對話佇列中等待逾時。',\n queue_cancelled: '對話工作已取消。',\n media_not_supported: '此媒體功能不可用或已停用。',\n media_provider_unavailable: '媒體提供者不可用。',\n media_generation_failed: '媒體生成失敗。',\n media_forbidden:\n '此 API 金鑰不允許生成媒體。請使用 agent 模式金鑰或管理員工作階段。',\n feature_disabled: '此 API 功能已停用。',\n feature: {\n imagesApi:\n 'Images API 已停用。請至「管理 → API 能力 → Images API」啟用。',\n videoApi:\n 'Video API 已停用。請至「管理 → API 能力 → Videos API」啟用。',\n audioApi:\n 'Audio API 已停用。請至「管理 → API 能力 → Audio API」啟用。',\n tools:\n 'Tools 已停用。請至「管理 → API 能力」啟用 Tools(圖像生成需要)。',\n filesOpenAiAlias:\n 'OpenAI Files API 別名已停用。請至「管理 → API 能力 → Files API 別名」啟用。',\n },\n media: {\n agent_or_admin_required:\n '圖像生成需要 agent 模式 API 金鑰或管理員工作階段。安全模式金鑰無法使用圖像工具。',\n source_required: '請提供圖像檔、媒體資產或文件作為來源。',\n source_must_be_image: '編輯或生成影片時,來源必須為圖像。',\n no_image_in_sandbox:\n '生成已結束,但未找到圖像檔。這不是 imagesApi 或 API 金鑰問題。',\n no_video_in_sandbox:\n '生成已結束,但未找到影片檔。',\n provider_no_edit: '目前媒體提供者不支援圖像編輯。',\n },\n },\n },\n};\n\nfunction detectLocale() {\n const saved = localStorage.getItem(LANG_KEY);\n if (saved === 'en' || saved === 'zh-Hant') return saved;\n const nav = (navigator.language || navigator.userLanguage || 'en').toLowerCase();\n if (nav.startsWith('zh')) return 'zh-Hant';\n return 'en';\n}\n\nlet locale = detectLocale();\n\nexport function getLocale() {\n return locale;\n}\n\nexport function setLocale(next) {\n if (next !== 'en' && next !== 'zh-Hant') return;\n locale = next;\n localStorage.setItem(LANG_KEY, next);\n}\n\nexport function t(path) {\n const parts = path.split('.');\n let cur = dict[locale] || dict.en;\n for (const p of parts) {\n if (cur && typeof cur === 'object' && p in cur) cur = cur[p];\n else {\n cur = dict.en;\n for (const q of parts) {\n if (cur && typeof cur === 'object' && q in cur) cur = cur[q];\n else return path;\n }\n break;\n }\n }\n return typeof cur === 'string' ? cur : path;\n}\n\n/** True if path resolves to a real string (not missing key). */\nexport function hasT(path) {\n return t(path) !== path;\n}\n\n/** t() with {name} placeholders: tf('keys.ipCount', { n: 3 }) */\nexport function tf(path, vars = {}) {\n let s = t(path);\n for (const [k, v] of Object.entries(vars)) {\n s = s.replaceAll(`{${k}}`, String(v));\n }\n return s;\n}\n\nexport function langSwitchHtml() {\n const aria = locale === 'zh-Hant' ? '語言' : 'Language';\n return `\n <div class=\"lang-switch\" role=\"group\" aria-label=\"${aria}\">\n <button type=\"button\" data-lang=\"en\" class=\"${locale === 'en' ? 'is-active' : ''}\">EN</button>\n <button type=\"button\" data-lang=\"zh-Hant\" class=\"${locale === 'zh-Hant' ? 'is-active' : ''}\">中文</button>\n </div>`;\n}\n","// AUTO-GENERATED by scripts/generate-allowed-extensions.cjs — do not edit.\n// Source: src/config/constants.ts ALLOWED_UPLOAD_EXTENSIONS\nexport const CHAT_ALLOWED_EXTENSIONS = new Set([\n \".txt\",\n \".md\",\n \".markdown\",\n \".csv\",\n \".json\",\n \".xml\",\n \".html\",\n \".htm\",\n \".js\",\n \".ts\",\n \".tsx\",\n \".jsx\",\n \".py\",\n \".java\",\n \".go\",\n \".rs\",\n \".c\",\n \".cpp\",\n \".h\",\n \".hpp\",\n \".css\",\n \".yml\",\n \".yaml\",\n \".toml\",\n \".ini\",\n \".env\",\n \".sh\",\n \".sql\",\n \".log\",\n \".pdf\",\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".webp\",\n \".gif\"\n]);\n\nexport const CHAT_FILE_ACCEPT = [...CHAT_ALLOWED_EXTENSIONS].join(',');\n","import { t, tf, hasT, getLocale, setLocale, langSwitchHtml } from './i18n.js';\nimport { CHAT_ALLOWED_EXTENSIONS, CHAT_FILE_ACCEPT } from './allowed-extensions.js';\n\nconst API = '/admin/api';\n/** Admin SPA session token (OTP login) — never store long-lived API keys here */\nconst KEY_STORAGE = 'gog_admin_session';\n\n/** @type {ReturnType<typeof setInterval> | null} */\nlet ddosTimer = null;\nlet ddosPaused = false;\n\n/**\n * Map OpenAI-style API error envelope → localized Admin message.\n * Prefers error.code + details.feature / details.reason; falls back to message fingerprints.\n * @param {any} data parsed JSON body\n * @param {string} [statusText]\n */\nfunction formatApiError(data, statusText) {\n const err = data?.error && typeof data.error === 'object' ? data.error : data || {};\n const code = typeof err.code === 'string' ? err.code : '';\n const details =\n err.details && typeof err.details === 'object' ? err.details : {};\n const feature =\n typeof details.feature === 'string'\n ? details.feature\n : typeof details.flag === 'string'\n ? details.flag\n : '';\n const reason = typeof details.reason === 'string' ? details.reason : '';\n const rawMsg = String(err.message || data?.message || statusText || '');\n\n // Feature flags (videoApi / imagesApi / tools / …)\n if (\n feature &&\n (code === 'feature_disabled' ||\n code === 'media_not_supported' ||\n code === 'forbidden')\n ) {\n const key = `errors.feature.${feature}`;\n if (hasT(key)) return t(key);\n }\n if (code === 'feature_disabled' && hasT('errors.feature_disabled')) {\n // try fingerprint from message if feature missing\n const fp = fingerprintFeature(rawMsg);\n if (fp && hasT(`errors.feature.${fp}`)) return t(`errors.feature.${fp}`);\n return t('errors.feature_disabled');\n }\n\n // Media / validation reason codes\n if (reason && hasT(`errors.media.${reason}`)) {\n return t(`errors.media.${reason}`);\n }\n if (code === 'media_generation_failed' && reason && hasT(`errors.media.${reason}`)) {\n return t(`errors.media.${reason}`);\n }\n if (code === 'media_forbidden' && hasT('errors.media_forbidden')) {\n return t('errors.media_forbidden');\n }\n\n // Legacy English bodies often use media_not_supported without details.feature\n const fpEarly = fingerprintFeature(rawMsg);\n if (fpEarly && hasT(`errors.feature.${fpEarly}`)) {\n return t(`errors.feature.${fpEarly}`);\n }\n\n // Generic error.code map\n if (code) {\n const key = `errors.${code}`;\n if (hasT(key)) return t(key);\n }\n\n // Legacy English server messages (before code/details were standardized)\n const fp = fingerprintFeature(rawMsg);\n if (fp && hasT(`errors.feature.${fp}`)) return t(`errors.feature.${fp}`);\n if (/agent-mode|agent mode|Safe keys cannot/i.test(rawMsg)) {\n return t('errors.media.agent_or_admin_required');\n }\n if (/no image file was found/i.test(rawMsg)) {\n return t('errors.media.no_image_in_sandbox');\n }\n if (/no video file was found/i.test(rawMsg)) {\n return t('errors.media.no_video_in_sandbox');\n }\n if (/does not support image edits/i.test(rawMsg)) {\n return t('errors.media.provider_no_edit');\n }\n if (/Provide an image file|sourceAssetId|sourceDocumentId/i.test(rawMsg)) {\n return t('errors.media.source_required');\n }\n if (/must be an image/i.test(rawMsg)) {\n return t('errors.media.source_must_be_image');\n }\n\n return rawMsg || t('common.requestFailed');\n}\n\nfunction fingerprintFeature(msg) {\n const m = String(msg || '');\n if (/videoApi/i.test(m) || /Video API is disabled/i.test(m)) return 'videoApi';\n if (/imagesApi/i.test(m) || /Images API is disabled/i.test(m)) return 'imagesApi';\n if (/audioApi/i.test(m) || /Audio API is disabled/i.test(m)) return 'audioApi';\n if (/filesOpenAiAlias/i.test(m) || /Files API alias/i.test(m))\n return 'filesOpenAiAlias';\n if (\n /Tools are disabled/i.test(m) ||\n (/\\btools\\b/i.test(m) && /disabled/i.test(m) && /image/i.test(m))\n ) {\n return 'tools';\n }\n return '';\n}\n\nconst state = {\n key: sessionStorage.getItem(KEY_STORAGE) || '',\n page: 'dashboard',\n me: null,\n error: '',\n modal: null,\n chatFilter: {\n q: '',\n status: '',\n model: '',\n apiKeyId: '',\n from: '',\n to: '',\n policyMode: '',\n hasDocuments: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n limit: 50,\n offset: 0,\n },\n docFilter: {\n q: '',\n apiKeyId: '',\n storageType: '',\n from: '',\n to: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n limit: 20,\n offset: 0,\n },\n keyFilter: {\n q: '',\n role: '',\n mode: '',\n isActive: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n limit: 20,\n offset: 0,\n },\n auditFilter: {\n q: '',\n action: '',\n apiKeyId: '',\n from: '',\n to: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n limit: 50,\n offset: 0,\n },\n usageFilter: {\n tab: 'model', // 'model' | 'key'\n modelQ: '',\n keyQ: '',\n keyActive: '',\n modelPage: 0,\n keyPage: 0,\n pageSize: 10,\n /** perKey: default lastUsedAt desc */\n sortBy: 'lastUsedAt',\n sortDir: 'desc',\n /** byModel: no time column — default requests desc */\n modelSortBy: 'requests',\n modelSortDir: 'desc',\n },\n ddosFilter: {\n /** 'policy' | 'live' | 'blacklist' | 'events' */\n tab: 'policy',\n liveQ: '',\n banQ: '',\n banSource: '',\n livePage: 0,\n banPage: 0,\n pageSize: 15,\n liveSortBy: 'startedAt',\n liveSortDir: 'desc',\n banSortBy: 'createdAt',\n banSortDir: 'desc',\n eventSortBy: 'at',\n eventSortDir: 'desc',\n },\n mediaFilter: {\n /** 'studio' | 'assets' | 'jobs' — same tab pattern as chat queue */\n tab: 'studio',\n q: '',\n kind: '',\n provider: '',\n from: '',\n to: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n jobSortBy: 'createdAt',\n jobSortDir: 'desc',\n limit: 20,\n offset: 0,\n },\n /** System page tab: 'software' | 'package' | 'env' | 'sessions' */\n systemTab: 'software',\n sessionQ: '',\n /** PM2 page tab: 'runner' | 'port' | 'config' | 'logs' */\n pm2Tab: 'runner',\n /** API features tab: 'protocols' | 'media' | 'caps' | 'emu' */\n apiFeaturesTab: 'protocols',\n /** Catalog: 'packs' | 'local' */\n catalogTab: 'local',\n catalogModality: '',\n catalogPulling: '',\n catalogPull: { id: '', bytes: 0, total: 0 },\n catalogQueue: [],\n catalogQueueRunning: false,\n catalogHubQ: '',\n catalogHubHits: null,\n catalogHubNext: '',\n catalogHubBusy: false,\n catalogPopularSyncedAt: '',\n runtimesOs: 'host',\n runtimesMod: '',\n runtimesReport: null,\n runtimesInstall: null,\n models: [],\n catalogLocal: [],\n keys: [],\n};\n\n/** Hash routes: #/dashboard, #/media, #/api-features … */\nconst PAGE_FROM_HASH = {\n login: 'login',\n dashboard: 'dashboard',\n chat: 'chat',\n chats: 'chats',\n keys: 'keys',\n documents: 'documents',\n media: 'media',\n catalog: 'catalog',\n runtimes: 'runtimes',\n audit: 'audit',\n settings: 'settings',\n 'api-features': 'apiFeatures',\n apifeatures: 'apiFeatures',\n usage: 'usage',\n ddos: 'ddos',\n queue: 'queue',\n pm2: 'pm2',\n system: 'system',\n support: 'support',\n};\n\nfunction pageToHash(page) {\n if (page === 'apiFeatures') return 'api-features';\n return page || 'dashboard';\n}\n\nfunction hashToPage(hash) {\n const raw = String(hash || '')\n .replace(/^#\\/?/, '')\n .split('?')[0]\n .split('/')[0]\n .toLowerCase();\n if (!raw) return null;\n if (raw === 'runtime' || raw === 'engines' || raw === 'engine') return 'runtimes';\n return PAGE_FROM_HASH[raw] || null;\n}\n\nfunction writePageHash(page) {\n const h = `#/${pageToHash(page)}`;\n if (location.hash !== h) {\n // push so browser Back works between admin pages\n history.pushState(null, '', h);\n }\n}\n\nfunction readInitialPage() {\n const fromHash = hashToPage(location.hash);\n if (fromHash) return fromHash;\n return state.key ? 'dashboard' : 'login';\n}\n\nasync function api(path, options = {}) {\n const headers = {\n ...(options.body ? { 'Content-Type': 'application/json' } : {}),\n ...(state.key ? { Authorization: `Bearer ${state.key}` } : {}),\n ...(options.headers || {}),\n };\n const res = await fetch(`${API}${path}`, { ...options, headers });\n const text = await res.text();\n let data = null;\n try {\n data = text ? JSON.parse(text) : null;\n } catch {\n data = { error: { message: text } };\n }\n if (!res.ok) {\n const msg = formatApiError(data, res.statusText);\n const code = data?.error?.code || '';\n if (res.status === 401) {\n if (state.page !== 'login') logout(false);\n } else if (res.status === 403) {\n // Keep session for permission / feature errors (not bad credentials)\n const keepSession = [\n 'media_forbidden',\n 'feature_disabled',\n 'forbidden',\n 'media_not_supported',\n ].includes(code);\n if (!keepSession && state.page !== 'login') logout(false);\n }\n const e = new Error(msg);\n e.status = res.status;\n e.code = code;\n e.details = data?.error?.details;\n throw e;\n }\n return data;\n}\n\n/** Parse fetch Response as JSON and throw localized Error if !ok */\nasync function parseApiResponse(res) {\n const text = await res.text();\n let data = null;\n try {\n data = text ? JSON.parse(text) : null;\n } catch {\n data = { error: { message: text } };\n }\n if (!res.ok) {\n const msg = formatApiError(data, res.statusText);\n const e = new Error(msg);\n e.status = res.status;\n e.code = data?.error?.code;\n e.details = data?.error?.details;\n throw e;\n }\n return data;\n}\n\nfunction logout(clear = true) {\n const token = state.key;\n if (clear && token && String(token).startsWith('gog_sess_')) {\n fetch('/admin/api/auth/logout', {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}` },\n }).catch(() => {});\n }\n if (clear) sessionStorage.removeItem(KEY_STORAGE);\n state.key = '';\n state.me = null;\n state.page = 'login';\n writePageHash('login');\n render();\n}\n\nfunction setPage(page) {\n applyPageChange(page, { writeHash: true });\n}\n\n/**\n * @param {string} page\n * @param {{ writeHash?: boolean }} [opts]\n */\nfunction applyPageChange(page, opts = {}) {\n const next = page || 'dashboard';\n state.page = next;\n state.modal = null;\n state.error = '';\n if (next === 'chats') state.chatFilter.offset = 0;\n if (next === 'documents') state.docFilter.offset = 0;\n if (next === 'keys') state.keyFilter.offset = 0;\n if (next === 'audit') state.auditFilter.offset = 0;\n if (next === 'media') state.mediaFilter.offset = 0;\n if (next !== 'ddos' && ddosTimer) {\n clearInterval(ddosTimer);\n ddosTimer = null;\n }\n // leave chat → close mobile history drawer\n if (next !== 'chat') {\n document.body.classList.remove('chat-history-open');\n }\n if (opts.writeHash !== false) writePageHash(next);\n render();\n}\n\nfunction escapeHtml(s) {\n return String(s ?? '')\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;');\n}\n\n/** @type {HTMLElement | null} */\nlet uiDialogRoot = null;\n/** @type {((v: unknown) => void) | null} */\nlet uiDialogResolve = null;\n\nfunction closeUiDialog(result) {\n const resolve = uiDialogResolve;\n uiDialogResolve = null;\n if (uiDialogRoot) {\n uiDialogRoot.remove();\n uiDialogRoot = null;\n }\n document.body.classList.remove('ui-dialog-open');\n document.removeEventListener('keydown', onUiDialogKeydown, true);\n if (resolve) resolve(result);\n}\n\nfunction onUiDialogKeydown(e) {\n if (!uiDialogRoot) return;\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n const cancelable = uiDialogRoot.dataset.cancelable !== '0';\n // alert-only: Escape dismisses as OK; confirm/prompt: cancel\n closeUiDialog(cancelable ? (uiDialogRoot.dataset.prompt === '1' ? null : false) : true);\n }\n}\n\n/**\n * In-app dialog (replaces window.alert / confirm / prompt).\n * @param {{\n * title?: string,\n * message: string,\n * variant?: 'info' | 'confirm' | 'danger',\n * confirmText?: string,\n * cancelText?: string,\n * showCancel?: boolean,\n * input?: boolean,\n * defaultValue?: string,\n * placeholder?: string,\n * maxLength?: number,\n * }} opts\n * @returns {Promise<boolean | string | null>}\n * confirm/alert → boolean; prompt → string | null (null = cancel)\n */\nfunction openUiDialog(opts) {\n // Replace any open dialog\n if (uiDialogRoot) closeUiDialog(false);\n\n const variant = opts.variant || (opts.showCancel === false ? 'info' : 'confirm');\n const showCancel = opts.showCancel !== false;\n const isPrompt = Boolean(opts.input);\n const title =\n opts.title ||\n (variant === 'danger'\n ? t('common.dangerTitle')\n : showCancel\n ? t('common.confirmTitle')\n : t('common.notice'));\n const confirmText =\n opts.confirmText ||\n (showCancel ? t('common.confirm') : t('common.ok'));\n const cancelText = opts.cancelText || t('common.cancel');\n const icon =\n variant === 'danger' ? '!' : variant === 'info' && !showCancel ? 'i' : '?';\n\n const root = document.createElement('div');\n root.className = 'ui-dialog-back';\n root.id = 'ui-dialog-back';\n root.dataset.cancelable = showCancel || isPrompt ? '1' : '0';\n root.dataset.prompt = isPrompt ? '1' : '0';\n root.setAttribute('role', 'presentation');\n root.innerHTML = `\n <div class=\"ui-dialog ui-dialog--${escapeHtml(variant)}${isPrompt ? '' : ''}\" role=\"alertdialog\" aria-modal=\"true\" aria-labelledby=\"ui-dialog-title\" aria-describedby=\"ui-dialog-msg\">\n <div class=\"ui-dialog-h\">\n <div class=\"ui-dialog-icon\" aria-hidden=\"true\">${icon}</div>\n <h3 class=\"ui-dialog-title\" id=\"ui-dialog-title\">${escapeHtml(title)}</h3>\n </div>\n <div class=\"ui-dialog-body\" id=\"ui-dialog-msg\">${escapeHtml(opts.message || '')}</div>\n ${\n isPrompt\n ? `<div class=\"ui-dialog-input-wrap\">\n <input type=\"text\" class=\"ui-dialog-input\" id=\"ui-dialog-input\" value=\"${escapeHtml(opts.defaultValue || '')}\" placeholder=\"${escapeHtml(opts.placeholder || '')}\" maxlength=\"${opts.maxLength || 500}\" autocomplete=\"off\" />\n </div>`\n : ''\n }\n <div class=\"ui-dialog-actions\">\n ${\n showCancel || isPrompt\n ? `<button type=\"button\" class=\"btn secondary sm\" id=\"ui-dialog-cancel\">${escapeHtml(cancelText)}</button>`\n : ''\n }\n <button type=\"button\" class=\"btn ${variant === 'danger' ? 'danger' : ''} sm\" id=\"ui-dialog-ok\">${escapeHtml(confirmText)}</button>\n </div>\n </div>`;\n\n document.body.appendChild(root);\n document.body.classList.add('ui-dialog-open');\n uiDialogRoot = root;\n document.addEventListener('keydown', onUiDialogKeydown, true);\n\n const okBtn = root.querySelector('#ui-dialog-ok');\n const cancelBtn = root.querySelector('#ui-dialog-cancel');\n const input = root.querySelector('#ui-dialog-input');\n\n const finish = (ok) => {\n if (isPrompt) {\n if (!ok) {\n closeUiDialog(null);\n return;\n }\n const val = input instanceof HTMLInputElement ? input.value : '';\n closeUiDialog(val);\n return;\n }\n closeUiDialog(Boolean(ok));\n };\n\n okBtn?.addEventListener('click', (e) => {\n e.preventDefault();\n finish(true);\n });\n cancelBtn?.addEventListener('click', (e) => {\n e.preventDefault();\n finish(false);\n });\n root.addEventListener('click', (e) => {\n if (e.target === root && (showCancel || isPrompt)) finish(false);\n });\n if (input instanceof HTMLInputElement) {\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n finish(true);\n }\n });\n }\n\n requestAnimationFrame(() => {\n if (input instanceof HTMLInputElement) {\n input.focus();\n input.select();\n } else {\n okBtn?.focus();\n }\n });\n\n return new Promise((resolve) => {\n uiDialogResolve = resolve;\n });\n}\n\n/** @param {string | { title?: string, message: string, variant?: string, confirmText?: string }} msg */\nasync function uiAlert(msg) {\n const opts =\n typeof msg === 'string'\n ? { message: msg, showCancel: false, variant: 'info' }\n : {\n title: msg.title,\n message: msg.message,\n showCancel: false,\n variant: msg.variant || 'info',\n confirmText: msg.confirmText || t('common.ok'),\n };\n await openUiDialog(opts);\n}\n\n/**\n * @param {string | { title?: string, message: string, variant?: 'confirm'|'danger', confirmText?: string, cancelText?: string }} msg\n * @returns {Promise<boolean>}\n */\nasync function uiConfirm(msg) {\n const opts =\n typeof msg === 'string'\n ? { message: msg, showCancel: true, variant: 'confirm' }\n : {\n title: msg.title,\n message: msg.message,\n showCancel: true,\n variant: msg.variant || 'confirm',\n confirmText: msg.confirmText,\n cancelText: msg.cancelText,\n };\n return Boolean(await openUiDialog(opts));\n}\n\n/**\n * @param {string | { title?: string, message?: string, defaultValue?: string, placeholder?: string, maxLength?: number }} msg\n * @returns {Promise<string | null>}\n */\nasync function uiPrompt(msg) {\n const opts =\n typeof msg === 'string'\n ? { message: msg, input: true, showCancel: true, variant: 'confirm' }\n : {\n title: msg.title,\n message: msg.message || '',\n input: true,\n showCancel: true,\n variant: 'confirm',\n defaultValue: msg.defaultValue,\n placeholder: msg.placeholder,\n maxLength: msg.maxLength,\n };\n const result = await openUiDialog(opts);\n return result === null || result === false ? null : String(result);\n}\n\n/** Configure marked once (GFM tables, soft line breaks). */\nfunction ensureMarkedConfigured() {\n const api = typeof window !== 'undefined' ? window.marked : null;\n if (!api || api.__gogConfigured) return api;\n try {\n if (typeof api.setOptions === 'function') {\n api.setOptions({ gfm: true, breaks: true });\n } else if (api.marked && typeof api.marked.setOptions === 'function') {\n api.marked.setOptions({ gfm: true, breaks: true });\n }\n } catch {\n /* ignore */\n }\n api.__gogConfigured = true;\n return api;\n}\n\n/**\n * Render assistant Markdown → sanitized HTML. Fallback to escaped plain text.\n * @param {string} src\n */\nfunction formatChatMarkdown(src) {\n if (!src) return '';\n const markedApi = ensureMarkedConfigured();\n const purify =\n typeof window !== 'undefined' ? window.DOMPurify || window.dompurify : null;\n if (!markedApi) return escapeHtml(src);\n\n let html = '';\n try {\n if (typeof markedApi.parse === 'function') {\n html = markedApi.parse(src, { gfm: true, breaks: true });\n } else if (typeof markedApi === 'function') {\n html = markedApi(src, { gfm: true, breaks: true });\n } else if (markedApi.marked && typeof markedApi.marked.parse === 'function') {\n html = markedApi.marked.parse(src, { gfm: true, breaks: true });\n } else {\n return escapeHtml(src);\n }\n } catch {\n return escapeHtml(src);\n }\n if (typeof html !== 'string') html = String(html ?? '');\n\n if (purify && typeof purify.sanitize === 'function') {\n html = purify.sanitize(html, {\n USE_PROFILES: { html: true },\n ADD_ATTR: ['target', 'rel'],\n });\n // Secure external links\n try {\n html = html.replace(\n /<a\\s+([^>]*href=)/gi,\n '<a target=\"_blank\" rel=\"noopener noreferrer\" $1',\n );\n } catch {\n /* ignore */\n }\n return html;\n }\n // No DOMPurify: refuse raw HTML path — safe plain fallback\n return escapeHtml(src);\n}\n\n/**\n * @param {string} text\n * @returns {Promise<boolean>}\n */\nasync function copyTextToClipboard(text) {\n const value = String(text ?? '');\n if (!value) return false;\n try {\n if (navigator.clipboard && window.isSecureContext !== false) {\n await navigator.clipboard.writeText(value);\n return true;\n }\n } catch {\n /* fallback */\n }\n try {\n const ta = document.createElement('textarea');\n ta.value = value;\n ta.setAttribute('readonly', '');\n ta.style.position = 'fixed';\n ta.style.left = '-9999px';\n document.body.appendChild(ta);\n ta.select();\n const ok = document.execCommand('copy');\n document.body.removeChild(ta);\n return ok;\n } catch {\n return false;\n }\n}\n\nfunction fmtTime(iso) {\n if (!iso) return '-';\n try {\n return new Date(iso).toLocaleString(getLocale() === 'zh-Hant' ? 'zh-HK' : 'en-US');\n } catch {\n return iso;\n }\n}\n\nfunction fmtBytes(n) {\n if (n == null) return '—';\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return tf('common.mb', { n: (n / 1024 / 1024).toFixed(1) });\n}\n\nfunction fmtMs(ms) {\n if (ms == null || ms === '') return '—';\n return tf('common.ms', { n: ms });\n}\n\nfunction fmtPerMin(n) {\n if (n == null || n === '') return '—';\n return tf('common.perMin', { n });\n}\n\nfunction showError(msg) {\n state.error = msg;\n const box = document.querySelector('#flash-error');\n if (box) {\n box.hidden = !msg;\n box.textContent = msg;\n }\n}\n\nfunction badgeStatus(s) {\n const c =\n s === 'success' ? 'success' : s === 'error' || s === 'timeout' ? 'error' : 'pending';\n const label =\n s === 'success'\n ? t('status.success')\n : s === 'error'\n ? t('status.error')\n : s === 'timeout'\n ? t('status.timeout')\n : s === 'pending'\n ? t('status.pending')\n : s || '-';\n return `<span class=\"badge ${c}\">${escapeHtml(label)}</span>`;\n}\n\n/** Job status badges for durable chat queue */\nfunction badgeQueueStatus(s) {\n const map = {\n queued: { cls: 'pending', label: t('queue.stQueued') },\n leased: { cls: 'info', label: t('queue.stLeased') },\n running: { cls: 'success', label: t('queue.stRunning') },\n succeeded: { cls: 'success', label: t('queue.stSucceeded') },\n failed: { cls: 'error', label: t('queue.stFailed') },\n dead: { cls: 'error', label: t('queue.stDead') },\n cancelled: { cls: 'muted', label: t('queue.stCancelled') },\n };\n const m = map[s] || { cls: 'pending', label: s || '—' };\n return `<span class=\"badge ${m.cls}\">${escapeHtml(m.label)}</span>`;\n}\n\nfunction badgeQueueSource(src) {\n const label =\n src === 'playground'\n ? t('queue.srcPlayground')\n : src === 'v1'\n ? t('queue.srcV1')\n : src || '—';\n return `<span class=\"badge muted\">${escapeHtml(label)}</span>`;\n}\n\nfunction badgeMode(m) {\n const mode = m === 'agent' ? 'agent' : m === 'safe' ? 'safe' : m || 'safe';\n const label =\n mode === 'agent'\n ? t('keys.modeAgentBadge')\n : mode === 'safe'\n ? t('keys.modeSafeBadge')\n : mode;\n return `<span class=\"badge ${mode === 'agent' ? 'agent' : 'safe'}\">${escapeHtml(label)}</span>`;\n}\n\nfunction badgeRole(r) {\n const role = String(r || '').toLowerCase();\n const label =\n role === 'admin'\n ? t('keys.roleAdminBadge')\n : role === 'client' || role === 'user'\n ? t('keys.roleClientBadge')\n : r || '-';\n return escapeHtml(label);\n}\n\nfunction isImageMime(m) {\n return String(m || '').toLowerCase().startsWith('image/');\n}\n\n/**\n * Browser-native preview kinds for Media library.\n * @returns {'image'|'video'|'audio'|'pdf'|'text'|null}\n */\nfunction mediaPreviewKind(mime, filename = '') {\n const m = String(mime || '').toLowerCase().trim();\n const name = String(filename || '').toLowerCase();\n const ext = (name.match(/\\.([a-z0-9]+)$/) || [])[1] || '';\n\n if (m.startsWith('image/') || ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'avif', 'ico'].includes(ext)) {\n return 'image';\n }\n if (\n m.startsWith('video/') ||\n ['mp4', 'webm', 'ogg', 'ogv', 'mov', 'm4v'].includes(ext)\n ) {\n // browsers typically play mp4/webm/ogg; still offer <video> for others\n return 'video';\n }\n if (\n m.startsWith('audio/') ||\n ['mp3', 'wav', 'ogg', 'oga', 'm4a', 'aac', 'flac', 'opus'].includes(ext)\n ) {\n return 'audio';\n }\n if (m === 'application/pdf' || ext === 'pdf') return 'pdf';\n if (\n m.startsWith('text/') ||\n m === 'application/json' ||\n m === 'application/xml' ||\n m === 'application/javascript' ||\n ['txt', 'md', 'csv', 'json', 'xml', 'html', 'htm', 'css', 'js', 'log', 'svg'].includes(ext)\n ) {\n // svg already image; skip if image handled\n if (ext === 'svg') return 'image';\n return 'text';\n }\n return null;\n}\n\nfunction isBrowserPreviewable(mime, filename = '') {\n return mediaPreviewKind(mime, filename) != null;\n}\n\n/** @type {string | null} */\nlet mediaPreviewObjectUrl = null;\n\nfunction revokeMediaPreviewUrl() {\n if (mediaPreviewObjectUrl) {\n try {\n URL.revokeObjectURL(mediaPreviewObjectUrl);\n } catch {\n /* ignore */\n }\n mediaPreviewObjectUrl = null;\n }\n}\n\n/**\n * Build lightbox stage HTML for a blob: object URL.\n * @param {'image'|'video'|'audio'|'pdf'|'text'|string} kind\n * @param {string} url\n * @param {string} filename\n */\nfunction mediaLightboxStageHtml(kind, url, filename) {\n if (kind === 'image') {\n return `<img class=\"media-lb-media media-lb-img\" src=\"${url}\" alt=\"${escapeHtml(filename)}\" />`;\n }\n if (kind === 'video') {\n return `<video class=\"media-lb-media media-lb-video\" src=\"${url}\" controls playsinline preload=\"metadata\"></video>`;\n }\n if (kind === 'audio') {\n return `\n <div class=\"media-lb-audio-wrap\">\n <div class=\"media-lb-audio-icon\" aria-hidden=\"true\">♪</div>\n <audio class=\"media-lb-media media-lb-audio\" src=\"${url}\" controls preload=\"metadata\"></audio>\n </div>`;\n }\n if (kind === 'pdf') {\n return `<iframe class=\"media-lb-media media-lb-pdf\" src=\"${url}#toolbar=1\" title=\"${escapeHtml(filename)}\"></iframe>`;\n }\n if (kind === 'text') {\n return `<div class=\"media-lb-text-loading muted\">${escapeHtml(t('common.loading') || '…')}</div>`;\n }\n return `<div class=\"data-empty\"><strong>${escapeHtml(t('media.previewUnsupported'))}</strong></div>`;\n}\n\n/**\n * Professional lightbox modal for media assets (image / video / audio / pdf / text).\n *\n * IMPORTANT: create the blob: object URL *after* openAppModal().\n * openAppModal → closeAppModal → revokeMediaPreviewUrl would otherwise\n * kill the URL immediately (empty / broken preview for every kind).\n *\n * @param {{ id: string, mime?: string, filename?: string, prompt?: string, kind?: string, bytes?: number }} meta\n * @param {Blob} blob\n */\nfunction openMediaPreviewLightbox(meta, blob) {\n const mime = meta.mime || blob.type || '';\n const filename = meta.filename || meta.id || 'asset';\n const kind = mediaPreviewKind(mime, filename) || 'image';\n const title = t('media.preview');\n const subParts = [\n filename,\n mime || '—',\n meta.bytes != null ? fmtBytes(meta.bytes) : '',\n meta.kind || '',\n ].filter(Boolean);\n const subtitle = escapeHtml(subParts.join(' · '));\n\n const promptHtml = meta.prompt\n ? `<div class=\"media-lb-prompt\"><span class=\"muted\">${escapeHtml(t('media.prompt'))}</span><p>${escapeHtml(meta.prompt)}</p></div>`\n : '';\n\n // Open shell first (this revokes any previous preview URL via closeAppModal)\n openAppModal({\n title,\n subtitle,\n size: 'xl',\n bodyHtml: `\n <div class=\"media-lightbox\" data-preview-kind=\"${escapeHtml(kind)}\">\n <div class=\"media-lb-stage\">\n <div class=\"media-lb-text-loading muted\">${escapeHtml(t('common.loading') || '…')}</div>\n </div>\n ${promptHtml}\n </div>`,\n footerHtml: `\n <button type=\"button\" class=\"btn secondary sm\" id=\"media-lb-download\">${escapeHtml(t('media.download'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"media-lb-close\">${escapeHtml(t('common.cancel'))}</button>`,\n });\n\n // Mark modal shell for lightbox styling\n const modal = document.querySelector('#modal-back .modal');\n if (modal) modal.classList.add('modal--media-preview');\n\n // Create object URL only after modal open — never before openAppModal\n const url = URL.createObjectURL(blob);\n mediaPreviewObjectUrl = url;\n\n const stage = document.querySelector('#modal-back .media-lb-stage');\n if (stage) {\n stage.innerHTML = mediaLightboxStageHtml(kind, url, filename);\n }\n\n const close = () => {\n document.querySelectorAll('#modal-back video, #modal-back audio').forEach((el) => {\n try {\n el.pause();\n } catch {\n /* ignore */\n }\n });\n revokeMediaPreviewUrl();\n closeAppModal();\n };\n\n // Bind close / download (openAppModal already wires modal-x + backdrop; re-bind to revoke)\n document.getElementById('modal-close')?.addEventListener('click', (e) => {\n e.preventDefault();\n close();\n });\n document.getElementById('media-lb-close')?.addEventListener('click', (e) => {\n e.preventDefault();\n close();\n });\n document.getElementById('modal-back')?.addEventListener('click', (e) => {\n if (e.target?.id === 'modal-back') close();\n });\n document.getElementById('media-lb-download')?.addEventListener('click', () => {\n const a = document.createElement('a');\n a.href = url;\n a.download = filename || `media-${String(meta.id || '').slice(0, 8)}`;\n a.click();\n });\n\n if (kind === 'text') {\n blob\n .text()\n .then((text) => {\n const el = document.querySelector('#modal-back .media-lb-stage');\n if (!el) return;\n const max = 400_000;\n const clipped =\n text.length > max\n ? text.slice(0, max) + `\\n… (${t('media.previewTruncated')})`\n : text;\n el.innerHTML = `<pre class=\"media-lb-text\">${escapeHtml(clipped)}</pre>`;\n })\n .catch(() => {\n const el = document.querySelector('#modal-back .media-lb-stage');\n if (el) {\n el.innerHTML = `<div class=\"error-box\">${escapeHtml(t('media.previewFail'))}</div>`;\n }\n });\n }\n}\n\nfunction poweredByFooter() {\n return `\n <footer class=\"site-footer\">\n <a class=\"powered-by\" href=\"https://ysk.hk/\" target=\"_blank\" rel=\"noopener noreferrer\">\n <img src=\"/admin/assets/logo.svg\" alt=\"\" width=\"22\" height=\"22\" />\n <span>${escapeHtml(t('common.powered'))} <strong>YSK Limited</strong></span>\n </a>\n </footer>`;\n}\n\nfunction pageTitle() {\n const map = {\n dashboard: t('nav.dashboard'),\n chat: t('nav.chat'),\n chats: t('nav.chats'),\n keys: t('nav.keys'),\n documents: t('nav.documents'),\n audit: t('nav.audit'),\n settings: t('nav.settings'),\n apiFeatures: t('nav.apiFeatures'),\n media: t('nav.media'),\n catalog: t('nav.catalog'),\n runtimes: t('nav.runtimes'),\n usage: t('nav.usage'),\n ddos: t('nav.ddos'),\n queue: t('nav.queue'),\n pm2: t('nav.pm2'),\n system: t('nav.system'),\n support: t('nav.support'),\n };\n return map[state.page] || t('brand');\n}\n\nfunction closeNav() {\n document.body.classList.remove('nav-open');\n}\n\nfunction openNav() {\n document.body.classList.add('nav-open');\n}\n\nfunction shell(content) {\n return `\n <div class=\"app-shell\">\n <header class=\"mobile-bar\">\n <button type=\"button\" class=\"icon-btn\" id=\"nav-open\" aria-label=\"${escapeHtml(t('shell.menu'))}\">☰</button>\n <div class=\"mobile-title\">${escapeHtml(pageTitle())}</div>\n ${langSwitchHtml()}\n <button type=\"button\" class=\"btn ghost sm\" id=\"btn-logout-mobile\">${escapeHtml(t('logout'))}</button>\n </header>\n <div class=\"layout\">\n <button type=\"button\" class=\"sidebar-backdrop\" id=\"nav-backdrop\" aria-label=\"${escapeHtml(t('shell.closeMenu'))}\"></button>\n <aside class=\"sidebar\" id=\"sidebar\">\n <div class=\"brand\">\n <img class=\"brand-logo\" src=\"/admin/assets/logo.svg\" alt=\"YSK\" width=\"40\" height=\"40\" />\n <div class=\"brand-text\">\n <strong>${escapeHtml(t('brand'))}</strong>\n <small>${escapeHtml(t('brandSub'))}</small>\n </div>\n </div>\n ${langSwitchHtml()}\n ${nav('dashboard', t('nav.dashboard'))}\n ${nav('chat', t('nav.chat'))}\n ${nav('chats', t('nav.chats'))}\n ${nav('keys', t('nav.keys'))}\n ${nav('documents', t('nav.documents'))}\n ${nav('media', t('nav.media'))}\n ${nav('catalog', t('nav.catalog'))}\n ${nav('runtimes', t('nav.runtimes') === 'nav.runtimes' ? 'Runtimes' : t('nav.runtimes'))}\n ${nav('audit', t('nav.audit'))}\n ${nav('settings', t('nav.settings'))}\n ${nav('apiFeatures', t('nav.apiFeatures'))}\n ${nav('usage', t('nav.usage'))}\n ${nav('ddos', t('nav.ddos'))}\n ${nav('queue', t('nav.queue'))}\n ${nav('pm2', t('nav.pm2'))}\n ${nav('system', t('nav.system'))}\n ${nav('support', t('nav.support'))}\n <div class=\"sidebar-foot\">\n <button class=\"btn secondary sm logout-btn\" id=\"btn-logout\">${escapeHtml(t('logout'))}</button>\n </div>\n </aside>\n <main class=\"main\">\n <div id=\"flash-error\" class=\"error-box\" ${state.error ? '' : 'hidden'}>${escapeHtml(state.error)}</div>\n ${content}\n </main>\n </div>\n ${poweredByFooter()}\n </div>\n ${state.modal || ''}\n `;\n}\n\nfunction nav(id, label) {\n return `<button type=\"button\" class=\"nav-btn ${state.page === id ? 'active' : ''}\" data-nav=\"${id}\">${escapeHtml(label)}</button>`;\n}\n\nfunction bindShell() {\n closeNav();\n document.querySelectorAll('[data-nav]').forEach((b) => {\n b.onclick = () => {\n closeNav();\n setPage(b.dataset.nav);\n };\n });\n const logoutHandler = () => logout(true);\n document.getElementById('btn-logout')?.addEventListener('click', logoutHandler);\n document.getElementById('btn-logout-mobile')?.addEventListener('click', logoutHandler);\n document.getElementById('nav-open')?.addEventListener('click', openNav);\n document.getElementById('nav-backdrop')?.addEventListener('click', closeNav);\n document.addEventListener(\n 'keydown',\n (e) => {\n if (e.key === 'Escape') closeNav();\n },\n { once: true },\n );\n document.querySelectorAll('[data-lang]').forEach((b) => {\n b.onclick = () => {\n setLocale(b.dataset.lang);\n render().catch(onErr);\n };\n });\n enhanceResponsiveTables(document);\n}\n\n/** Strip sort arrows / extra whitespace from a header cell. */\nfunction tableHeaderLabel(th) {\n if (!th) return '';\n const fromAttr = (th.getAttribute('data-label') || '').trim();\n if (fromAttr) return fromAttr;\n const btn = th.querySelector('.th-sort-btn');\n const raw = btn\n ? [...btn.childNodes]\n .filter((n) => n.nodeType === Node.TEXT_NODE)\n .map((n) => n.textContent || '')\n .join('')\n : th.textContent || '';\n return raw.replace(/[▲▼]/g, '').replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Map thead labels onto tbody cells so the mobile card-table can show a caption.\n * Safe to call after any tbody rewrite (queue poll, DDoS soft refresh).\n */\nfunction enhanceResponsiveTables(root) {\n const scope = root || document;\n scope.querySelectorAll('table.data-table').forEach((table) => {\n const labels = [...table.querySelectorAll('thead th')].map(tableHeaderLabel);\n table.querySelectorAll('tbody tr').forEach((tr) => {\n if (tr.classList.contains('empty-row')) return;\n [...tr.children].forEach((td, i) => {\n const kids = [...td.children];\n const isActions =\n td.classList.contains('row-actions') ||\n Boolean(td.querySelector(':scope > .row-actions')) ||\n (kids.length > 0 &&\n kids.every((el) => el.matches('button, .btn, .row-actions')));\n td.classList.toggle('is-actions', isActions);\n td.classList.toggle('is-primary', i === 0 && !isActions);\n if (isActions) {\n td.removeAttribute('data-label');\n return;\n }\n if (labels[i]) td.setAttribute('data-label', labels[i]);\n });\n });\n });\n}\n\nfunction onErr(e) {\n console.error(e);\n showError(e.message || String(e));\n}\n\nasync function ensureMe() {\n if (!state.key) return false;\n const data = await api('/me');\n state.me = data.data;\n return true;\n}\n\nasync function loadModels(refresh = false) {\n try {\n const res = await api(`/models${refresh ? '?refresh=1' : ''}`);\n state.models = res.data?.models || [];\n return res.data;\n } catch {\n state.models = [];\n return { models: [], source: 'fallback', defaultModel: '' };\n }\n}\n\nasync function loadKeys() {\n try {\n // Full list for selects / playground (unpaginated)\n const res = await api('/keys?all=1');\n state.keys = res.data || [];\n } catch {\n state.keys = [];\n }\n}\n\n/* ——— Shared list UI helpers ——— */\n\n/**\n * Secondary line under topbar (hints, totals). Never put totals in topbar right.\n * @param {string|string[]} parts plain text segments joined with ·\n */\nfunction pageMetaHtml(parts) {\n const list = (Array.isArray(parts) ? parts : [parts]).filter(Boolean);\n if (!list.length) return '';\n const body = list\n .map((p) => `<span>${typeof p === 'string' ? escapeHtml(p) : p}</span>`)\n .join('<span class=\"page-meta-sep\" aria-hidden=\"true\">·</span>');\n return `<div class=\"page-meta\" role=\"status\">${body}</div>`;\n}\n\nfunction filterPanelHtml({ title, hint, meta, searchHtml, gridHtml }) {\n return `\n <div class=\"panel data-filter-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(title)}</strong>\n ${hint ? `<span class=\"muted\">${escapeHtml(hint)}</span>` : ''}\n </div>\n ${meta ? `<span class=\"panel-h-meta muted\">${typeof meta === 'string' ? escapeHtml(meta) : meta}</span>` : ''}\n </div>\n <div class=\"data-filter\">\n ${searchHtml || ''}\n ${gridHtml ? `<div class=\"data-filter-grid\">${gridHtml}</div>` : ''}\n <div class=\"data-filter-actions\">\n <button type=\"button\" class=\"btn secondary sm\" data-filter-reset>${escapeHtml(t('common.reset'))}</button>\n <button type=\"button\" class=\"btn sm\" data-filter-apply>${escapeHtml(t('common.apply'))}</button>\n </div>\n </div>\n </div>`;\n}\n\nfunction dataTablePanelHtml({ headHtml, bodyHtml, colSpan, emptyText, pagerHtml: pager }) {\n const body =\n bodyHtml ||\n `<tr class=\"empty-row\"><td colspan=\"${colSpan || 6}\">\n <div class=\"data-empty\">\n <div class=\"data-empty-icon\">∅</div>\n <strong>${escapeHtml(emptyText || t('common.empty'))}</strong>\n </div>\n </td></tr>`;\n return `\n <div class=\"panel data-table-panel\">\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr>${headHtml}</tr></thead>\n <tbody>${body}</tbody>\n </table>\n </div>\n ${pager || ''}\n </div>`;\n}\n\n/** Append server-side sort query params (default time desc when omitted on API). */\nfunction appendSortParams(params, filterRef, sortByKey = 'sortBy', sortDirKey = 'sortDir') {\n const by = filterRef?.[sortByKey];\n const dir = filterRef?.[sortDirKey];\n if (by) params.set('sortBy', String(by));\n if (dir === 'asc' || dir === 'desc') params.set('sortDir', dir);\n return params;\n}\n\n/**\n * Sortable table header cell. Click cycles: defaultDesc field → asc → desc.\n * @param {{ field: string, label: string, filterRef: object, sortByKey?: string, sortDirKey?: string }} opts\n */\nfunction sortThHtml({\n field,\n label,\n filterRef,\n sortByKey = 'sortBy',\n sortDirKey = 'sortDir',\n}) {\n const active = filterRef?.[sortByKey] === field;\n const dir = active ? filterRef?.[sortDirKey] || 'desc' : '';\n const aria =\n active && dir === 'asc' ? 'ascending' : active && dir === 'desc' ? 'descending' : 'none';\n const indicator = active ? (dir === 'asc' ? ' ▲' : ' ▼') : '';\n return `<th class=\"th-sort${active ? ' is-sorted' : ''}\" data-label=\"${escapeHtml(label)}\" data-sort-field=\"${escapeHtml(field)}\" data-sort-by-key=\"${escapeHtml(sortByKey)}\" data-sort-dir-key=\"${escapeHtml(sortDirKey)}\" aria-sort=\"${aria}\" title=\"${escapeHtml(t('common.sortHint') || 'Sort')}\"><button type=\"button\" class=\"th-sort-btn\">${escapeHtml(label)}<span class=\"th-sort-ind\" aria-hidden=\"true\">${indicator}</span></button></th>`;\n}\n\n/** Bind click on [data-sort-field] headers; toggles sort on filterRef and reloads. */\nfunction bindSortHeaders(filterRef, reload) {\n document.querySelectorAll('th.th-sort[data-sort-field]').forEach((th) => {\n const btn = th.querySelector('.th-sort-btn') || th;\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n const field = th.getAttribute('data-sort-field');\n if (!field || !filterRef) return;\n const byKey = th.getAttribute('data-sort-by-key') || 'sortBy';\n const dirKey = th.getAttribute('data-sort-dir-key') || 'sortDir';\n if (filterRef[byKey] === field) {\n filterRef[dirKey] = filterRef[dirKey] === 'asc' ? 'desc' : 'asc';\n } else {\n filterRef[byKey] = field;\n filterRef[dirKey] = 'desc';\n }\n if ('offset' in filterRef) filterRef.offset = 0;\n if ('modelPage' in filterRef && byKey === 'modelSortBy') filterRef.modelPage = 0;\n if ('keyPage' in filterRef && byKey === 'sortBy') filterRef.keyPage = 0;\n if ('livePage' in filterRef && byKey === 'liveSortBy') filterRef.livePage = 0;\n if ('banPage' in filterRef && byKey === 'banSortBy') filterRef.banPage = 0;\n reload();\n });\n });\n}\n\nfunction pagerHtml({ total, limit, offset, idPrefix }) {\n const pages = Math.max(1, Math.ceil((total || 0) / limit) || 1);\n const page = Math.floor(offset / limit) + 1;\n const canPrev = offset > 0;\n const canNext = offset + limit < total;\n return `\n <div class=\"data-pager\" id=\"${idPrefix}-pager\">\n <div class=\"data-pager-meta\">\n <span>${escapeHtml(tf('common.pagerTotal', { n: total || 0 }))}</span>\n <span>${escapeHtml(tf('common.pagerPage', { n: page, total: pages }))}</span>\n <label class=\"muted\">${escapeHtml(t('common.perPage'))}\n <select id=\"${idPrefix}-limit\">\n ${[10, 20, 50, 100]\n .map(\n (n) =>\n `<option value=\"${n}\" ${limit === n ? 'selected' : ''}>${n}</option>`,\n )\n .join('')}\n </select>\n </label>\n </div>\n <div class=\"data-pager-actions\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"${idPrefix}-prev\" ${canPrev ? '' : 'disabled'}>${escapeHtml(t('common.prev'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"${idPrefix}-next\" ${canNext ? '' : 'disabled'}>${escapeHtml(t('common.next'))}</button>\n </div>\n </div>`;\n}\n\nfunction bindPager(idPrefix, filterRef, reload) {\n document.getElementById(`${idPrefix}-prev`)?.addEventListener('click', () => {\n filterRef.offset = Math.max(0, filterRef.offset - filterRef.limit);\n reload();\n });\n document.getElementById(`${idPrefix}-next`)?.addEventListener('click', () => {\n filterRef.offset = filterRef.offset + filterRef.limit;\n reload();\n });\n document.getElementById(`${idPrefix}-limit`)?.addEventListener('change', (e) => {\n filterRef.limit = Number(e.target.value) || 20;\n filterRef.offset = 0;\n reload();\n });\n}\n\nfunction closeAppModal() {\n document.querySelectorAll('#modal-back video, #modal-back audio').forEach((el) => {\n try {\n el.pause();\n } catch {\n /* ignore */\n }\n });\n revokeMediaPreviewUrl();\n document.getElementById('modal-back')?.remove();\n state.modal = null;\n}\n\nfunction openAppModal({ title, subtitle, bodyHtml, footerHtml, size = 'md' }) {\n closeAppModal();\n const html = `\n <div class=\"modal-back\" id=\"modal-back\">\n <div class=\"modal modal--${escapeHtml(size)}\" role=\"dialog\" aria-modal=\"true\">\n <div class=\"modal-h\">\n <div class=\"modal-title-block\">\n <strong>${escapeHtml(title || '')}</strong>\n ${subtitle ? `<div class=\"muted\">${subtitle}</div>` : ''}\n </div>\n <button type=\"button\" class=\"modal-x\" id=\"modal-close\" aria-label=\"${escapeHtml(t('common.cancel'))}\">×</button>\n </div>\n <div class=\"modal-b\">${bodyHtml || ''}</div>\n ${footerHtml ? `<div class=\"modal-f\">${footerHtml}</div>` : ''}\n </div>\n </div>`;\n document.getElementById('app').insertAdjacentHTML('beforeend', html);\n const close = () => closeAppModal();\n document.getElementById('modal-close').onclick = close;\n document.getElementById('modal-back').onclick = (e) => {\n if (e.target.id === 'modal-back') close();\n };\n const onEsc = (e) => {\n if (e.key === 'Escape') {\n close();\n document.removeEventListener('keydown', onEsc);\n }\n };\n document.addEventListener('keydown', onEsc);\n}\n\nasync function renderLogin() {\n const cmd = 'ysk-omni admin otp';\n document.getElementById('app').innerHTML = `\n <div class=\"login-wrap\">\n <div class=\"login-stage\">\n <div class=\"login-card\">\n <div class=\"login-brand\">\n <img src=\"/admin/assets/logo.svg\" alt=\"YSK\" width=\"48\" height=\"48\" />\n <h1 class=\"brand-title\">${escapeHtml(t('loginTitle'))}</h1>\n </div>\n ${langSwitchHtml()}\n <div id=\"flash-error\" class=\"error-box\" ${state.error ? '' : 'hidden'}>${escapeHtml(state.error)}</div>\n <label for=\"login-key\">${escapeHtml(t('loginOtpLabel'))}</label>\n <input id=\"login-key\" type=\"text\" inputmode=\"text\" autocomplete=\"one-time-code\" placeholder=\"ABCD-EFGH\" autofocus spellcheck=\"false\" />\n <button class=\"btn\" id=\"btn-login\">${escapeHtml(t('loginBtn'))}</button>\n </div>\n <p class=\"login-cmd-hint\">${escapeHtml(t('loginOtpHint'))}</p>\n <div class=\"login-cmd\">\n <code id=\"login-cmd-text\">${escapeHtml(cmd)}</code>\n <button type=\"button\" class=\"btn-copy\" id=\"btn-copy-cmd\">${escapeHtml(t('loginCopy'))}</button>\n </div>\n <p class=\"login-cmd-hint\">${escapeHtml(t('loginOtpExpiry'))}</p>\n </div>\n ${poweredByFooter()}\n </div>\n `;\n document.querySelectorAll('[data-lang]').forEach((b) => {\n b.onclick = () => {\n setLocale(b.dataset.lang);\n renderLogin().catch(onErr);\n };\n });\n document.getElementById('btn-copy-cmd').onclick = async () => {\n try {\n await navigator.clipboard.writeText(cmd);\n const btn = document.getElementById('btn-copy-cmd');\n btn.textContent = t('loginCopied');\n setTimeout(() => {\n btn.textContent = t('loginCopy');\n }, 1500);\n } catch {\n /* ignore */\n }\n };\n document.getElementById('btn-login').onclick = async () => {\n const code = document.getElementById('login-key').value.trim();\n if (!code) return showError(t('needOtp'));\n try {\n const res = await fetch('/admin/api/auth/login', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ code }),\n });\n const data = await res.json().catch(() => ({}));\n if (!res.ok) {\n throw new Error(\n data?.error?.message || data?.message || t('loginOtpFail'),\n );\n }\n const token = data?.data?.token;\n if (!token) throw new Error(t('loginOtpFail'));\n state.key = token;\n sessionStorage.setItem(KEY_STORAGE, token);\n await ensureMe();\n state.error = '';\n setPage('dashboard');\n } catch (e) {\n state.key = '';\n sessionStorage.removeItem(KEY_STORAGE);\n showError(e.message || t('loginOtpFail'));\n }\n };\n document.getElementById('login-key').onkeydown = (e) => {\n if (e.key === 'Enter') document.getElementById('btn-login').click();\n };\n}\n\nfunction dashKpiCard({ label, value, sub, tone, href, valueId, subId }) {\n const toneCls = tone ? ` dash-kpi--${tone}` : '';\n const valueAttr = valueId ? ` id=\"${escapeHtml(valueId)}\"` : '';\n const subAttr = subId ? ` id=\"${escapeHtml(subId)}\"` : '';\n const inner = `\n <div class=\"label\">${escapeHtml(label)}</div>\n <div class=\"value\"${valueAttr}>${value}</div>\n ${sub != null && sub !== '' ? `<div class=\"dash-kpi-sub muted\"${subAttr}>${sub}</div>` : ''}`;\n if (href) {\n return `<button type=\"button\" class=\"card dash-kpi${toneCls}\" data-nav=\"${escapeHtml(href)}\">${inner}</button>`;\n }\n return `<div class=\"card dash-kpi${toneCls}\">${inner}</div>`;\n}\n\nfunction dashStatusPill(ok, okText, badText) {\n return ok\n ? `<span class=\"badge success\">${escapeHtml(okText)}</span>`\n : `<span class=\"badge warn\">${escapeHtml(badText)}</span>`;\n}\n\n/**\n * Page-level master switch for the topbar (not a form checkbox).\n * @param {{ id: string, on: boolean, onLabel: string, offLabel: string, title?: string }} opts\n */\nfunction masterToggleBtnHtml({ id, on, onLabel, offLabel, title }) {\n return `<button type=\"button\"\n class=\"master-toggle ${on ? 'is-on' : 'is-off'}\"\n id=\"${escapeHtml(id)}\"\n aria-pressed=\"${on ? 'true' : 'false'}\"\n title=\"${escapeHtml(title || '')}\">\n <span class=\"master-toggle-track\" aria-hidden=\"true\"><span class=\"master-toggle-knob\"></span></span>\n <span class=\"master-toggle-label\">${escapeHtml(on ? onLabel : offLabel)}</span>\n </button>`;\n}\n\nfunction isMasterToggleOn(id) {\n const btn = document.getElementById(id);\n return btn ? btn.classList.contains('is-on') : false;\n}\n\nfunction setMasterToggle(id, on, onLabel, offLabel) {\n const btn = document.getElementById(id);\n if (!btn) return;\n btn.classList.toggle('is-on', Boolean(on));\n btn.classList.toggle('is-off', !on);\n btn.setAttribute('aria-pressed', on ? 'true' : 'false');\n const lab = btn.querySelector('.master-toggle-label');\n if (lab && onLabel != null && offLabel != null) {\n lab.textContent = on ? onLabel : offLabel;\n }\n}\n\nfunction featureOffBannerHtml(id, message) {\n return `<div class=\"feature-off-banner\" id=\"${escapeHtml(id)}\" hidden role=\"status\">\n <strong>${escapeHtml(t('common.featureOff'))}</strong>\n <span>${escapeHtml(message)}</span>\n </div>`;\n}\n\nfunction setFeatureOffBanner(id, off) {\n const el = document.getElementById(id);\n if (el) el.hidden = !off;\n}\n\nfunction setFeatureRootOff(rootId, off) {\n const root = document.getElementById(rootId);\n if (root) root.classList.toggle('is-feature-off', Boolean(off));\n}\n\nfunction proxySourceShort(src) {\n const map = {\n auto: t('ddos.proxySrcAuto'),\n cloudflare: t('ddos.proxySrcCf'),\n nginx: t('ddos.proxySrcNginx'),\n 'x-forwarded-for': t('ddos.proxySrcXff'),\n socket: t('ddos.proxySrcSocket'),\n };\n return map[src] || src || '—';\n}\n\nasync function renderDashboard() {\n const res = await api('/stats');\n const d = res.data || {};\n const tot = d.totals || {};\n const prot = d.protection || {};\n const rt = d.runtime || {};\n const conc = d.concurrency || {};\n const q = d.queue || null;\n const safety = d.safety || null;\n const models = d.models24h || [];\n const rate24 = tot.successRate24h ?? 0;\n const rateAll = tot.successRate ?? 0;\n const genAt = d.generatedAt ? fmtTime(d.generatedAt) : '—';\n\n let queueKpiValue = '—';\n let queueKpiSub = t('dash.kpiQueueSub');\n let queueTone = '';\n if (q) {\n if (!q.enabled) {\n queueKpiValue = t('dash.kpiQueueOff');\n queueTone = 'warn';\n } else if (q.paused) {\n queueKpiValue = t('dash.kpiQueuePaused');\n queueTone = 'warn';\n } else if (q.drainMode) {\n queueKpiValue = t('dash.kpiQueueDrain');\n queueTone = 'warn';\n } else {\n queueKpiValue = `${q.depth ?? 0}`;\n }\n const waitS =\n q.oldestQueuedAgeMs > 0\n ? ` · wait ${Math.round(q.oldestQueuedAgeMs / 1000)}s`\n : '';\n queueKpiSub = tf('dash.kpiQueueSubLive', {\n run: q.running ?? 0,\n max: q.globalConcurrency ?? '—',\n dead: q.dead ?? 0,\n wait: waitS,\n });\n if ((q.dead || 0) > 0 || (q.depth || 0) > 20) queueTone = queueTone || 'warn';\n }\n\n const safeOn = Boolean(safety?.globalSafeMode);\n const safeKpiValue = safety\n ? safeOn\n ? t('dash.kpiSafeOn')\n : t('dash.kpiSafeOff')\n : '—';\n const safeKpiSub = safety\n ? escapeHtml(\n tf('dash.kpiSafeSub', {\n tools: safety.safeToolsMode || '—',\n turns: safety.safeMaxTurns ?? '—',\n model: safety.defaultModel || '—',\n }),\n )\n : escapeHtml(t('dash.kpiSafeSubEmpty'));\n\n const bodyHtml = (d.recentChats || [])\n .map(\n (c) => `\n <tr>\n <td><button class=\"linkish cell-primary\" data-chat=\"${c.id}\">${escapeHtml(c.requestId)}</button>\n <div class=\"cell-sub\">${escapeHtml(c.apiKey?.name || '')}</div></td>\n <td>${escapeHtml(c.model)}</td>\n <td>${badgeStatus(c.status)}</td>\n <td>${badgeMode(c.policyMode || '-')}</td>\n <td>${fmtMs(c.durationMs)}</td>\n <td>${fmtTime(c.createdAt)}</td>\n </tr>`,\n )\n .join('');\n\n const recentTable = dataTablePanelHtml({\n headHtml: `\n <th>${escapeHtml(t('chats.request'))}</th>\n <th>${escapeHtml(t('chats.model'))}</th>\n <th>${escapeHtml(t('chats.status'))}</th>\n <th>${escapeHtml(t('chats.mode'))}</th>\n <th>${escapeHtml(t('chats.duration'))}</th>\n <th>${escapeHtml(t('chats.time'))}</th>`,\n bodyHtml,\n colSpan: 6,\n emptyText: t('dash.empty'),\n });\n\n const modelMax = Math.max(1, ...models.map((m) => m.requests || 0));\n const modelBars = models.length\n ? models\n .map((m) => {\n const pct = Math.round(((m.requests || 0) / modelMax) * 100);\n return `\n <div class=\"dash-bar-row\">\n <div class=\"dash-bar-label\" title=\"${escapeHtml(m.model)}\">${escapeHtml(m.model)}</div>\n <div class=\"dash-bar-track\"><span style=\"width:${pct}%\"></span></div>\n <div class=\"dash-bar-n\">${m.requests}</div>\n </div>`;\n })\n .join('')\n : `<div class=\"data-empty\" style=\"padding:20px\"><strong>${escapeHtml(t('dash.emptyModels'))}</strong></div>`;\n\n const ruleChip = (on, label) =>\n `<span class=\"dash-rule-chip ${on ? 'is-on' : 'is-off'}\">${escapeHtml(label)}</span>`;\n\n const queueDetailHtml = q\n ? `\n <div class=\"dash-stat-grid\">\n <div><div class=\"label\">${escapeHtml(t('dash.qQueued'))}</div><div class=\"value value-sm\">${q.queued ?? 0}</div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.qRunning'))}</div><div class=\"value value-sm\">${q.running ?? 0}<span class=\"dash-kpi-den\">/${q.globalConcurrency ?? '—'}</span></div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.qDead'))}</div><div class=\"value value-sm\">${q.dead ?? 0}</div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.qSucceeded'))}</div><div class=\"value value-sm\">${q.succeeded ?? 0}</div></div>\n </div>\n <div class=\"dash-prot-meta muted\">\n ${escapeHtml(t('dash.qWorker'))}: ${escapeHtml(q.workerId || '—')}\n · ${escapeHtml(t('dash.qWorkerActive'))}: ${q.workerActive ?? 0}\n ${\n q.oldestQueuedAgeMs > 0\n ? ` · ${escapeHtml(t('dash.qOldest'))}: ${Math.round(q.oldestQueuedAgeMs / 1000)}s`\n : ''\n }\n </div>`\n : `<div class=\"data-empty\" style=\"padding:12px 0\"><strong>${escapeHtml(t('dash.qUnavailable'))}</strong></div>`;\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"dash-hero\">\n <div class=\"dash-hero-text\">\n <h2>${escapeHtml(t('dash.title'))}</h2>\n <p class=\"muted\">${escapeHtml(t('dash.subtitle'))}</p>\n </div>\n <div class=\"dash-hero-meta\">\n <span class=\"muted\">${escapeHtml(t('dash.updated'))}: ${escapeHtml(genAt)}</span>\n <button type=\"button\" class=\"btn secondary sm\" id=\"dash-refresh\">${escapeHtml(t('dash.refresh'))}</button>\n </div>\n </div>\n\n <div class=\"dash-kpi-grid\">\n ${dashKpiCard({\n label: t('dash.kpi24h'),\n value: tot.chats24h ?? 0,\n sub: tf('dash.kpi24hSub', {\n ok: tot.success24h ?? 0,\n err: tot.error24h ?? 0,\n }),\n tone: 'primary',\n href: 'chats',\n })}\n ${dashKpiCard({\n label: t('dash.kpiSuccessRate'),\n value: `${rate24}%`,\n sub: tf('dash.kpiSuccessRateSub', { all: rateAll }),\n tone: rate24 >= 90 ? 'ok' : rate24 >= 70 ? 'warn' : 'danger',\n href: 'usage',\n })}\n ${dashKpiCard({\n label: t('dash.kpiErrors'),\n value: tot.error24h ?? 0,\n sub: tf('dash.kpiErrorsSub', { all: tot.errors ?? 0 }),\n tone: (tot.error24h || 0) > 0 ? 'warn' : 'ok',\n href: 'chats',\n })}\n ${dashKpiCard({\n label: t('dash.kpiQueue'),\n value: queueKpiValue,\n sub: queueKpiSub,\n tone: queueTone,\n href: 'queue',\n })}\n ${dashKpiCard({\n label: t('dash.kpiSafe'),\n value: safeKpiValue,\n sub: safeKpiSub,\n tone: safety ? (safeOn ? 'ok' : 'warn') : '',\n href: 'settings',\n })}\n ${dashKpiCard({\n label: t('dash.kpiKeys'),\n value: `${tot.activeKeys ?? 0}<span class=\"dash-kpi-den\">/${tot.totalKeys ?? 0}</span>`,\n sub: t('dash.kpiKeysSub'),\n href: 'keys',\n })}\n ${dashKpiCard({\n label: t('dash.kpiDocs'),\n value: tot.documents ?? 0,\n sub: t('dash.kpiDocsSub'),\n href: 'documents',\n })}\n ${dashKpiCard({\n label: t('dash.kpiMedia') || 'Media',\n value: tot.mediaAssets ?? 0,\n sub: tf('dash.kpiMediaSub', { n: tot.mediaAssets24h ?? 0 }),\n href: 'media',\n })}\n ${dashKpiCard({\n label: t('dash.kpiConv'),\n value: tot.conversations ?? 0,\n sub: tf('dash.kpiConvSub', { n: tot.conversations24h ?? 0 }),\n href: 'chat',\n })}\n ${dashKpiCard({\n label: t('dash.kpiSessions'),\n value: tot.adminSessions ?? rt.adminSessions ?? 0,\n sub: t('dash.kpiSessionsSub'),\n })}\n ${dashKpiCard({\n label: t('dash.kpiConcurrent'),\n value: `${conc.active ?? 0}<span class=\"dash-kpi-den\">/${conc.max ?? 0}</span>`,\n sub: t('dash.kpiConcurrentSub'),\n tone: (conc.active || 0) >= (conc.max || 1) ? 'warn' : '',\n })}\n </div>\n\n <div class=\"dash-layout\">\n <div class=\"dash-main\">\n <div class=\"panel dash-panel\">\n <div class=\"panel-h\">\n <strong>${escapeHtml(t('dash.recent'))}</strong>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"chats\">${escapeHtml(t('dash.viewAll'))}</button>\n </div>\n ${recentTable.replace('data-table-panel', 'data-table-panel dash-embed-table')}\n </div>\n\n <div class=\"panel dash-panel\">\n <div class=\"panel-h\">\n <strong>${escapeHtml(t('dash.queuePanel'))}</strong>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"queue\">${escapeHtml(t('dash.openQueue'))}</button>\n </div>\n <div class=\"panel-pad dash-prot\">\n <div class=\"dash-prot-row\">\n <span>${escapeHtml(t('dash.queueState'))}</span>\n ${\n !q\n ? `<span class=\"badge warn\">${escapeHtml(t('dash.kpiQueueOff'))}</span>`\n : !q.enabled\n ? `<span class=\"badge warn\">${escapeHtml(t('dash.kpiQueueOff'))}</span>`\n : q.paused\n ? `<span class=\"badge warn\">${escapeHtml(t('dash.kpiQueuePaused'))}</span>`\n : q.drainMode\n ? `<span class=\"badge warn\">${escapeHtml(t('dash.kpiQueueDrain'))}</span>`\n : `<span class=\"badge success\">${escapeHtml(t('dash.queueLive'))}</span>`\n }\n </div>\n ${queueDetailHtml}\n </div>\n </div>\n </div>\n\n <aside class=\"dash-side\">\n <div class=\"panel dash-panel\">\n <div class=\"panel-h\">\n <strong>${escapeHtml(t('dash.safety'))}</strong>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"settings\">${escapeHtml(t('dash.openSettings'))}</button>\n </div>\n <div class=\"panel-pad dash-prot\">\n <div class=\"dash-prot-row\">\n <span>${escapeHtml(t('dash.globalSafe'))}</span>\n ${dashStatusPill(safeOn, t('dash.on'), t('dash.off'))}\n </div>\n <div class=\"dash-stat-grid\">\n <div><div class=\"label\">${escapeHtml(t('dash.safeTools'))}</div><div class=\"value value-sm\">${escapeHtml(safety?.safeToolsMode || '—')}</div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.safeTurns'))}</div><div class=\"value value-sm\">${safety?.safeMaxTurns ?? '—'}</div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.safeTimeout'))}</div><div class=\"value value-sm\">${safety?.safeTimeoutMs != null ? Math.round(safety.safeTimeoutMs / 1000) + 's' : '—'}</div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.defaultModel'))}</div><div class=\"value value-sm\" style=\"font-size:0.95rem!important\">${escapeHtml(safety?.defaultModel || '—')}</div></div>\n </div>\n <div class=\"dash-prot-meta muted\">${escapeHtml(t('dash.safetyHint'))}</div>\n </div>\n </div>\n\n <div class=\"panel dash-panel\">\n <div class=\"panel-h\">\n <strong>${escapeHtml(t('dash.protection'))}</strong>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"ddos\">${escapeHtml(t('dash.openDdos'))}</button>\n </div>\n <div class=\"panel-pad dash-prot\">\n <div class=\"dash-prot-row\">\n <span>${escapeHtml(t('dash.autoBan'))}</span>\n ${dashStatusPill(\n Boolean(prot.autoBanEnabled),\n t('dash.on'),\n t('dash.off'),\n )}\n </div>\n <div class=\"dash-rule-row\">\n ${ruleChip(prot.autoAuthEnabled, t('dash.ruleAuth'))}\n ${ruleChip(prot.autoRateEnabled, t('dash.ruleRate'))}\n ${ruleChip(prot.autoConnEnabled, t('dash.ruleConn'))}\n ${ruleChip(prot.autoVelocityEnabled, t('dash.ruleVelocity'))}\n </div>\n <div class=\"dash-stat-grid\">\n <div><div class=\"label\">${escapeHtml(t('dash.bans'))}</div><div class=\"value value-sm\">${prot.bans ?? 0}</div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.blocked'))}</div><div class=\"value value-sm\">${prot.blockedHits ?? 0}</div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.rateHits'))}</div><div class=\"value value-sm\">${prot.rateLimitedHits ?? 0}</div></div>\n <div><div class=\"label\">${escapeHtml(t('dash.liveConn'))}</div><div class=\"value value-sm\">${prot.activeConnections ?? 0}</div></div>\n </div>\n <div class=\"dash-prot-meta muted\">\n ${escapeHtml(t('dash.proxy'))}: ${escapeHtml(proxySourceShort(prot.proxyIpSource))}\n · ${escapeHtml(t('dash.hops'))}: ${prot.proxyTrustHops ?? 0}\n · ${escapeHtml(t('dash.limits'))}: ${prot.rateLimitMax ?? '—'}/${prot.rateLimitIpMax ?? '—'}\n </div>\n </div>\n </div>\n\n <div class=\"panel dash-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('dash.models24h'))}</strong></div>\n <div class=\"panel-pad\">${modelBars}</div>\n </div>\n\n <div class=\"panel dash-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('dash.runtime'))}</strong></div>\n <div class=\"panel-pad dash-runtime\">\n <div class=\"dash-prot-row\">\n <span>${escapeHtml(t('dash.port'))}</span>\n <strong>${rt.port ?? '—'}<span class=\"muted\" style=\"font-weight:500\"> (${escapeHtml(t('dash.defaultPort'))} ${rt.defaultPort ?? 3850})</span></strong>\n </div>\n <div class=\"dash-prot-row\">\n <span>${escapeHtml(t('dash.env'))}</span>\n <strong>${escapeHtml(rt.env || '—')}</strong>\n </div>\n <div class=\"dash-prot-row\">\n <span>${escapeHtml(t('dash.authMode'))}</span>\n <strong>${escapeHtml(t('dash.authOtp'))}</strong>\n </div>\n <div class=\"dash-prot-row\">\n <span>${escapeHtml(t('dash.encryption'))}</span>\n ${dashStatusPill(\n Boolean(rt.encryptionReady),\n t('dash.ready'),\n t('dash.notReady'),\n )}\n </div>\n <div class=\"dash-quick\">\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"chat\">${escapeHtml(t('nav.chat'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"queue\">${escapeHtml(t('dash.openQueue'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"settings\">${escapeHtml(t('nav.settings'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"usage\">${escapeHtml(t('nav.usage'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"pm2\">${escapeHtml(t('nav.pm2'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"system\">${escapeHtml(t('nav.system'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"audit\">${escapeHtml(t('nav.audit'))}</button>\n </div>\n </div>\n </div>\n </aside>\n </div>\n `);\n bindShell();\n document.getElementById('dash-refresh')?.addEventListener('click', () =>\n renderDashboard().catch(onErr),\n );\n document.querySelectorAll('[data-nav]').forEach((b) => {\n b.onclick = () => {\n const page = b.dataset.nav;\n if (page) setPage(page);\n };\n });\n document.querySelectorAll('[data-chat]').forEach((b) => {\n b.onclick = () => openChat(b.dataset.chat);\n });\n}\n\nfunction attachChips(docs) {\n if (!docs?.length) return `<span class=\"muted\">—</span>`;\n return docs\n .map((d) => {\n const img = isImageMime(d.mimeType);\n return `<span class=\"chip ${img ? 'img' : ''}\" title=\"${escapeHtml(d.mimeType)}\">${escapeHtml(d.originalName || t('chats.file'))}</span>`;\n })\n .join(' ');\n}\n\n/**\n * Split stored prompt (from messagesToPrompt) into system vs body.\n * Multi-turn format: \"role: content\" blocks joined by \\\\n\n */\nfunction parseStoredPrompt(prompt) {\n const raw = String(prompt || '');\n if (!raw.trim()) {\n return { system: '', body: '', hasRoles: false };\n }\n // Single-turn stores raw content without \"role: \" prefix\n if (!/^(system|user|assistant|tool): /m.test(raw)) {\n return { system: '', body: raw, hasRoles: false };\n }\n const re = /(^|\\n)(system|user|assistant|tool): /g;\n const matches = [];\n let m;\n while ((m = re.exec(raw)) !== null) {\n matches.push({\n role: m[2],\n contentStart: m.index + m[0].length,\n // content ends at next match index (join separator is \\n before next role)\n index: m.index,\n });\n }\n if (!matches.length) {\n return { system: '', body: raw, hasRoles: false };\n }\n const blocks = matches.map((hit, i) => {\n const end = i + 1 < matches.length ? matches[i + 1].index : raw.length;\n return {\n role: hit.role,\n content: raw.slice(hit.contentStart, end),\n };\n });\n const systemParts = blocks.filter((b) => b.role === 'system').map((b) => b.content);\n const bodyParts = blocks\n .filter((b) => b.role !== 'system')\n .map((b) => `${b.role}: ${b.content}`);\n return {\n system: systemParts.join('\\n\\n').trim(),\n body: bodyParts.length ? bodyParts.join('\\n') : raw,\n hasRoles: true,\n blocks,\n };\n}\n\nasync function renderChats() {\n await Promise.all([loadModels(), loadKeys()]);\n const f = state.chatFilter;\n const q = new URLSearchParams();\n q.set('limit', String(f.limit));\n q.set('offset', String(f.offset));\n if (f.status) q.set('status', f.status);\n if (f.model) q.set('model', f.model);\n if (f.apiKeyId) q.set('apiKeyId', f.apiKeyId);\n if (f.q) q.set('q', f.q);\n if (f.from) q.set('from', new Date(f.from).toISOString());\n if (f.to) {\n const end = new Date(f.to);\n end.setHours(23, 59, 59, 999);\n q.set('to', end.toISOString());\n }\n if (f.policyMode) q.set('policyMode', f.policyMode);\n if (f.hasDocuments !== '') q.set('hasDocuments', f.hasDocuments);\n appendSortParams(q, f);\n\n const data = await api(`/chats?${q}`);\n const total = data.total || 0;\n\n const modelOpts = [\n `<option value=\"\">${escapeHtml(t('chats.allModels'))}</option>`,\n ...state.models.map(\n (m) =>\n `<option value=\"${escapeHtml(m)}\" ${f.model === m ? 'selected' : ''}>${escapeHtml(m)}</option>`,\n ),\n ].join('');\n\n const keyOpts = [\n `<option value=\"\">${escapeHtml(t('chats.allKeys'))}</option>`,\n ...state.keys.map(\n (k) =>\n `<option value=\"${k.id}\" ${f.apiKeyId === k.id ? 'selected' : ''}>${escapeHtml(k.name)} (${escapeHtml(k.keyPrefix)})</option>`,\n ),\n ].join('');\n\n const bodyHtml = (data.items || [])\n .map((c) => {\n const parsed = parseStoredPrompt(c.promptPreview || '');\n const hasSys = Boolean(parsed.system);\n const previewBody = hasSys\n ? parsed.body.slice(0, 160)\n : c.promptPreview || '';\n return `\n <tr>\n <td><button class=\"linkish cell-primary\" data-chat=\"${c.id}\">${escapeHtml(c.requestId)}</button></td>\n <td><div class=\"cell-primary\">${escapeHtml(c.apiKey?.name || '')}</div><div class=\"cell-sub\">${escapeHtml(c.apiKey?.keyPrefix || '')}</div></td>\n <td>${escapeHtml(c.model)}</td>\n <td>${badgeStatus(c.status)} ${badgeMode(c.policyMode || '-')}</td>\n <td>${attachChips(c.documents)} ${c.documentCount ? `<span class=\"muted\">×${c.documentCount}</span>` : ''}</td>\n <td class=\"chats-preview-cell\">\n ${hasSys ? `<span class=\"chip sys-chip\" title=\"${escapeHtml(parsed.system.slice(0, 400))}\">${escapeHtml(t('chats.hasSystem'))}</span>` : ''}\n <div class=\"muted preview-text\">${escapeHtml(previewBody)}</div>\n </td>\n <td class=\"chats-preview-cell\"><div class=\"muted preview-text\">${escapeHtml(c.contentPreview)}</div></td>\n <td>${fmtTime(c.createdAt)}</td>\n <td class=\"muted\">${c.durationMs != null ? fmtMs(c.durationMs) : '—'}</td>\n </tr>`;\n })\n .join('');\n\n const filter = filterPanelHtml({\n title: t('chats.filterTitle') || t('common.filterTitle'),\n hint: t('chats.filterHint') || t('common.filterHint'),\n meta: tf('common.pagerTotal', { n: total }),\n searchHtml: `\n <div class=\"data-filter-search\">\n <label for=\"f-q\">${escapeHtml(t('chats.search'))}</label>\n <input type=\"search\" id=\"f-q\" value=\"${escapeHtml(f.q)}\" placeholder=\"${escapeHtml(t('chats.searchPh'))}\" />\n </div>`,\n gridHtml: `\n <label>${escapeHtml(t('chats.status'))}\n <select id=\"f-status\">\n <option value=\"\">${escapeHtml(t('chats.allStatus'))}</option>\n ${['success', 'error', 'timeout', 'pending']\n .map(\n (s) =>\n `<option value=\"${s}\" ${f.status === s ? 'selected' : ''}>${escapeHtml(t(`status.${s}`))}</option>`,\n )\n .join('')}\n </select>\n </label>\n <label>${escapeHtml(t('chats.model'))}\n <select id=\"f-model\">${modelOpts}</select>\n </label>\n <label>${escapeHtml(t('chats.apiKey'))}\n <select id=\"f-key\">${keyOpts}</select>\n </label>\n <label>${escapeHtml(t('chats.mode'))}\n <select id=\"f-mode\">\n <option value=\"\">${escapeHtml(t('chats.allModes'))}</option>\n <option value=\"safe\" ${f.policyMode === 'safe' ? 'selected' : ''}>${escapeHtml(t('keys.modeSafeBadge'))}</option>\n <option value=\"agent\" ${f.policyMode === 'agent' ? 'selected' : ''}>${escapeHtml(t('keys.modeAgentBadge'))}</option>\n </select>\n </label>\n <label>${escapeHtml(t('chats.from'))}\n <input type=\"date\" id=\"f-from\" value=\"${escapeHtml(f.from)}\" />\n </label>\n <label>${escapeHtml(t('chats.to'))}\n <input type=\"date\" id=\"f-to\" value=\"${escapeHtml(f.to)}\" />\n </label>\n <label class=\"data-filter-check\">\n <input type=\"checkbox\" id=\"f-docs\" ${f.hasDocuments === 'true' ? 'checked' : ''} />\n <span>${escapeHtml(t('chats.hasDocs'))}</span>\n </label>`,\n });\n\n const table = dataTablePanelHtml({\n headHtml: `\n <th>${escapeHtml(t('chats.request'))}</th>\n <th>${escapeHtml(t('chats.apiKey'))}</th>\n ${sortThHtml({ field: 'model', label: t('chats.model'), filterRef: f })}\n ${sortThHtml({ field: 'status', label: t('chats.status'), filterRef: f })}\n <th>${escapeHtml(t('chats.attachments'))}</th>\n <th>${escapeHtml(t('chats.prompt'))}</th>\n <th>${escapeHtml(t('chats.response'))}</th>\n ${sortThHtml({ field: 'createdAt', label: t('chats.time'), filterRef: f })}\n ${sortThHtml({ field: 'durationMs', label: t('ddos.duration'), filterRef: f })}`,\n bodyHtml,\n colSpan: 9,\n emptyText: t('common.empty'),\n pagerHtml: pagerHtml({\n total,\n limit: f.limit,\n offset: f.offset,\n idPrefix: 'chats',\n }),\n });\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('chats.title'))}</h2>\n </div>\n ${pageMetaHtml([t('chats.decrypt')])}\n ${filter}\n ${table}\n `);\n bindShell();\n bindPager('chats', state.chatFilter, () => renderChats().catch(onErr));\n bindSortHeaders(state.chatFilter, () => renderChats().catch(onErr));\n\n const applyFilter = () => {\n state.chatFilter.q = document.getElementById('f-q').value.trim();\n state.chatFilter.status = document.getElementById('f-status').value;\n state.chatFilter.model = document.getElementById('f-model').value;\n state.chatFilter.apiKeyId = document.getElementById('f-key').value;\n state.chatFilter.policyMode = document.getElementById('f-mode').value;\n state.chatFilter.from = document.getElementById('f-from').value;\n state.chatFilter.to = document.getElementById('f-to').value;\n state.chatFilter.hasDocuments = document.getElementById('f-docs').checked\n ? 'true'\n : '';\n state.chatFilter.offset = 0;\n renderChats().catch(onErr);\n };\n\n document.querySelector('[data-filter-apply]').onclick = applyFilter;\n document.getElementById('f-q').onkeydown = (e) => {\n if (e.key === 'Enter') applyFilter();\n };\n document.querySelector('[data-filter-reset]').onclick = () => {\n state.chatFilter = {\n q: '',\n status: '',\n model: '',\n apiKeyId: '',\n from: '',\n to: '',\n policyMode: '',\n hasDocuments: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n limit: 50,\n offset: 0,\n };\n renderChats().catch(onErr);\n };\n document.querySelectorAll('[data-chat]').forEach((b) => {\n b.onclick = () => openChat(b.dataset.chat);\n });\n}\n\nasync function openChat(id) {\n const { data } = await api(`/chats/${id}`);\n const r = data.response || {};\n const docs = data.documents || [];\n\n let attachHtml = `<p class=\"muted\">${escapeHtml(t('chats.noAttach'))}</p>`;\n if (docs.length) {\n const parts = [];\n for (const d of docs) {\n let preview = '';\n if (isImageMime(d.mimeType)) {\n try {\n const full = await api(`/documents/${d.id}`);\n const img = await resolveDocumentImageSrc(full.data || { id: d.id, isImage: true, mimeType: d.mimeType });\n if (img?.src) {\n preview = `<img class=\"preview\" src=\"${img.src}\" alt=\"${escapeHtml(d.originalName)}\" />`;\n }\n } catch {\n preview = `<span class=\"muted\">${escapeHtml(t('chats.previewFailed'))}</span>`;\n }\n }\n parts.push(`\n <div class=\"attach-item\">\n <div style=\"flex:1;min-width:0\">\n <strong>${escapeHtml(d.originalName)}</strong>\n <div class=\"muted\">${escapeHtml(d.mimeType)} · ${fmtBytes(d.sizeBytes)}</div>\n ${preview}\n </div>\n <button class=\"btn secondary sm\" data-open-doc=\"${d.id}\">${escapeHtml(t('chats.openFile'))}</button>\n </div>`);\n }\n attachHtml = `<div class=\"attach-list\">${parts.join('')}</div>`;\n }\n\n const parsed = parseStoredPrompt(data.prompt || '');\n const systemHtml = parsed.system\n ? `<div class=\"block block-system\">\n <div class=\"block-head\">\n <h4>${escapeHtml(t('chats.systemPrompt'))}</h4>\n <button class=\"btn secondary sm\" data-copy=\"system\">${escapeHtml(t('chats.copySystem'))}</button>\n </div>\n <p class=\"hint\">${escapeHtml(t('chats.systemHint'))}</p>\n <div class=\"pre pre-system\">${escapeHtml(parsed.system)}</div>\n </div>`\n : `<div class=\"block block-system muted-block\">\n <h4>${escapeHtml(t('chats.systemPrompt'))}</h4>\n <p class=\"muted\">${escapeHtml(t('chats.noSystem'))}</p>\n </div>`;\n\n const bodyHtml = `\n <div class=\"grid modal-meta-grid\">\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('chats.model'))}</div><div class=\"value value-sm\">${escapeHtml(data.model)}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('chats.duration'))}</div><div class=\"value value-sm\">${fmtMs(data.durationMs)}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('chats.apiKey'))}</div><div class=\"value value-sm\">${escapeHtml(data.apiKey?.name || '')}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('chats.stream'))}</div><div class=\"value value-sm\">${data.stream ? t('common.yes') : t('common.no')}</div></div>\n </div>\n ${data.errorMessage ? `<div class=\"error-box\">${escapeHtml(data.errorMessage)}</div>` : ''}\n ${systemHtml}\n <div class=\"block\">\n <h4>${escapeHtml(t('chats.attachments'))}</h4>\n ${attachHtml}\n </div>\n <div class=\"block\">\n <div class=\"block-head\">\n <h4>${escapeHtml(t('chats.userPrompt'))}</h4>\n <button class=\"btn secondary sm\" data-copy=\"prompt\">${escapeHtml(t('chats.copyPrompt'))}</button>\n </div>\n <div class=\"pre\">${escapeHtml(parsed.body || data.prompt || t('chats.none'))}</div>\n </div>\n <div class=\"block\">\n <h4>${escapeHtml(t('chats.reasoning'))}</h4>\n <div class=\"pre\">${escapeHtml(r.reasoning_content || t('chats.none'))}</div>\n </div>\n <div class=\"block\">\n <div class=\"block-head\">\n <h4>${escapeHtml(t('chats.content'))}</h4>\n <button class=\"btn secondary sm\" data-copy=\"content\">${escapeHtml(t('chats.copyContent'))}</button>\n </div>\n <div class=\"pre\">${escapeHtml(r.content || t('chats.none'))}</div>\n </div>\n <div class=\"block\">\n <div class=\"block-head\">\n <h4>${escapeHtml(t('chats.rawPrompt'))}</h4>\n <button class=\"btn secondary sm\" data-copy=\"raw-prompt\">${escapeHtml(t('chats.copyRawPrompt'))}</button>\n </div>\n <div class=\"pre\">${escapeHtml(data.prompt || t('chats.none'))}</div>\n </div>\n <div class=\"block\">\n <h4>${escapeHtml(t('chats.raw'))}</h4>\n <div class=\"pre\">${escapeHtml(r.raw || '')}</div>\n </div>\n <div class=\"modal-meta-foot muted\">${escapeHtml(t('common.ipLabel'))}: ${escapeHtml(data.ip || '—')} · ${escapeHtml(t('common.uaLabel'))}: ${escapeHtml(data.userAgent || '—')} · ${fmtTime(data.createdAt)}</div>`;\n\n openAppModal({\n title: t('chats.detail'),\n subtitle: `${escapeHtml(data.requestId)} · ${badgeStatus(data.status)} ${badgeMode(data.policyMode || '-')}`,\n bodyHtml,\n size: 'xl',\n footerHtml: `<button type=\"button\" class=\"btn secondary sm\" id=\"modal-ok\">${escapeHtml(t('chats.close'))}</button>`,\n });\n document.getElementById('modal-ok')?.addEventListener('click', () => closeAppModal());\n document.querySelector('[data-copy=\"system\"]')?.addEventListener('click', () => {\n navigator.clipboard.writeText(parsed.system || '');\n });\n document.querySelector('[data-copy=\"prompt\"]')?.addEventListener('click', () => {\n navigator.clipboard.writeText(parsed.body || data.prompt || '');\n });\n document.querySelector('[data-copy=\"raw-prompt\"]')?.addEventListener('click', () => {\n navigator.clipboard.writeText(data.prompt || '');\n });\n document.querySelector('[data-copy=\"content\"]')?.addEventListener('click', () => {\n navigator.clipboard.writeText(r.content || '');\n });\n document.querySelectorAll('[data-open-doc]').forEach((b) => {\n b.onclick = () => openDocument(b.dataset.openDoc);\n });\n}\n\nasync function renderKeys() {\n const f = state.keyFilter;\n let usageMap = {};\n try {\n const u = await api('/usage');\n for (const row of u.data?.perKey || []) {\n usageMap[row.apiKeyId] = row;\n }\n } catch {\n /* ignore */\n }\n const q = new URLSearchParams();\n q.set('limit', String(f.limit));\n q.set('offset', String(f.offset));\n if (f.q) q.set('q', f.q);\n if (f.role) q.set('role', f.role);\n if (f.mode) q.set('mode', f.mode);\n if (f.isActive !== '') q.set('isActive', f.isActive);\n appendSortParams(q, f);\n const res = await api(`/keys?${q}`);\n const data = res.data || [];\n const total = res.total ?? data.length;\n\n const bodyHtml = data\n .map((k) => {\n const u = usageMap[k.id];\n const reqs = u?.requests ?? '—';\n const util = u ? Math.round((u.utilization || 0) * 100) : 0;\n const wl = k.ipWhitelist || [];\n const wlLabel = wl.length\n ? tf('keys.ipCount', { n: wl.length })\n : t('keys.ipAll');\n const models = k.allowedModels || [];\n const modelsLabel = !models.length\n ? t('keys.modelsAll')\n : models.length <= 2\n ? models.join(', ')\n : tf('keys.modelsCount', { n: models.length });\n return `\n <tr>\n <td><div class=\"cell-primary\">${escapeHtml(k.name)}</div><div class=\"cell-sub\">${escapeHtml(k.keyPrefix)}…</div></td>\n <td>${badgeRole(k.role)}</td>\n <td>${badgeMode(k.mode)}</td>\n <td>${fmtPerMin(k.rateLimit)}</td>\n <td title=\"${escapeHtml(wl.join(', '))}\">${escapeHtml(wlLabel)}</td>\n <td title=\"${escapeHtml(models.join(', '))}\">${escapeHtml(modelsLabel)}</td>\n <td>\n <div>${reqs} <span class=\"muted\">(${escapeHtml(t('keys.usage24'))})</span></div>\n <div class=\"usage-bar ${util > 80 ? 'warn' : ''}\"><span style=\"width:${util}%\"></span></div>\n </td>\n <td>${k.isActive ? `<span class=\"badge success\">${escapeHtml(t('common.active'))}</span>` : `<span class=\"badge error\">${escapeHtml(t('common.revoked'))}</span>`}</td>\n <td>${fmtTime(k.createdAt)}</td>\n <td><div class=\"row-actions\">\n <button class=\"btn secondary sm\" data-edit=\"${k.id}\">${escapeHtml(t('keys.edit'))}</button>\n ${k.isActive ? `<button class=\"btn danger sm\" data-revoke=\"${k.id}\">${escapeHtml(t('keys.revoke'))}</button>` : ''}\n </div></td>\n </tr>`;\n })\n .join('');\n\n const filter = filterPanelHtml({\n title: t('common.filterTitle'),\n hint: t('common.filterHint'),\n meta: tf('common.pagerTotal', { n: total }),\n searchHtml: `\n <div class=\"data-filter-search\">\n <label for=\"kf-q\">${escapeHtml(t('common.search'))}</label>\n <input type=\"search\" id=\"kf-q\" value=\"${escapeHtml(f.q)}\" placeholder=\"${escapeHtml(t('keys.searchPh'))}\" />\n </div>`,\n gridHtml: `\n <label>${escapeHtml(t('keys.role'))}\n <select id=\"kf-role\">\n <option value=\"\">${escapeHtml(t('common.all'))}</option>\n <option value=\"client\" ${f.role === 'client' ? 'selected' : ''}>${escapeHtml(t('keys.roleClient'))}</option>\n <option value=\"admin\" ${f.role === 'admin' ? 'selected' : ''}>${escapeHtml(t('keys.roleAdmin'))}</option>\n </select>\n </label>\n <label>${escapeHtml(t('keys.mode'))}\n <select id=\"kf-mode\">\n <option value=\"\">${escapeHtml(t('common.all'))}</option>\n <option value=\"safe\" ${f.mode === 'safe' ? 'selected' : ''}>${escapeHtml(t('keys.modeSafeBadge'))}</option>\n <option value=\"agent\" ${f.mode === 'agent' ? 'selected' : ''}>${escapeHtml(t('keys.modeAgentBadge'))}</option>\n </select>\n </label>\n <label>${escapeHtml(t('keys.status'))}\n <select id=\"kf-active\">\n <option value=\"\">${escapeHtml(t('common.all'))}</option>\n <option value=\"true\" ${f.isActive === 'true' ? 'selected' : ''}>${escapeHtml(t('common.active'))}</option>\n <option value=\"false\" ${f.isActive === 'false' ? 'selected' : ''}>${escapeHtml(t('common.revoked'))}</option>\n </select>\n </label>`,\n });\n\n const table = dataTablePanelHtml({\n headHtml: `\n ${sortThHtml({ field: 'name', label: t('keys.name'), filterRef: f })}\n ${sortThHtml({ field: 'role', label: t('keys.role'), filterRef: f })}\n ${sortThHtml({ field: 'mode', label: t('keys.mode'), filterRef: f })}\n ${sortThHtml({ field: 'rateLimit', label: t('keys.rate'), filterRef: f })}\n <th>${escapeHtml(t('keys.ipWhitelistCol'))}</th>\n <th>${escapeHtml(t('keys.allowedModelsCol'))}</th>\n <th>${escapeHtml(t('keys.usage24'))}</th>\n ${sortThHtml({ field: 'isActive', label: t('keys.status'), filterRef: f })}\n ${sortThHtml({ field: 'createdAt', label: t('keys.created'), filterRef: f })}\n <th>${escapeHtml(t('common.actions'))}</th>`,\n bodyHtml,\n colSpan: 10,\n emptyText: t('keys.empty'),\n pagerHtml: pagerHtml({\n total,\n limit: f.limit,\n offset: f.offset,\n idPrefix: 'keys',\n }),\n });\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('keys.title'))}</h2>\n <div class=\"toolbar\">\n <button class=\"btn\" id=\"btn-new-key\">${escapeHtml(t('keys.new'))}</button>\n </div>\n </div>\n ${filter}\n ${table}\n `);\n bindShell();\n bindPager('keys', state.keyFilter, () => renderKeys().catch(onErr));\n bindSortHeaders(state.keyFilter, () => renderKeys().catch(onErr));\n document.querySelector('[data-filter-apply]').onclick = () => {\n state.keyFilter.q = document.getElementById('kf-q').value.trim();\n state.keyFilter.role = document.getElementById('kf-role').value;\n state.keyFilter.mode = document.getElementById('kf-mode').value;\n state.keyFilter.isActive = document.getElementById('kf-active').value;\n state.keyFilter.offset = 0;\n renderKeys().catch(onErr);\n };\n document.querySelector('[data-filter-reset]').onclick = () => {\n state.keyFilter = {\n q: '',\n role: '',\n mode: '',\n isActive: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n limit: 20,\n offset: 0,\n };\n renderKeys().catch(onErr);\n };\n document.getElementById('btn-new-key').onclick = () =>\n showKeyForm().catch(onErr);\n document.querySelectorAll('[data-edit]').forEach((b) => {\n const key = data.find((x) => x.id === b.dataset.edit);\n b.onclick = () => showKeyForm(key).catch(onErr);\n });\n document.querySelectorAll('[data-revoke]').forEach((b) => {\n b.onclick = async () => {\n if (\n !(await uiConfirm({\n message: t('keys.confirmRevoke'),\n variant: 'danger',\n confirmText: t('keys.revoke'),\n }))\n )\n return;\n await api(`/keys/${b.dataset.revoke}`, { method: 'DELETE' });\n renderKeys().catch(onErr);\n };\n });\n}\n\nasync function showKeyForm(existing) {\n const isEdit = Boolean(existing);\n const wlText = (existing?.ipWhitelist || []).join('\\n');\n const selectedModels = new Set(existing?.allowedModels || []);\n let preset = ['piper/lessac-high', 'echo'];\n try {\n const cat = await api('/catalog');\n const local = (cat.local || []).map((m) => m.id).filter(Boolean);\n const loaded = (cat.loaded || [])\n .map((e) => e.id || e)\n .filter(Boolean);\n preset = [...new Set([...loaded, ...local, ...preset])];\n } catch {\n /* keep builtin ids */\n }\n const extraIds = [...selectedModels].filter((id) => !preset.includes(id));\n const modelBoxes = preset\n .map(\n (id) => `\n <label class=\"key-model-item\">\n <input type=\"checkbox\" data-k-model value=\"${escapeHtml(id)}\" ${selectedModels.has(id) ? 'checked' : ''} />\n <span>${escapeHtml(id)}</span>\n </label>`,\n )\n .join('');\n openAppModal({\n title: isEdit ? t('keys.edit') : t('keys.new'),\n subtitle: isEdit\n ? `${escapeHtml(existing?.name || '')} · ${escapeHtml(existing?.keyPrefix || '')}…`\n : '',\n size: 'lg',\n bodyHtml: `\n <div class=\"form-grid\">\n <label class=\"full\">${escapeHtml(t('keys.name'))}<input id=\"k-name\" value=\"${escapeHtml(existing?.name || '')}\" /></label>\n <label>${escapeHtml(t('keys.role'))}\n <select id=\"k-role\">\n <option value=\"client\">${escapeHtml(t('keys.roleClient'))}</option>\n <option value=\"admin\">${escapeHtml(t('keys.roleAdmin'))}</option>\n </select>\n </label>\n <label>${escapeHtml(t('keys.mode'))}\n <select id=\"k-mode\">\n <option value=\"safe\">${escapeHtml(t('keys.modeSafe'))}</option>\n <option value=\"agent\">${escapeHtml(t('keys.modeAgent'))}</option>\n </select>\n </label>\n <label>${escapeHtml(t('keys.rate'))}<input id=\"k-rate\" type=\"number\" value=\"${existing?.rateLimit ?? 60}\" /></label>\n <label>${escapeHtml(t('keys.maxTurns'))}<input id=\"k-turns\" type=\"number\" value=\"${existing?.maxTurns ?? ''}\" /></label>\n <label>${escapeHtml(t('keys.timeoutMs'))}<input id=\"k-timeout\" type=\"number\" value=\"${existing?.timeoutMs ?? ''}\" /></label>\n <label class=\"full\">${escapeHtml(t('keys.ipWhitelist'))}\n <textarea id=\"k-ip\" rows=\"4\" placeholder=\"${escapeHtml(t('keys.ipPlaceholder'))}\">${escapeHtml(wlText)}</textarea>\n <span class=\"field-hint\">${escapeHtml(t('keys.ipWhitelistHint'))}</span>\n </label>\n <div class=\"full key-models-field\">\n <span>${escapeHtml(t('keys.allowedModels'))}</span>\n <div class=\"key-model-list\" id=\"k-models\">${modelBoxes}</div>\n <span class=\"field-hint\">${escapeHtml(t('keys.allowedModelsHint'))}</span>\n </div>\n <label class=\"full\">${escapeHtml(t('keys.modelsExtra'))}\n <textarea id=\"k-models-extra\" rows=\"3\" placeholder=\"${escapeHtml(t('keys.modelsPlaceholder'))}\">${escapeHtml(extraIds.join('\\n'))}</textarea>\n <span class=\"field-hint\">${escapeHtml(t('keys.modelsExtraHint'))}</span>\n </label>\n ${\n isEdit\n ? `<label class=\"full\">${escapeHtml(t('keys.status'))}\n <select id=\"k-active\"><option value=\"true\">${escapeHtml(t('common.active'))}</option><option value=\"false\">${escapeHtml(t('common.revoked'))}</option></select>\n </label>`\n : ''\n }\n </div>\n <pre id=\"k-created\" class=\"pre key-once-box\" hidden></pre>`,\n footerHtml: `\n <button type=\"button\" class=\"btn secondary sm\" id=\"k-cancel\">${escapeHtml(t('common.cancel'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"k-save\">${escapeHtml(t('common.save'))}</button>`,\n });\n document.getElementById('k-role').value = existing?.role || 'client';\n document.getElementById('k-mode').value = existing?.mode || 'safe';\n if (isEdit) document.getElementById('k-active').value = String(existing.isActive);\n document.getElementById('k-cancel').onclick = () => closeAppModal();\n document.getElementById('k-save').onclick = async () => {\n const ipWhitelist = document\n .getElementById('k-ip')\n .value.split(/[\\n,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n const checked = [\n ...document.querySelectorAll('[data-k-model]:checked'),\n ].map((el) => el.value);\n const extra = document\n .getElementById('k-models-extra')\n .value.split(/[\\n,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n const allowedModels = [...new Set([...checked, ...extra])];\n const body = {\n name: document.getElementById('k-name').value.trim(),\n role: document.getElementById('k-role').value,\n mode: document.getElementById('k-mode').value,\n rateLimit: Number(document.getElementById('k-rate').value || 60),\n maxTurns: document.getElementById('k-turns').value\n ? Number(document.getElementById('k-turns').value)\n : null,\n timeoutMs: document.getElementById('k-timeout').value\n ? Number(document.getElementById('k-timeout').value)\n : null,\n ipWhitelist,\n allowedModels,\n };\n try {\n if (isEdit) {\n body.isActive = document.getElementById('k-active').value === 'true';\n await api(`/keys/${existing.id}`, { method: 'PATCH', body: JSON.stringify(body) });\n closeAppModal();\n renderKeys().catch(onErr);\n } else {\n const res = await api('/keys', { method: 'POST', body: JSON.stringify(body) });\n const box = document.getElementById('k-created');\n if (box) {\n box.hidden = false;\n box.textContent = `${t('keys.keyOnce')}\\n${res.data?.key || JSON.stringify(res.data)}`;\n }\n const saveBtn = document.getElementById('k-save');\n if (saveBtn) {\n saveBtn.textContent = t('chats.close');\n saveBtn.onclick = () => {\n closeAppModal();\n renderKeys().catch(onErr);\n };\n }\n }\n } catch (e) {\n onErr(e);\n }\n };\n}\n\nfunction storageTypeLabel(type) {\n if (type === 'filesystem') return t('docs.storageFs');\n return t('docs.storageDb');\n}\n\nasync function downloadDocument(id, originalName) {\n try {\n const res = await fetch(`${API}/documents/${id}/download`, {\n headers: state.key ? { Authorization: `Bearer ${state.key}` } : {},\n });\n if (!res.ok) {\n const text = await res.text();\n let msg = text;\n try {\n const j = JSON.parse(text);\n msg = j.error?.message || text;\n } catch {\n /* */\n }\n throw new Error(msg || t('docs.downloadFail'));\n }\n const blob = await res.blob();\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = originalName || 'download';\n document.body.appendChild(a);\n a.click();\n a.remove();\n URL.revokeObjectURL(url);\n } catch (e) {\n showError(e.message || t('docs.downloadFail'));\n }\n}\n\nasync function renderDocuments() {\n await loadKeys();\n const f = state.docFilter;\n const params = new URLSearchParams({\n limit: String(f.limit),\n offset: String(f.offset),\n });\n if (f.q) params.set('q', f.q);\n if (f.apiKeyId) params.set('apiKeyId', f.apiKeyId);\n if (f.storageType) params.set('storageType', f.storageType);\n if (f.from) params.set('from', new Date(f.from).toISOString());\n if (f.to) {\n const end = new Date(f.to);\n end.setHours(23, 59, 59, 999);\n params.set('to', end.toISOString());\n }\n appendSortParams(params, f);\n const data = await api(`/documents?${params}`);\n const total = data.total ?? 0;\n const meta = data.meta || {};\n const storageHint = tf('docs.storageHint', {\n dir: meta.storageDir || '—',\n dbMax: fmtBytes(meta.documentDbMaxBytes),\n upMax: fmtBytes(meta.uploadMaxBytes),\n });\n\n const keyOpts = [\n `<option value=\"\">${escapeHtml(t('common.all'))}</option>`,\n ...state.keys.map(\n (k) =>\n `<option value=\"${k.id}\" ${f.apiKeyId === k.id ? 'selected' : ''}>${escapeHtml(k.name)}</option>`,\n ),\n ].join('');\n\n const bodyHtml = (data.data || [])\n .map(\n (d) => `\n <tr>\n <td><button class=\"linkish cell-primary\" data-doc=\"${d.id}\">${escapeHtml(d.originalName)}</button>\n ${isImageMime(d.mimeType) ? `<span class=\"chip img\">${escapeHtml(t('chats.img'))}</span>` : ''}</td>\n <td>${escapeHtml(d.apiKey?.name || '')}</td>\n <td>${escapeHtml(d.mimeType)}</td>\n <td>${fmtBytes(d.sizeBytes)}</td>\n <td>\n <span title=\"${escapeHtml(d.storagePath || '')}\">${escapeHtml(storageTypeLabel(d.storageType))}</span>\n ${d.storagePath ? `<div class=\"cell-sub\">${escapeHtml(d.storagePath)}</div>` : ''}\n </td>\n <td>${fmtTime(d.createdAt)}</td>\n <td><div class=\"row-actions\">\n <button class=\"btn secondary sm\" data-dl=\"${d.id}\" data-name=\"${escapeHtml(d.originalName)}\">${escapeHtml(t('docs.download'))}</button>\n <button class=\"btn danger sm\" data-del=\"${d.id}\">${escapeHtml(t('docs.delete'))}</button>\n </div></td>\n </tr>`,\n )\n .join('');\n\n const filter = filterPanelHtml({\n title: t('common.filterTitle'),\n hint: t('common.filterHint'),\n meta: tf('common.pagerTotal', { n: total }),\n searchHtml: `\n <div class=\"data-filter-search\">\n <label for=\"df-q\">${escapeHtml(t('common.search'))}</label>\n <input type=\"search\" id=\"df-q\" value=\"${escapeHtml(f.q)}\" placeholder=\"${escapeHtml(t('docs.searchPh'))}\" />\n </div>`,\n gridHtml: `\n <label>${escapeHtml(t('chats.apiKey'))}\n <select id=\"df-key\">${keyOpts}</select>\n </label>\n <label>${escapeHtml(t('docs.storage'))}\n <select id=\"df-storage\">\n <option value=\"\">${escapeHtml(t('common.all'))}</option>\n <option value=\"db\" ${f.storageType === 'db' ? 'selected' : ''}>${escapeHtml(t('docs.storageDb'))}</option>\n <option value=\"filesystem\" ${f.storageType === 'filesystem' ? 'selected' : ''}>${escapeHtml(t('docs.storageFs'))}</option>\n </select>\n </label>\n <label>${escapeHtml(t('chats.from'))}<input type=\"date\" id=\"df-from\" value=\"${escapeHtml(f.from)}\" /></label>\n <label>${escapeHtml(t('chats.to'))}<input type=\"date\" id=\"df-to\" value=\"${escapeHtml(f.to)}\" /></label>`,\n });\n\n const table = dataTablePanelHtml({\n headHtml: `\n ${sortThHtml({ field: 'originalName', label: t('docs.file'), filterRef: f })}\n <th>${escapeHtml(t('chats.apiKey'))}</th>\n ${sortThHtml({ field: 'mimeType', label: t('docs.mime'), filterRef: f })}\n ${sortThHtml({ field: 'sizeBytes', label: t('docs.size'), filterRef: f })}\n ${sortThHtml({ field: 'storageType', label: t('docs.storage'), filterRef: f })}\n ${sortThHtml({ field: 'createdAt', label: t('docs.time'), filterRef: f })}\n <th>${escapeHtml(t('common.actions'))}</th>`,\n bodyHtml,\n colSpan: 7,\n emptyText: t('docs.empty'),\n pagerHtml: pagerHtml({\n total,\n limit: f.limit,\n offset: f.offset,\n idPrefix: 'docs',\n }),\n });\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('docs.title'))}</h2>\n </div>\n ${pageMetaHtml([storageHint])}\n ${filter}\n ${table}\n `);\n bindShell();\n bindPager('docs', state.docFilter, () => renderDocuments().catch(onErr));\n bindSortHeaders(state.docFilter, () => renderDocuments().catch(onErr));\n document.querySelector('[data-filter-apply]').onclick = () => {\n state.docFilter.q = document.getElementById('df-q').value.trim();\n state.docFilter.apiKeyId = document.getElementById('df-key').value;\n state.docFilter.storageType = document.getElementById('df-storage').value;\n state.docFilter.from = document.getElementById('df-from').value;\n state.docFilter.to = document.getElementById('df-to').value;\n state.docFilter.offset = 0;\n renderDocuments().catch(onErr);\n };\n document.querySelector('[data-filter-reset]').onclick = () => {\n state.docFilter = {\n q: '',\n apiKeyId: '',\n storageType: '',\n from: '',\n to: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n limit: 20,\n offset: 0,\n };\n renderDocuments().catch(onErr);\n };\n document.querySelectorAll('[data-doc]').forEach((b) => {\n b.onclick = () => openDocument(b.dataset.doc);\n });\n document.querySelectorAll('[data-dl]').forEach((b) => {\n b.onclick = () =>\n downloadDocument(b.getAttribute('data-dl'), b.getAttribute('data-name') || 'file');\n });\n document.querySelectorAll('[data-del]').forEach((b) => {\n b.onclick = async () => {\n if (\n !(await uiConfirm({\n message: t('docs.confirmDel'),\n variant: 'danger',\n confirmText: t('docs.delete'),\n }))\n )\n return;\n await api(`/documents/${b.dataset.del}`, { method: 'DELETE' });\n renderDocuments().catch(onErr);\n };\n });\n}\n\n/** Fetch decrypted document bytes with admin session/key (for image preview). */\nasync function fetchDocumentBlobUrl(id) {\n const res = await fetch(`${API}/documents/${id}/download`, {\n headers: state.key ? { Authorization: `Bearer ${state.key}` } : {},\n });\n if (!res.ok) {\n const text = await res.text();\n let msg = text;\n try {\n msg = JSON.parse(text)?.error?.message || text;\n } catch {\n /* */\n }\n throw new Error(msg || t('docs.downloadFail'));\n }\n const blob = await res.blob();\n return URL.createObjectURL(blob);\n}\n\nasync function resolveDocumentImageSrc(doc) {\n if (doc?.imageDataUrl) return { src: doc.imageDataUrl, revoke: null };\n if (doc?.isImage || isImageMime(doc?.mimeType)) {\n const src = await fetchDocumentBlobUrl(doc.id);\n return { src, revoke: src };\n }\n return null;\n}\n\nasync function openDocument(id) {\n const { data: doc } = await api(`/documents/${id}`);\n let preview;\n let revokeUrl = null;\n try {\n const img = await resolveDocumentImageSrc(doc);\n if (img) {\n revokeUrl = img.revoke;\n preview = `<img class=\"preview doc-preview-img\" src=\"${img.src}\" alt=\"${escapeHtml(doc.originalName || '')}\" />`;\n } else if (doc.isBinary || doc.content == null) {\n preview = `<div class=\"data-empty\"><div class=\"data-empty-icon\">⧉</div><strong>${escapeHtml(t('docs.binaryPreview'))}</strong></div>`;\n } else {\n preview = `<div class=\"pre\" id=\"doc-content\">${escapeHtml(doc.content || t('chats.none'))}</div>`;\n }\n } catch {\n preview = `<div class=\"data-empty\"><div class=\"data-empty-icon\">⧉</div><strong>${escapeHtml(t('chats.previewFailed') || t('docs.binaryPreview'))}</strong></div>`;\n }\n const storageLine = `${storageTypeLabel(doc.storageType)}${\n doc.storagePath ? ` · ${doc.storagePath}` : ''\n }`;\n openAppModal({\n title: t('docs.detail'),\n subtitle: `${escapeHtml(doc.originalName)} · ${escapeHtml(doc.mimeType)} · ${fmtBytes(doc.sizeBytes)}<br/><span class=\"muted\">${escapeHtml(t('docs.storage'))}: ${escapeHtml(storageLine)}</span>`,\n size: 'lg',\n bodyHtml: `\n <div class=\"block\">\n <h4>${escapeHtml(t('docs.preview'))}</h4>\n ${preview}\n </div>`,\n footerHtml: `\n ${\n !doc.imageDataUrl &&\n !(doc.isImage || isImageMime(doc.mimeType)) &&\n doc.content &&\n !doc.isBinary\n ? `<button type=\"button\" class=\"btn secondary sm\" id=\"doc-copy\">${escapeHtml(t('docs.copy'))}</button>`\n : ''\n }\n <button type=\"button\" class=\"btn sm\" id=\"doc-download\">${escapeHtml(t('docs.download'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"doc-close\">${escapeHtml(t('chats.close'))}</button>`,\n });\n const closeAndRevoke = () => {\n if (revokeUrl) {\n try {\n URL.revokeObjectURL(revokeUrl);\n } catch {\n /* */\n }\n }\n closeAppModal();\n };\n document.getElementById('doc-close')?.addEventListener('click', closeAndRevoke);\n document.getElementById('doc-download').onclick = () =>\n downloadDocument(doc.id, doc.originalName);\n document.getElementById('doc-copy')?.addEventListener('click', async () => {\n const ok = await copyTextToClipboard(doc.content || '');\n if (ok) {\n const b = document.getElementById('doc-copy');\n if (b) b.textContent = t('chat.copied');\n }\n });\n}\n\nfunction auditActionLabel(action) {\n if (!action) return '-';\n // i18n keys use _ (t() splits on .)\n const key = `audit.actions.${String(action).replace(/\\./g, '_')}`;\n const label = t(key);\n return label === key ? action : label;\n}\n\nfunction auditResourceLabel(resource) {\n if (!resource) return '';\n const key = `audit.resources.${String(resource).replace(/\\./g, '_')}`;\n const label = t(key);\n return label === key ? resource : label;\n}\n\n/** Pretty-print meta JSON with light field name hints for zh users */\nfunction formatAuditMeta(metaJson) {\n if (!metaJson) return '';\n try {\n const obj = typeof metaJson === 'string' ? JSON.parse(metaJson) : metaJson;\n if (!obj || typeof obj !== 'object') return String(metaJson);\n return Object.entries(obj)\n .map(([k, v]) => {\n const field =\n {\n originalName: t('docs.file'),\n mimeType: t('docs.mime'),\n sizeBytes: t('docs.size'),\n storageType: t('audit.metaStorage'),\n asKeyId: t('audit.metaAsKey'),\n asKeyName: t('audit.metaAsKeyName'),\n model: t('chats.model'),\n stream: t('chats.stream'),\n }[k] || k;\n const val =\n typeof v === 'object' ? JSON.stringify(v) : String(v ?? '');\n return `${field}: ${val}`;\n })\n .join(' · ');\n } catch {\n return String(metaJson);\n }\n}\n\nasync function renderAudit() {\n await loadKeys();\n const f = state.auditFilter;\n const q = new URLSearchParams();\n q.set('limit', String(f.limit));\n q.set('offset', String(f.offset));\n if (f.q) q.set('q', f.q);\n if (f.action) q.set('action', f.action);\n if (f.apiKeyId) q.set('apiKeyId', f.apiKeyId);\n if (f.from) q.set('from', new Date(f.from).toISOString());\n if (f.to) {\n const end = new Date(f.to);\n end.setHours(23, 59, 59, 999);\n q.set('to', end.toISOString());\n }\n appendSortParams(q, f);\n const data = await api(`/audit-logs?${q}`);\n const total = data.total ?? 0;\n const actions = [\n '',\n 'chat.create',\n 'document.upload',\n 'document.delete',\n 'document.download',\n 'api_key.create',\n 'api_key.update',\n 'api_key.delete',\n 'settings.update',\n 'playground.chat',\n 'ip.ban',\n 'ip.unban',\n 'ddos.policy_update',\n 'pm2.switch',\n 'system.update',\n ];\n const keyOpts = [\n `<option value=\"\">${escapeHtml(t('common.all'))}</option>`,\n ...state.keys.map(\n (k) =>\n `<option value=\"${k.id}\" ${f.apiKeyId === k.id ? 'selected' : ''}>${escapeHtml(k.name)}</option>`,\n ),\n ].join('');\n const actionOpts = actions\n .map((a) => {\n if (!a)\n return `<option value=\"\">${escapeHtml(t('common.all'))}</option>`;\n return `<option value=\"${escapeHtml(a)}\" ${f.action === a ? 'selected' : ''}>${escapeHtml(auditActionLabel(a))}</option>`;\n })\n .join('');\n\n const bodyHtml = (data.data || [])\n .map(\n (a) => `\n <tr>\n <td>${fmtTime(a.createdAt)}</td>\n <td title=\"${escapeHtml(a.action || '')}\"><span class=\"cell-primary\">${escapeHtml(auditActionLabel(a.action))}</span></td>\n <td>\n <div>${escapeHtml(auditResourceLabel(a.resource))}</div>\n ${a.resourceId ? `<div class=\"cell-sub audit-id\" title=\"${escapeHtml(a.resourceId)}\">${escapeHtml(a.resourceId)}</div>` : ''}\n </td>\n <td>${escapeHtml(a.apiKey?.name || '-')}</td>\n <td class=\"muted audit-meta\">${escapeHtml(formatAuditMeta(a.metaJson))}</td>\n </tr>`,\n )\n .join('');\n\n const filter = filterPanelHtml({\n title: t('common.filterTitle'),\n hint: t('common.filterHint'),\n meta: tf('common.pagerTotal', { n: total }),\n searchHtml: `\n <div class=\"data-filter-search\">\n <label for=\"af-q\">${escapeHtml(t('common.search'))}</label>\n <input type=\"search\" id=\"af-q\" value=\"${escapeHtml(f.q)}\" placeholder=\"${escapeHtml(t('audit.searchPh'))}\" />\n </div>`,\n gridHtml: `\n <label>${escapeHtml(t('audit.action'))}\n <select id=\"af-action\">${actionOpts}</select>\n </label>\n <label>${escapeHtml(t('audit.key'))}\n <select id=\"af-key\">${keyOpts}</select>\n </label>\n <label>${escapeHtml(t('chats.from'))}<input type=\"date\" id=\"af-from\" value=\"${escapeHtml(f.from)}\" /></label>\n <label>${escapeHtml(t('chats.to'))}<input type=\"date\" id=\"af-to\" value=\"${escapeHtml(f.to)}\" /></label>`,\n });\n\n const table = dataTablePanelHtml({\n headHtml: `\n ${sortThHtml({ field: 'createdAt', label: t('audit.time'), filterRef: f })}\n ${sortThHtml({ field: 'action', label: t('audit.action'), filterRef: f })}\n ${sortThHtml({ field: 'resource', label: t('audit.resource'), filterRef: f })}\n <th>${escapeHtml(t('audit.key'))}</th>\n <th>${escapeHtml(t('audit.meta'))}</th>`,\n bodyHtml,\n colSpan: 5,\n emptyText: t('audit.empty'),\n pagerHtml: pagerHtml({\n total,\n limit: f.limit,\n offset: f.offset,\n idPrefix: 'audit',\n }),\n });\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('audit.title'))}</h2>\n </div>\n ${filter}\n ${table}\n `);\n bindShell();\n bindPager('audit', state.auditFilter, () => renderAudit().catch(onErr));\n bindSortHeaders(state.auditFilter, () => renderAudit().catch(onErr));\n document.querySelector('[data-filter-apply]').onclick = () => {\n state.auditFilter.q = document.getElementById('af-q').value.trim();\n state.auditFilter.action = document.getElementById('af-action').value;\n state.auditFilter.apiKeyId = document.getElementById('af-key').value;\n state.auditFilter.from = document.getElementById('af-from').value;\n state.auditFilter.to = document.getElementById('af-to').value;\n state.auditFilter.offset = 0;\n renderAudit().catch(onErr);\n };\n document.querySelector('[data-filter-reset]').onclick = () => {\n state.auditFilter = {\n q: '',\n action: '',\n apiKeyId: '',\n from: '',\n to: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n limit: 50,\n offset: 0,\n };\n renderAudit().catch(onErr);\n };\n}\n\n/** Presets for Safety settings guide (apply confirms + persists immediately). */\nfunction settingsPresets() {\n return [\n {\n id: 'local',\n titleKey: 'settings.scLocalTitle',\n descKey: 'settings.scLocalDesc',\n detailKey: 'settings.scLocalDetail',\n // Off global — safe fields unused but set sensible defaults if re-enabled\n values: {\n globalSafeMode: false,\n safeToolsMode: 'none',\n safeMaxTurns: 16,\n safeTimeoutMs: 180000,\n },\n },\n {\n id: 'prod',\n titleKey: 'settings.scProdTitle',\n descKey: 'settings.scProdDesc',\n detailKey: 'settings.scProdDetail',\n values: {\n globalSafeMode: true,\n safeToolsMode: 'none',\n safeMaxTurns: 10,\n safeTimeoutMs: 120000,\n },\n },\n {\n id: 'code',\n titleKey: 'settings.scCodeTitle',\n descKey: 'settings.scCodeDesc',\n detailKey: 'settings.scCodeDetail',\n values: {\n globalSafeMode: false,\n safeToolsMode: 'none',\n safeMaxTurns: 20,\n safeTimeoutMs: 300000,\n },\n },\n {\n id: 'read',\n titleKey: 'settings.scReadTitle',\n descKey: 'settings.scReadDesc',\n detailKey: 'settings.scReadDetail',\n values: {\n globalSafeMode: true,\n safeToolsMode: 'readonly',\n safeMaxTurns: 12,\n safeTimeoutMs: 150000,\n },\n },\n {\n id: 'chat',\n titleKey: 'settings.scChatTitle',\n descKey: 'settings.scChatDesc',\n detailKey: 'settings.scChatDetail',\n values: {\n globalSafeMode: true,\n safeToolsMode: 'none',\n safeMaxTurns: 5,\n safeTimeoutMs: 60000,\n },\n },\n {\n id: 'long',\n titleKey: 'settings.scLongTitle',\n descKey: 'settings.scLongDesc',\n detailKey: 'settings.scLongDetail',\n values: {\n globalSafeMode: true,\n safeToolsMode: 'none',\n safeMaxTurns: 40,\n safeTimeoutMs: 600000,\n },\n },\n ];\n}\n\nfunction readSettingsFormValues() {\n return {\n globalSafeMode: document.getElementById('s-master-global')\n ? isMasterToggleOn('s-master-global')\n : false,\n safeToolsMode: document.getElementById('s-tools')?.value || 'none',\n safeMaxTurns: Number(document.getElementById('s-turns')?.value),\n safeTimeoutMs: Number(document.getElementById('s-timeout')?.value),\n };\n}\n\nfunction presetMatchesForm(values) {\n const cur = readSettingsFormValues();\n if (!Number.isFinite(cur.safeMaxTurns) || !Number.isFinite(cur.safeTimeoutMs)) {\n return false;\n }\n return (\n cur.globalSafeMode === Boolean(values.globalSafeMode) &&\n cur.safeToolsMode === values.safeToolsMode &&\n cur.safeMaxTurns === Number(values.safeMaxTurns) &&\n cur.safeTimeoutMs === Number(values.safeTimeoutMs)\n );\n}\n\nfunction refreshSettingsPresetUi() {\n for (const p of settingsPresets()) {\n const card = document.querySelector(`[data-preset=\"${p.id}\"]`);\n const btn = document.querySelector(`[data-apply-preset=\"${p.id}\"]`);\n if (!card || !btn) continue;\n const active = presetMatchesForm(p.values);\n card.classList.toggle('is-applied', active);\n btn.textContent = active\n ? t('settings.guideActive')\n : t('settings.guideApply');\n btn.disabled = active;\n btn.classList.toggle('is-applied', active);\n btn.setAttribute('aria-pressed', active ? 'true' : 'false');\n }\n}\n\nfunction applySettingsPresetToForm(values) {\n const tools = document.getElementById('s-tools');\n const turns = document.getElementById('s-turns');\n const timeout = document.getElementById('s-timeout');\n const on = Boolean(values.globalSafeMode);\n setMasterToggle(\n 's-master-global',\n on,\n t('settings.masterOn'),\n t('settings.masterOff'),\n );\n setFeatureRootOff('settings-root', !on);\n setFeatureOffBanner('settings-disabled-banner', !on);\n if (tools && values.safeToolsMode) tools.value = values.safeToolsMode;\n if (turns && values.safeMaxTurns != null) turns.value = String(values.safeMaxTurns);\n if (timeout && values.safeTimeoutMs != null) {\n timeout.value = String(values.safeTimeoutMs);\n }\n refreshSettingsPresetUi();\n}\n\n/** Confirm → fill form → PUT /settings so “Applied” reflects saved state. */\nasync function applySettingsPreset(preset) {\n if (!preset?.values) return;\n if (\n !(await uiConfirm({\n title: t(preset.titleKey),\n message: tf('settings.guideApplyConfirm', { name: t(preset.titleKey) }),\n variant: 'confirm',\n confirmText: t('settings.guideApply'),\n }))\n ) {\n return;\n }\n applySettingsPresetToForm(preset.values);\n try {\n await api('/settings', {\n method: 'PUT',\n body: JSON.stringify({\n globalSafeMode: Boolean(preset.values.globalSafeMode),\n safeToolsMode: preset.values.safeToolsMode,\n safeMaxTurns: Number(preset.values.safeMaxTurns),\n safeTimeoutMs: Number(preset.values.safeTimeoutMs),\n defaultModel: document.getElementById('s-model')?.value?.trim() || '',\n }),\n });\n refreshSettingsPresetUi();\n const bar = document.querySelector('#flash-error');\n if (bar) {\n bar.hidden = false;\n bar.classList.add('flash-ok');\n bar.textContent = t('settings.guideApplied');\n setTimeout(() => {\n if (bar.textContent === t('settings.guideApplied')) {\n bar.hidden = true;\n bar.classList.remove('flash-ok');\n bar.textContent = '';\n }\n }, 2500);\n }\n } catch (e) {\n onErr(e);\n }\n}\n\nasync function renderSettings() {\n const [{ data }, catalog] = await Promise.all([api('/settings'), loadModels()]);\n const modelOpts = (catalog.models || state.models || [])\n .map(\n (m) =>\n `<option value=\"${escapeHtml(m)}\" ${data.defaultModel === m ? 'selected' : ''}>${escapeHtml(m)}</option>`,\n )\n .join('');\n\n const guideCards = settingsPresets()\n .map(\n (p) => `\n <article class=\"settings-guide-card\" data-preset=\"${escapeHtml(p.id)}\">\n <div class=\"settings-guide-card-h\">\n <strong>${escapeHtml(t(p.titleKey))}</strong>\n <button type=\"button\" class=\"btn secondary sm\" data-apply-preset=\"${escapeHtml(p.id)}\">${escapeHtml(t('settings.guideApply'))}</button>\n </div>\n <p class=\"settings-guide-desc\">${escapeHtml(t(p.descKey))}</p>\n <p class=\"settings-guide-detail muted\">${escapeHtml(t(p.detailKey))}</p>\n <div class=\"settings-guide-chips\">\n <span class=\"chip\">${escapeHtml(p.values.globalSafeMode ? t('settings.chipGlobalOn') : t('settings.chipGlobalOff'))}</span>\n <span class=\"chip\">${escapeHtml(p.values.safeToolsMode)}</span>\n <span class=\"chip\">turns ${p.values.safeMaxTurns}</span>\n <span class=\"chip\">${Math.round(p.values.safeTimeoutMs / 1000)}s</span>\n </div>\n </article>`,\n )\n .join('');\n\n const safeOn = Boolean(data.globalSafeMode);\n\n document.getElementById('app').innerHTML = shell(`\n <div id=\"settings-root\" class=\"${safeOn ? '' : 'is-feature-off'}\">\n <div class=\"topbar\">\n <h2>${escapeHtml(t('settings.title'))}</h2>\n <div class=\"toolbar\">\n ${masterToggleBtnHtml({\n id: 's-master-global',\n on: safeOn,\n onLabel: t('settings.masterOn'),\n offLabel: t('settings.masterOff'),\n title: t('settings.globalSafeHint'),\n })}\n <button class=\"btn secondary sm\" id=\"btn-refresh-models\">${escapeHtml(t('settings.refreshModels'))}</button>\n </div>\n </div>\n <div class=\"feature-off-banner\" id=\"settings-disabled-banner\" ${safeOn ? 'hidden' : ''} role=\"status\">\n <strong>${escapeHtml(t('common.featureOff'))}</strong>\n <span>${escapeHtml(t('settings.disabledBanner'))}</span>\n </div>\n ${pageMetaHtml([t('settings.globalSafeHint')])}\n <div class=\"panel\">\n <div class=\"modal-b\">\n <div class=\"form-grid settings-safe-fields\">\n <label>${escapeHtml(t('settings.tools'))}\n <select id=\"s-tools\">\n <option value=\"none\">${escapeHtml(t('settings.toolsNone'))}</option>\n <option value=\"readonly\">${escapeHtml(t('settings.toolsReadonly'))}</option>\n </select>\n <span class=\"hint\">${escapeHtml(t('settings.toolsHint'))}</span>\n </label>\n <label>${escapeHtml(t('settings.maxTurns'))}\n <input id=\"s-turns\" type=\"number\" min=\"1\" max=\"50\" value=\"${data.safeMaxTurns}\" />\n <span class=\"hint\">${escapeHtml(t('settings.maxTurnsHint'))}</span>\n </label>\n <label>${escapeHtml(t('settings.timeout'))}\n <input id=\"s-timeout\" type=\"number\" min=\"1000\" step=\"1000\" value=\"${data.safeTimeoutMs}\" />\n <span class=\"hint\">${escapeHtml(t('settings.timeoutHint'))}</span>\n </label>\n <label class=\"full\">${escapeHtml(t('settings.defaultModel'))}\n <select id=\"s-model\">${modelOpts || `<option value=\"${escapeHtml(data.defaultModel)}\">${escapeHtml(data.defaultModel)}</option>`}</select>\n <span class=\"hint\">${escapeHtml(t('settings.defaultModelHint'))}${catalog.source ? ` · ${escapeHtml(catalog.source)}` : ''}</span>\n </label>\n </div>\n <div class=\"toolbar settings-save-bar\">\n <button class=\"btn\" id=\"s-save\">${escapeHtml(t('settings.save'))}</button>\n </div>\n </div>\n </div>\n <div class=\"panel settings-guide\">\n <div class=\"panel-h\">\n <strong>${escapeHtml(t('settings.guideTitle'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('settings.guideIntro'))}</span>\n </div>\n <div class=\"modal-b\">\n <div class=\"settings-guide-grid\">${guideCards}</div>\n </div>\n </div>\n <div class=\"danger-zone\">\n <h3>${escapeHtml(t('settings.dangerTitle'))}</h3>\n <p class=\"muted\">${escapeHtml(t('settings.panelOffHint'))} · ${escapeHtml(t('settings.panelStatus'))}: <strong>${data.adminPanelEnabled ? t('settings.panelOn') : t('settings.panelOff')}</strong></p>\n <button class=\"btn danger sm\" id=\"s-disable-panel\" ${!data.adminPanelEnabled ? 'disabled' : ''}>${escapeHtml(t('settings.disablePanel'))}</button>\n </div>\n </div>\n `);\n bindShell();\n document.getElementById('s-tools').value = data.safeToolsMode || 'none';\n\n const syncPresetUi = () => refreshSettingsPresetUi();\n ['s-tools', 's-turns', 's-timeout'].forEach((id) => {\n const el = document.getElementById(id);\n if (!el) return;\n el.addEventListener('change', syncPresetUi);\n el.addEventListener('input', syncPresetUi);\n });\n refreshSettingsPresetUi();\n\n document.getElementById('s-master-global')?.addEventListener('click', async () => {\n const next = !isMasterToggleOn('s-master-global');\n setMasterToggle(\n 's-master-global',\n next,\n t('settings.masterOn'),\n t('settings.masterOff'),\n );\n setFeatureRootOff('settings-root', !next);\n setFeatureOffBanner('settings-disabled-banner', !next);\n refreshSettingsPresetUi();\n // Immediate save of master switch + current form values\n try {\n await api('/settings', {\n method: 'PUT',\n body: JSON.stringify({\n globalSafeMode: next,\n safeToolsMode: document.getElementById('s-tools').value,\n safeMaxTurns: Number(document.getElementById('s-turns').value),\n safeTimeoutMs: Number(document.getElementById('s-timeout').value),\n defaultModel: document.getElementById('s-model').value.trim(),\n }),\n });\n } catch (e) {\n setMasterToggle(\n 's-master-global',\n !next,\n t('settings.masterOn'),\n t('settings.masterOff'),\n );\n setFeatureRootOff('settings-root', next);\n setFeatureOffBanner('settings-disabled-banner', next);\n onErr(e);\n }\n });\n\n document.getElementById('btn-refresh-models').onclick = async () => {\n await loadModels(true);\n renderSettings().catch(onErr);\n };\n document.getElementById('s-save').onclick = async () => {\n try {\n await api('/settings', {\n method: 'PUT',\n body: JSON.stringify({\n globalSafeMode: isMasterToggleOn('s-master-global'),\n safeToolsMode: document.getElementById('s-tools').value,\n safeMaxTurns: Number(document.getElementById('s-turns').value),\n safeTimeoutMs: Number(document.getElementById('s-timeout').value),\n defaultModel: document.getElementById('s-model').value.trim(),\n }),\n });\n refreshSettingsPresetUi();\n const bar = document.querySelector('#flash-error');\n if (bar) {\n bar.hidden = false;\n bar.classList.add('flash-ok');\n bar.textContent = t('settings.saved');\n setTimeout(() => {\n bar.hidden = true;\n bar.classList.remove('flash-ok');\n bar.textContent = '';\n }, 2000);\n }\n } catch (e) {\n onErr(e);\n }\n };\n document.querySelectorAll('[data-apply-preset]').forEach((btn) => {\n btn.addEventListener('click', async () => {\n if (btn.disabled) return;\n const id = btn.getAttribute('data-apply-preset');\n const preset = settingsPresets().find((p) => p.id === id);\n if (preset) await applySettingsPreset(preset);\n });\n });\n document.getElementById('s-disable-panel').onclick = async () => {\n if (\n !(await uiConfirm({\n message: t('settings.disablePanelConfirm'),\n variant: 'danger',\n confirmText: t('settings.disablePanel'),\n }))\n )\n return;\n try {\n await api('/settings', {\n method: 'PUT',\n body: JSON.stringify({ adminPanelEnabled: false }),\n });\n await uiAlert({\n message: t('settings.disablePanelDone'),\n title: t('common.notice'),\n });\n logout(false);\n } catch (e) {\n onErr(e);\n }\n };\n}\n\n/** Admin: protocol and capability feature flags — tab layout matches other pages */\nasync function renderApiFeatures() {\n const res = await api('/api-features');\n if (state.page !== 'apiFeatures') return;\n const data = res.data || {};\n\n const groups = [\n {\n id: 'protocols',\n title: t('apiFeatures.groupProtocols'),\n tabLabel: t('apiFeatures.tabProtocols'),\n keys: ['openaiChat', 'openaiResponses', 'anthropicMessages'],\n },\n {\n id: 'media',\n title: t('apiFeatures.groupMedia'),\n tabLabel: t('apiFeatures.tabMedia'),\n keys: ['imagesApi', 'filesOpenAiAlias', 'videoApi', 'audioApi'],\n },\n {\n id: 'caps',\n title: t('apiFeatures.groupCaps'),\n tabLabel: t('apiFeatures.tabCaps'),\n keys: [\n 'tools',\n 'structuredOutput',\n 'vision',\n 'reasoningEffort',\n 'webSearch',\n 'subagents',\n 'planMode',\n 'memory',\n 'sessionResume',\n 'bestOfN',\n 'checkLoop',\n 'systemOverride',\n 'rules',\n 'permissionMode',\n 'sandbox',\n ],\n },\n {\n id: 'emu',\n title: t('apiFeatures.groupEmu'),\n tabLabel: t('apiFeatures.tabEmu'),\n keys: [\n 'usageEstimate',\n 'assistantsEmulation',\n 'strictSampling',\n 'forceDisableToolsInSafe',\n ],\n },\n ];\n\n const tab =\n state.apiFeaturesTab === 'media' ||\n state.apiFeaturesTab === 'caps' ||\n state.apiFeaturesTab === 'emu' ||\n state.apiFeaturesTab === 'protocols'\n ? state.apiFeaturesTab\n : 'protocols';\n state.apiFeaturesTab = tab;\n\n const flagLabel = (k) => t(`apiFeatures.flag.${k}`) || k;\n const flagHint = (k) => t(`apiFeatures.hint.${k}`) || '';\n\n const groupOnCount = (keys) => keys.filter((k) => Boolean(data[k])).length;\n\n const flagRowsHtml = (keys) =>\n keys\n .map((k) => {\n const on = Boolean(data[k]);\n return `\n <div class=\"dash-prot-row api-feat-row\" data-feat=\"${escapeHtml(k)}\">\n <div>\n <strong>${escapeHtml(flagLabel(k))}</strong>\n <div class=\"muted api-feat-hint\">${escapeHtml(flagHint(k))}</div>\n </div>\n <button type=\"button\" class=\"master-toggle ${on ? 'is-on' : 'is-off'}\" data-feat-toggle=\"${escapeHtml(k)}\" aria-pressed=\"${on ? 'true' : 'false'}\">\n <span class=\"master-toggle-track\" aria-hidden=\"true\"><span class=\"master-toggle-knob\"></span></span>\n <span class=\"master-toggle-label\">${escapeHtml(on ? t('dash.on') : t('dash.off'))}</span>\n </button>\n </div>`;\n })\n .join('');\n\n const totalKeys = groups.reduce((n, g) => n + g.keys.length, 0);\n const totalOn = groups.reduce((n, g) => n + groupOnCount(g.keys), 0);\n\n const kpiGrid = `\n <div class=\"grid api-feat-kpi-grid\">\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('apiFeatures.kpiEnabled'))}</div>\n <div class=\"value value-sm\">${totalOn}<span class=\"dash-kpi-den\">/${totalKeys}</span></div>\n <div class=\"muted card-sub\">${escapeHtml(t('apiFeatures.kpiEnabledSub'))}</div>\n </div>\n ${groups\n .map((g) => {\n const on = groupOnCount(g.keys);\n return `\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(g.tabLabel)}</div>\n <div class=\"value value-sm\">${on}<span class=\"dash-kpi-den\">/${g.keys.length}</span></div>\n <div class=\"muted card-sub\">${escapeHtml(g.title)}</div>\n </div>`;\n })\n .join('')}\n </div>`;\n\n const tabButtons = groups\n .map((g) => {\n const on = groupOnCount(g.keys);\n return `\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === g.id ? 'is-active' : ''}\" data-feat-tab=\"${escapeHtml(g.id)}\" aria-selected=\"${tab === g.id}\">\n ${escapeHtml(g.tabLabel)}\n <span class=\"seg-tab-count\">${on}/${g.keys.length}</span>\n </button>`;\n })\n .join('');\n\n const tabPanes = groups\n .map((g) => {\n return `\n <div class=\"usage-tab-pane api-feat-tab-pane\" id=\"api-feat-tab-${escapeHtml(g.id)}\" ${tab === g.id ? '' : 'hidden'}>\n <div class=\"panel data-table-panel api-feat-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(g.title)}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(tf('apiFeatures.groupMeta', { on: groupOnCount(g.keys), n: g.keys.length }))}</span>\n </div>\n </div>\n <div class=\"panel-pad api-feat-list\">${flagRowsHtml(g.keys)}</div>\n </div>\n </div>`;\n })\n .join('');\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('apiFeatures.title'))}</h2>\n <div class=\"toolbar\">\n <button type=\"button\" class=\"btn secondary sm\" data-feat-preset=\"open\">${escapeHtml(t('apiFeatures.presetOpen'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-feat-preset=\"locked\">${escapeHtml(t('apiFeatures.presetLocked'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-feat-preset=\"dev\">${escapeHtml(t('apiFeatures.presetDev'))}</button>\n </div>\n </div>\n ${pageMetaHtml([t('apiFeatures.intro')])}\n ${kpiGrid}\n\n <div class=\"usage-tabs-panel panel api-feat-tabs-panel\">\n <div class=\"seg-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('apiFeatures.title'))}\">\n ${tabButtons}\n </div>\n <div class=\"usage-tab-body\">\n ${tabPanes}\n </div>\n </div>\n `);\n bindShell();\n\n document.querySelectorAll('[data-feat-tab]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const raw = btn.getAttribute('data-feat-tab') || 'protocols';\n const next =\n raw === 'media' || raw === 'caps' || raw === 'emu' || raw === 'protocols'\n ? raw\n : 'protocols';\n if (state.apiFeaturesTab === next) return;\n state.apiFeaturesTab = next;\n renderApiFeatures().catch(onErr);\n });\n });\n\n document.querySelectorAll('[data-feat-toggle]').forEach((btn) => {\n btn.addEventListener('click', async () => {\n const key = btn.getAttribute('data-feat-toggle');\n if (!key) return;\n const next = !btn.classList.contains('is-on');\n try {\n await api('/api-features', {\n method: 'PUT',\n body: JSON.stringify({ [key]: next }),\n });\n await renderApiFeatures();\n } catch (e) {\n onErr(e);\n }\n });\n });\n\n document.querySelectorAll('[data-feat-preset]').forEach((btn) => {\n btn.addEventListener('click', async () => {\n const name = btn.getAttribute('data-feat-preset');\n if (\n !(await uiConfirm({\n message: tf('apiFeatures.presetConfirm', { name }),\n confirmText: t('common.confirm'),\n }))\n )\n return;\n try {\n await api('/api-features/preset', {\n method: 'POST',\n body: JSON.stringify({ name }),\n });\n await renderApiFeatures();\n } catch (e) {\n onErr(e);\n }\n });\n });\n}\n\n/** Admin: media studio + assets + jobs — tab layout matches chat queue */\nasync function renderMedia() {\n if (!state.mediaFilter) {\n state.mediaFilter = {\n tab: 'studio',\n q: '',\n kind: '',\n provider: '',\n from: '',\n to: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n jobSortBy: 'createdAt',\n jobSortDir: 'desc',\n limit: 20,\n offset: 0,\n };\n }\n if (!state.mediaFilter.sortBy) state.mediaFilter.sortBy = 'createdAt';\n if (!state.mediaFilter.sortDir) state.mediaFilter.sortDir = 'desc';\n if (!state.mediaFilter.jobSortBy) state.mediaFilter.jobSortBy = 'createdAt';\n if (!state.mediaFilter.jobSortDir) state.mediaFilter.jobSortDir = 'desc';\n if (!state.mediaFilter.tab) state.mediaFilter.tab = 'studio';\n const f = state.mediaFilter;\n const tab =\n f.tab === 'assets' || f.tab === 'jobs' || f.tab === 'studio'\n ? f.tab\n : 'studio';\n f.tab = tab;\n\n const params = new URLSearchParams({\n limit: String(f.limit),\n offset: String(f.offset),\n });\n if (f.q) params.set('q', f.q);\n if (f.kind) params.set('kind', f.kind);\n if (f.provider) params.set('provider', f.provider);\n if (f.from) params.set('from', new Date(f.from).toISOString());\n if (f.to) {\n const end = new Date(f.to);\n end.setHours(23, 59, 59, 999);\n params.set('to', end.toISOString());\n }\n appendSortParams(params, f);\n\n const jobParams = new URLSearchParams({ limit: '50', offset: '0' });\n appendSortParams(jobParams, f, 'jobSortBy', 'jobSortDir');\n\n // Keys + full model catalog (local models + system default) + assets/jobs\n const [catalog, , assetsRes, jobsRes] = await Promise.all([\n loadModels(false).catch(() => ({\n models: state.models || [],\n defaultModel: '',\n })),\n loadKeys().catch(() => {}),\n api(`/media/assets?${params}`),\n api(`/media/jobs?${jobParams}`).catch(() => ({ data: [], total: 0 })),\n ]);\n const assets = assetsRes.data || [];\n const assetsTotal = assetsRes.total ?? assets.length;\n const jobs = jobsRes.data || [];\n const jobsTotal = jobsRes.total ?? jobs.length;\n\n const agentKeys = (state.keys || []).filter(\n (k) => k.isActive !== false && (k.mode === 'agent' || k.role === 'admin'),\n );\n const genKeyOpts = [\n `<option value=\"\">${escapeHtml(t('media.generateKeySession'))}</option>`,\n ...agentKeys.map(\n (k) =>\n `<option value=\"${escapeHtml(k.id)}\">${escapeHtml(k.name || k.id)} · ${escapeHtml(k.keyPrefix || '')}… · ${escapeHtml(k.mode || '')}</option>`,\n ),\n ].join('');\n const modelList = catalog.models?.length\n ? catalog.models\n : state.models || [];\n const defaultModel =\n catalog.defaultModel || modelList[0] || '';\n // All local catalog models; system default selected\n const genModelOpts = modelList.length\n ? modelList\n .map(\n (m) =>\n `<option value=\"${escapeHtml(m)}\" ${m === defaultModel ? 'selected' : ''}>${escapeHtml(m)}${m === defaultModel ? ` · ${escapeHtml(t('media.modelDefault'))}` : ''}</option>`,\n )\n .join('')\n : `<option value=\"\">${escapeHtml(defaultModel || t('media.modelEmpty'))}</option>`;\n\n // OpenAI-compat aspect_ratio for image / video\n const aspectOpts = [\n ['1:1', '1:1 · square'],\n ['16:9', '16:9 · landscape'],\n ['9:16', '9:16 · portrait / story'],\n ['4:3', '4:3'],\n ['3:4', '3:4'],\n ['3:2', '3:2'],\n ['2:3', '2:3'],\n ['auto', 'auto'],\n ]\n .map(\n ([v, label], i) =>\n `<option value=\"${v}\" ${i === 0 ? 'selected' : ''}>${escapeHtml(label)}</option>`,\n )\n .join('');\n\n const bodyHtml = assets\n .map((a) => {\n const mime = a.mime || '';\n const fname = a.filename || a.originalName || '';\n const canPreview = isBrowserPreviewable(mime, fname);\n const pKind = mediaPreviewKind(mime, fname) || '';\n const preview = canPreview\n ? `<button type=\"button\" class=\"btn ghost sm\" data-media-preview=\"${escapeHtml(a.id)}\" data-media-mime=\"${escapeHtml(mime)}\" data-media-name=\"${escapeHtml(fname)}\" data-media-kind=\"${escapeHtml(a.kind || '')}\" data-media-bytes=\"${escapeHtml(String(a.bytes ?? ''))}\" data-media-prompt=\"${escapeHtml(a.prompt || '')}\" data-preview-kind=\"${escapeHtml(pKind)}\" title=\"${escapeHtml(t('media.preview'))}\">${escapeHtml(t('media.preview'))}</button>`\n : '';\n return `\n <tr>\n <td>\n <div class=\"cell-primary mono\" title=\"${escapeHtml(a.id)}\">${escapeHtml(String(a.id).slice(0, 8))}…</div>\n <div class=\"cell-sub\">${escapeHtml(fname || a.source || '—')}</div>\n </td>\n <td>${escapeHtml(a.kind || '—')}</td>\n <td class=\"muted\">${escapeHtml(mime || '—')}</td>\n <td>${fmtBytes(a.bytes)}</td>\n <td>${escapeHtml(a.provider || '—')}</td>\n <td class=\"muted\" title=\"${escapeHtml(a.prompt || '')}\">${escapeHtml((a.prompt || '—').slice(0, 48))}</td>\n <td>${fmtTime(a.created_at)}</td>\n <td><div class=\"row-actions\">\n ${preview}\n <button type=\"button\" class=\"btn ghost sm\" data-media-dl=\"${escapeHtml(a.id)}\" data-media-name=\"${escapeHtml(fname)}\">${escapeHtml(t('media.download'))}</button>\n <button type=\"button\" class=\"btn danger sm\" data-media-del=\"${escapeHtml(a.id)}\">${escapeHtml(t('media.delete'))}</button>\n </div></td>\n </tr>`;\n })\n .join('');\n\n const filter = filterPanelHtml({\n title: t('common.filterTitle'),\n hint: t('common.filterHint'),\n meta: tf('common.pagerTotal', { n: assetsTotal }),\n searchHtml: `\n <div class=\"data-filter-search\">\n <label for=\"mf-q\">${escapeHtml(t('common.search'))}</label>\n <input type=\"search\" id=\"mf-q\" value=\"${escapeHtml(f.q)}\" placeholder=\"${escapeHtml(t('media.searchPh'))}\" />\n </div>`,\n gridHtml: `\n <label>${escapeHtml(t('media.kind'))}\n <select id=\"mf-kind\">\n <option value=\"\">${escapeHtml(t('media.allKinds'))}</option>\n <option value=\"image\" ${f.kind === 'image' ? 'selected' : ''}>image</option>\n <option value=\"video\" ${f.kind === 'video' ? 'selected' : ''}>video</option>\n <option value=\"audio\" ${f.kind === 'audio' ? 'selected' : ''}>audio</option>\n </select>\n </label>\n <label>${escapeHtml(t('media.provider'))}\n <input type=\"text\" id=\"mf-provider\" value=\"${escapeHtml(f.provider)}\" placeholder=\"${escapeHtml(t('media.providerPh'))}\" />\n </label>\n <label>${escapeHtml(t('media.from'))}\n <input type=\"date\" id=\"mf-from\" value=\"${escapeHtml(f.from)}\" />\n </label>\n <label>${escapeHtml(t('media.to'))}\n <input type=\"date\" id=\"mf-to\" value=\"${escapeHtml(f.to)}\" />\n </label>`,\n });\n\n const assetsTable = dataTablePanelHtml({\n headHtml: `\n <th>ID</th>\n ${sortThHtml({ field: 'kind', label: t('media.kind'), filterRef: f })}\n ${sortThHtml({ field: 'mime', label: 'MIME', filterRef: f })}\n ${sortThHtml({ field: 'byteSize', label: t('media.bytes'), filterRef: f })}\n ${sortThHtml({ field: 'provider', label: t('media.provider'), filterRef: f })}\n <th>${escapeHtml(t('media.prompt'))}</th>\n ${sortThHtml({ field: 'createdAt', label: t('media.created'), filterRef: f })}\n <th>${escapeHtml(t('common.actions'))}</th>`,\n bodyHtml,\n colSpan: 8,\n emptyText: t('media.empty'),\n pagerHtml: pagerHtml({\n total: assetsTotal,\n limit: f.limit,\n offset: f.offset,\n idPrefix: 'media',\n }),\n });\n\n const jobRows = jobs\n .map(\n (j) => `\n <tr>\n <td>\n <div class=\"cell-primary mono\" title=\"${escapeHtml(j.id)}\">${escapeHtml(String(j.id).slice(0, 8))}…</div>\n </td>\n <td>${escapeHtml(j.status || '—')}</td>\n <td class=\"muted\" title=\"${escapeHtml(j.prompt || '')}\">${escapeHtml((j.prompt || '—').slice(0, 64))}</td>\n <td class=\"mono\">${escapeHtml(j.result_asset_id ? String(j.result_asset_id).slice(0, 8) + '…' : '—')}</td>\n <td>${fmtTime(j.created_at)}</td>\n </tr>`,\n )\n .join('');\n\n const jobsTable = dataTablePanelHtml({\n headHtml: `\n <th>ID</th>\n ${sortThHtml({ field: 'status', label: t('media.status'), filterRef: f, sortByKey: 'jobSortBy', sortDirKey: 'jobSortDir' })}\n <th>${escapeHtml(t('media.prompt'))}</th>\n <th>Asset</th>\n ${sortThHtml({ field: 'createdAt', label: t('media.created'), filterRef: f, sortByKey: 'jobSortBy', sortDirKey: 'jobSortDir' })}`,\n bodyHtml: jobRows,\n colSpan: 5,\n emptyText: t('media.jobsEmpty'),\n });\n\n const studioPane = `\n <div class=\"panel media-studio-panel data-table-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('media.studioTitle'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('media.studioHint'))}</span>\n </div>\n </div>\n <div class=\"panel-pad\">\n <div class=\"seg-tabs media-mode-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('media.studioTitle'))}\">\n <button type=\"button\" class=\"seg-tab is-active\" data-mg-mode=\"generate\" role=\"tab\" aria-selected=\"true\">${escapeHtml(t('media.modeGenerate'))}</button>\n <button type=\"button\" class=\"seg-tab\" data-mg-mode=\"edit\" role=\"tab\" aria-selected=\"false\">${escapeHtml(t('media.modeEdit'))}</button>\n <button type=\"button\" class=\"seg-tab\" data-mg-mode=\"video\" role=\"tab\" aria-selected=\"false\">${escapeHtml(t('media.modeVideo'))}</button>\n <button type=\"button\" class=\"seg-tab\" data-mg-mode=\"speech\" role=\"tab\" aria-selected=\"false\">${escapeHtml(t('media.modeSpeech'))}</button>\n <button type=\"button\" class=\"seg-tab\" data-mg-mode=\"transcribe\" role=\"tab\" aria-selected=\"false\">${escapeHtml(t('media.modeTranscribe'))}</button>\n </div>\n <div class=\"form-grid\">\n <label class=\"full\" id=\"mg-prompt-wrap\">${escapeHtml(t('media.generatePrompt'))}\n <textarea id=\"mg-prompt\" rows=\"3\" placeholder=\"${escapeHtml(t('media.generatePromptPh'))}\"></textarea>\n </label>\n <label>${escapeHtml(t('media.generateKey'))}\n <select id=\"mg-key\">${genKeyOpts}</select>\n </label>\n <label>${escapeHtml(t('chats.model'))}\n <select id=\"mg-model\">${genModelOpts}</select>\n <span class=\"hint\">${escapeHtml(t('media.modelHint'))}</span>\n </label>\n <label id=\"mg-aspect-wrap\">${escapeHtml(t('media.aspectRatio'))}\n <select id=\"mg-aspect\">${aspectOpts}</select>\n <span class=\"hint\">${escapeHtml(t('media.aspectHint'))}</span>\n </label>\n <label id=\"mg-n-wrap\">${escapeHtml(t('media.generateN'))}\n <input type=\"number\" id=\"mg-n\" min=\"1\" max=\"4\" value=\"1\" />\n <span class=\"hint\">${escapeHtml(t('media.nHint'))}</span>\n </label>\n <label id=\"mg-format-wrap\">${escapeHtml(t('media.outputFormat'))}\n <select id=\"mg-format\"></select>\n <span class=\"hint\">${escapeHtml(t('media.outputFormatHint'))}</span>\n </label>\n <label id=\"mg-voice-wrap\" hidden>${escapeHtml(t('media.videoVoice'))}\n <select id=\"mg-voice\">\n <option value=\"\">${escapeHtml(t('media.videoVoiceNone'))}</option>\n ${['ara', 'eve', 'leo', 'rex', 'sal', 'mio']\n .map((v) => `<option value=\"${v}\">${v}</option>`)\n .join('')}\n </select>\n <span class=\"hint\">${escapeHtml(t('media.videoVoiceHint'))}</span>\n </label>\n <label id=\"mg-duration-wrap\" hidden>${escapeHtml(t('media.videoDuration'))}\n <select id=\"mg-duration\">\n ${[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]\n .map(\n (s) =>\n `<option value=\"${s}\" ${s === 6 ? 'selected' : ''}>${s}s</option>`,\n )\n .join('')}\n </select>\n <span class=\"hint\">${escapeHtml(t('media.videoDurationHint'))}</span>\n </label>\n </div>\n <div id=\"mg-source-section\" class=\"media-source-section\" hidden>\n <div class=\"media-source-head\">\n <strong>${escapeHtml(t('media.sourceTitle'))}</strong>\n <span class=\"muted hint\">${escapeHtml(t('media.sourceHint'))}</span>\n </div>\n <div class=\"media-dropzone\" id=\"mg-dropzone\" tabindex=\"0\" role=\"button\" aria-label=\"${escapeHtml(t('media.dropzoneAria'))}\">\n <input type=\"file\" id=\"mg-file\" accept=\"image/*\" hidden />\n <div class=\"media-dropzone-inner\" id=\"mg-drop-inner\">\n <div class=\"media-dropzone-icon\" aria-hidden=\"true\">📎</div>\n <strong id=\"mg-drop-title\">${escapeHtml(t('media.dropTitle'))}</strong>\n <span class=\"muted\" id=\"mg-drop-hint\">${escapeHtml(t('media.dropHint'))}</span>\n <div class=\"media-dropzone-actions\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"mg-pick-file\">${escapeHtml(t('media.pickFile'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"mg-pick-lib\">${escapeHtml(t('media.pickLibrary'))}</button>\n <button type=\"button\" class=\"btn ghost sm\" id=\"mg-clear-source\" hidden>${escapeHtml(t('media.clearSource'))}</button>\n </div>\n <div class=\"media-source-chip\" id=\"mg-source-chip\" hidden></div>\n </div>\n </div>\n </div>\n <div class=\"media-gen-actions toolbar\">\n <button type=\"button\" class=\"btn\" id=\"mg-submit\">${escapeHtml(t('media.generateSubmit'))}</button>\n <span id=\"mg-status\" class=\"muted\" hidden></span>\n </div>\n </div>\n </div>`;\n\n // KPI strip (always visible) — same pattern as queue / usage / ddos\n const kpiGrid = `\n <div class=\"grid media-kpi-grid\" id=\"media-kpi-grid\">\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('media.assets'))}</div>\n <div class=\"value value-sm\">${assetsTotal}</div>\n <div class=\"muted card-sub\">${escapeHtml(t('media.kpiAssetsSub'))}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('media.jobs'))}</div>\n <div class=\"value value-sm\">${jobsTotal}</div>\n <div class=\"muted card-sub\">${escapeHtml(t('media.kpiJobsSub'))}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('media.tabStudio'))}</div>\n <div class=\"value value-sm\">${escapeHtml(t('media.modeGenerate'))} / ${escapeHtml(t('media.modeEdit'))} / ${escapeHtml(t('media.modeVideo'))}</div>\n <div class=\"muted card-sub\">${escapeHtml(t('media.kpiStudioSub'))}</div>\n </div>\n </div>`;\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('media.title'))}</h2>\n </div>\n ${pageMetaHtml([t('media.intro')])}\n ${kpiGrid}\n <div class=\"usage-tabs-panel panel media-tabs-panel queue-tabs-panel\">\n <div class=\"seg-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('media.title'))}\">\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'studio' ? 'is-active' : ''}\" data-media-tab=\"studio\" aria-selected=\"${tab === 'studio'}\">\n ${escapeHtml(t('media.tabStudio'))}\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'assets' ? 'is-active' : ''}\" data-media-tab=\"assets\" aria-selected=\"${tab === 'assets'}\">\n ${escapeHtml(t('media.tabAssets'))}\n <span class=\"seg-tab-count\">${assetsTotal}</span>\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'jobs' ? 'is-active' : ''}\" data-media-tab=\"jobs\" aria-selected=\"${tab === 'jobs'}\">\n ${escapeHtml(t('media.tabJobs'))}\n <span class=\"seg-tab-count\">${jobsTotal}</span>\n </button>\n </div>\n <div class=\"usage-tab-body\">\n <div class=\"usage-tab-pane media-tab-pane-studio\" id=\"media-tab-studio\" ${tab === 'studio' ? '' : 'hidden'}>\n ${studioPane}\n </div>\n <div class=\"usage-tab-pane media-tab-pane-assets\" id=\"media-tab-assets\" ${tab === 'assets' ? '' : 'hidden'}>\n ${filter}\n ${assetsTable}\n </div>\n <div class=\"usage-tab-pane media-tab-pane-jobs\" id=\"media-tab-jobs\" ${tab === 'jobs' ? '' : 'hidden'}>\n ${jobsTable}\n </div>\n </div>\n </div>\n `);\n bindShell();\n\n document.querySelectorAll('[data-media-tab]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const raw = btn.getAttribute('data-media-tab') || 'studio';\n const next =\n raw === 'assets' || raw === 'jobs' || raw === 'studio' ? raw : 'studio';\n if (state.mediaFilter.tab === next) return;\n state.mediaFilter.tab = next;\n renderMedia().catch(onErr);\n });\n });\n\n // ——— Studio: mode, source (drop / library), submit ———\n async function fetchMediaBlob(id) {\n const r = await fetch(`/admin/api/media/assets/${id}/download`, {\n headers: { Authorization: `Bearer ${state.key}` },\n });\n if (!r.ok) throw new Error(await r.text());\n return r.blob();\n }\n\n {\n let mediaMode = 'generate';\n /** @type {{ kind: 'file'|'asset'|'document', file?: File, id?: string, name?: string, mime?: string } | null} */\n let mediaSource = null;\n\n const paintSourceChip = () => {\n const chip = document.getElementById('mg-source-chip');\n const clearBtn = document.getElementById('mg-clear-source');\n if (!chip) return;\n if (!mediaSource) {\n chip.hidden = true;\n chip.innerHTML = '';\n if (clearBtn) clearBtn.hidden = true;\n return;\n }\n const kindLabel =\n mediaSource.kind === 'file'\n ? t('media.sourceKindUpload')\n : mediaSource.kind === 'asset'\n ? t('media.sourceKindAsset')\n : t('media.sourceKindDocument');\n chip.hidden = false;\n chip.innerHTML = `<span class=\"chip\">${escapeHtml(kindLabel)}</span> <span class=\"mono\">${escapeHtml(mediaSource.name || mediaSource.id || '')}</span>`;\n if (clearBtn) clearBtn.hidden = false;\n };\n\n const setMediaSource = (src) => {\n mediaSource = src;\n const input = document.getElementById('mg-file');\n if (input && src?.kind !== 'file') input.value = '';\n paintSourceChip();\n };\n\n const setMediaMode = (mode) => {\n mediaMode =\n mode === 'edit' ||\n mode === 'video' ||\n mode === 'speech' ||\n mode === 'transcribe'\n ? mode\n : 'generate';\n document.querySelectorAll('[data-mg-mode]').forEach((b) => {\n const on = b.getAttribute('data-mg-mode') === mediaMode;\n b.classList.toggle('is-active', on);\n b.setAttribute('aria-selected', on ? 'true' : 'false');\n });\n const srcSec = document.getElementById('mg-source-section');\n const nWrap = document.getElementById('mg-n-wrap');\n const durWrap = document.getElementById('mg-duration-wrap');\n const voiceWrap = document.getElementById('mg-voice-wrap');\n const aspectWrap = document.getElementById('mg-aspect-wrap');\n const promptWrap = document.getElementById('mg-prompt-wrap');\n const submit = document.getElementById('mg-submit');\n if (srcSec) {\n srcSec.hidden = mediaMode === 'generate' || mediaMode === 'speech';\n }\n if (nWrap) nWrap.hidden = mediaMode !== 'generate' && mediaMode !== 'edit';\n if (durWrap) durWrap.hidden = mediaMode !== 'video';\n if (voiceWrap) voiceWrap.hidden = mediaMode !== 'video';\n if (aspectWrap) {\n aspectWrap.hidden = mediaMode === 'speech' || mediaMode === 'transcribe';\n }\n if (promptWrap) promptWrap.hidden = mediaMode === 'transcribe';\n const fmtSel = document.getElementById('mg-format');\n const fmtWrap = document.getElementById('mg-format-wrap');\n if (fmtWrap) fmtWrap.hidden = false;\n if (fmtSel) {\n const opts =\n mediaMode === 'speech'\n ? ['wav', 'mp3', 'opus', 'flac', 'aac']\n : mediaMode === 'transcribe'\n ? ['txt', 'json', 'srt', 'vtt']\n : mediaMode === 'video'\n ? ['mp4', 'webm', 'mov']\n : ['png', 'jpeg', 'webp'];\n const cur = fmtSel.value;\n fmtSel.innerHTML = opts\n .map(\n (o) =>\n `<option value=\"${o}\" ${o === cur ? 'selected' : ''}>${o}</option>`,\n )\n .join('');\n if (!opts.includes(fmtSel.value)) fmtSel.value = opts[0];\n }\n const fileEl = document.getElementById('mg-file');\n if (fileEl) {\n fileEl.accept = mediaMode === 'transcribe' ? 'audio/*' : 'image/*';\n }\n if (submit) {\n submit.textContent =\n mediaMode === 'edit'\n ? t('media.editSubmit')\n : mediaMode === 'video'\n ? t('media.videoSubmit')\n : mediaMode === 'speech'\n ? t('media.speechSubmit')\n : mediaMode === 'transcribe'\n ? t('media.transcribeSubmit')\n : t('media.generateSubmit');\n }\n const ta = document.getElementById('mg-prompt');\n if (ta) {\n ta.placeholder =\n mediaMode === 'edit'\n ? t('media.editPromptPh')\n : mediaMode === 'video'\n ? t('media.videoPromptPh')\n : mediaMode === 'speech'\n ? t('media.speechPromptPh')\n : t('media.generatePromptPh');\n }\n const dropTitle = document.getElementById('mg-drop-title');\n const dropHint = document.getElementById('mg-drop-hint');\n if (dropTitle) {\n dropTitle.textContent =\n mediaMode === 'video'\n ? t('media.dropTitleVideo')\n : mediaMode === 'transcribe'\n ? t('media.dropTitleAudio')\n : t('media.dropTitle');\n }\n if (dropHint) {\n dropHint.textContent =\n mediaMode === 'video'\n ? t('media.dropHintVideo')\n : mediaMode === 'transcribe'\n ? t('media.dropHintAudio')\n : t('media.dropHint');\n }\n };\n\n document.querySelectorAll('[data-mg-mode]').forEach((btn) => {\n btn.addEventListener('click', () =>\n setMediaMode(btn.getAttribute('data-mg-mode') || 'generate'),\n );\n });\n setMediaMode('generate');\n\n const zone = document.getElementById('mg-dropzone');\n const fileInput = document.getElementById('mg-file');\n const acceptImageFile = (file) => {\n if (!file) return false;\n if (file.type && file.type.startsWith('image/')) return true;\n return /\\.(png|jpe?g|webp|gif|bmp|svg)$/i.test(file.name || '');\n };\n const acceptAudioFile = (file) => {\n if (!file) return false;\n if (file.type && file.type.startsWith('audio/')) return true;\n return /\\.(wav|mp3|m4a|aac|ogg|oga|flac|opus|webm)$/i.test(file.name || '');\n };\n const takeFiles = (fileList) => {\n const accept =\n mediaMode === 'transcribe' ? acceptAudioFile : acceptImageFile;\n const file = [...(fileList || [])].find(accept);\n if (!file) {\n showError(\n mediaMode === 'transcribe'\n ? t('media.sourceNeedAudio')\n : t('media.sourceNeedImage'),\n );\n return;\n }\n setMediaSource({\n kind: 'file',\n file,\n name: file.name,\n mime: file.type || (mediaMode === 'transcribe' ? 'audio/*' : 'image/*'),\n });\n showError('');\n };\n\n document.getElementById('mg-pick-file')?.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n fileInput?.click();\n });\n fileInput?.addEventListener('change', () => {\n if (fileInput.files?.length) takeFiles(fileInput.files);\n });\n document.getElementById('mg-clear-source')?.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n setMediaSource(null);\n });\n document.getElementById('mg-pick-lib')?.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n openMediaSourceLibraryPicker({\n imagesOnly: mediaMode !== 'transcribe',\n audioOnly: mediaMode === 'transcribe',\n onPick: (item) => {\n setMediaSource({\n kind: item.kind,\n id: item.id,\n name: item.name,\n mime: item.mime,\n });\n showError('');\n },\n }).catch((err) => showError(err.message || t('media.libraryLoadFail')));\n });\n\n if (zone) {\n zone.addEventListener('click', (e) => {\n if (e.target.closest('button')) return;\n fileInput?.click();\n });\n zone.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n fileInput?.click();\n }\n });\n ;['dragenter', 'dragover'].forEach((ev) => {\n zone.addEventListener(ev, (e) => {\n e.preventDefault();\n e.stopPropagation();\n zone.classList.add('is-dragover');\n });\n });\n ;['dragleave', 'drop'].forEach((ev) => {\n zone.addEventListener(ev, (e) => {\n e.preventDefault();\n e.stopPropagation();\n zone.classList.remove('is-dragover');\n });\n });\n zone.addEventListener('drop', (e) => {\n const dt = e.dataTransfer;\n if (dt?.files?.length) takeFiles(dt.files);\n });\n }\n\n // Page-level drag highlight (abort previous listeners on re-render)\n if (state._mediaDragAbort) {\n try {\n state._mediaDragAbort.abort();\n } catch {\n /* ignore */\n }\n }\n state._mediaDragAbort = new AbortController();\n const dragSig = { signal: state._mediaDragAbort.signal };\n const mediaPage = document.getElementById('app');\n let dragDepth = 0;\n window.addEventListener(\n 'dragenter',\n (e) => {\n if (mediaMode === 'generate' || mediaMode === 'speech') return;\n if (![...(e.dataTransfer?.types || [])].includes('Files')) return;\n dragDepth += 1;\n mediaPage?.classList.add('is-media-file-drag');\n },\n dragSig,\n );\n window.addEventListener(\n 'dragleave',\n () => {\n dragDepth = Math.max(0, dragDepth - 1);\n if (dragDepth === 0) mediaPage?.classList.remove('is-media-file-drag');\n },\n dragSig,\n );\n window.addEventListener(\n 'drop',\n (e) => {\n dragDepth = 0;\n mediaPage?.classList.remove('is-media-file-drag');\n if (mediaMode === 'generate' || mediaMode === 'speech') return;\n if (e.dataTransfer?.files?.length) {\n e.preventDefault();\n takeFiles(e.dataTransfer.files);\n }\n },\n dragSig,\n );\n window.addEventListener(\n 'dragover',\n (e) => {\n if (mediaMode === 'generate' || mediaMode === 'speech') return;\n if ([...(e.dataTransfer?.types || [])].includes('Files')) {\n e.preventDefault();\n }\n },\n dragSig,\n );\n\n document.getElementById('mg-submit')?.addEventListener('click', async () => {\n const prompt = document.getElementById('mg-prompt')?.value?.trim() || '';\n if (!prompt && mediaMode !== 'transcribe') {\n showError(t('media.generateNeedPrompt'));\n return;\n }\n const apiKeyId = document.getElementById('mg-key')?.value || '';\n const model = document.getElementById('mg-model')?.value || undefined;\n const format = document.getElementById('mg-format')?.value || undefined;\n const aspect = document.getElementById('mg-aspect')?.value || '1:1';\n const n = Math.min(\n 4,\n Math.max(1, Number(document.getElementById('mg-n')?.value) || 1),\n );\n const btn = document.getElementById('mg-submit');\n const st = document.getElementById('mg-status');\n const busyLabel =\n mediaMode === 'video'\n ? t('media.videoBusy')\n : mediaMode === 'edit'\n ? t('media.editBusy')\n : mediaMode === 'speech'\n ? t('media.speechBusy')\n : mediaMode === 'transcribe'\n ? t('media.transcribeBusy')\n : t('media.generateBusy');\n if (btn) {\n btn.disabled = true;\n btn.textContent = busyLabel;\n }\n if (st) {\n st.hidden = false;\n st.textContent = busyLabel;\n }\n showError('');\n try {\n if (mediaMode === 'edit') {\n if (!mediaSource) {\n throw new Error(t('media.editNeedImage'));\n }\n const fd = new FormData();\n fd.append('prompt', prompt);\n fd.append('aspect_ratio', aspect);\n fd.append('n', String(n));\n fd.append('response_format', 'url');\n if (model) fd.append('model', model);\n if (apiKeyId) fd.append('apiKeyId', apiKeyId);\n if (mediaSource.kind === 'file' && mediaSource.file) {\n fd.append('image', mediaSource.file);\n } else if (mediaSource.kind === 'asset' && mediaSource.id) {\n fd.append('sourceAssetId', mediaSource.id);\n } else if (mediaSource.kind === 'document' && mediaSource.id) {\n fd.append('sourceDocumentId', mediaSource.id);\n }\n await parseApiResponse(\n await fetch('/admin/api/media/edit', {\n method: 'POST',\n headers: { Authorization: `Bearer ${state.key}` },\n body: fd,\n }),\n );\n if (st) st.textContent = t('media.editOk');\n state.mediaFilter.tab = 'assets';\n state.mediaFilter.offset = 0;\n await renderMedia();\n return;\n }\n\n if (mediaMode === 'speech') {\n if (!prompt) {\n throw new Error(t('media.generateNeedPrompt'));\n }\n const res = await api('/media/speech', {\n method: 'POST',\n body: JSON.stringify({\n input: prompt,\n ...(model ? { model } : {}),\n ...(apiKeyId ? { apiKeyId } : {}),\n ...(format ? { format } : {}),\n }),\n });\n const id = res?.data?.asset_id;\n if (st) st.textContent = t('media.speechOk');\n state.mediaFilter.tab = 'assets';\n state.mediaFilter.offset = 0;\n await renderMedia();\n if (id) {\n try {\n const blob = await fetchMediaBlob(id);\n openMediaPreviewLightbox(\n {\n id,\n mime: blob.type || 'audio/wav',\n filename: `speech-${String(id).slice(0, 8)}.wav`,\n kind: 'audio',\n bytes: blob.size,\n prompt,\n },\n blob,\n );\n } catch {\n /* ignore */\n }\n }\n return;\n }\n\n if (mediaMode === 'transcribe') {\n if (!mediaSource) {\n throw new Error(t('media.transcribeNeedAudio'));\n }\n const fd = new FormData();\n if (apiKeyId) fd.append('apiKeyId', apiKeyId);\n if (format) fd.append('format', format);\n if (mediaSource.kind === 'file' && mediaSource.file) {\n fd.append('file', mediaSource.file);\n } else if (mediaSource.kind === 'asset' && mediaSource.id) {\n fd.append('sourceAssetId', mediaSource.id);\n } else if (mediaSource.kind === 'document' && mediaSource.id) {\n fd.append('sourceDocumentId', mediaSource.id);\n }\n const res = await parseApiResponse(\n await fetch('/admin/api/media/transcribe', {\n method: 'POST',\n headers: { Authorization: `Bearer ${state.key}` },\n body: fd,\n }),\n );\n const id = res?.data?.asset_id;\n const text = res?.data?.text || '';\n if (st) {\n st.textContent = text\n ? `${t('media.transcribeOk')} ${text.slice(0, 120)}`\n : t('media.transcribeOk');\n }\n state.mediaFilter.tab = 'assets';\n state.mediaFilter.offset = 0;\n await renderMedia();\n if (id) {\n try {\n const blob = await fetchMediaBlob(id);\n openMediaPreviewLightbox(\n {\n id,\n mime: 'text/plain',\n filename: `transcript-${String(id).slice(0, 8)}.txt`,\n kind: 'file',\n bytes: blob.size,\n prompt: text.slice(0, 200),\n },\n blob,\n );\n } catch {\n /* ignore */\n }\n }\n return;\n }\n\n if (mediaMode === 'video') {\n const fd = new FormData();\n fd.append('prompt', prompt);\n fd.append('aspect_ratio', aspect);\n fd.append(\n 'seconds',\n String(document.getElementById('mg-duration')?.value || 6),\n );\n if (model) fd.append('model', model);\n if (apiKeyId) fd.append('apiKeyId', apiKeyId);\n if (format) fd.append('format', format);\n const voice = document.getElementById('mg-voice')?.value || '';\n if (voice) fd.append('voices', voice);\n if (mediaSource?.kind === 'file' && mediaSource.file) {\n fd.append('image', mediaSource.file);\n } else if (mediaSource?.kind === 'asset' && mediaSource.id) {\n fd.append('source_asset_id', mediaSource.id);\n } else if (mediaSource?.kind === 'document' && mediaSource.id) {\n fd.append('source_document_id', mediaSource.id);\n }\n await parseApiResponse(\n await fetch('/admin/api/media/videos', {\n method: 'POST',\n headers: { Authorization: `Bearer ${state.key}` },\n body: fd,\n }),\n );\n if (st) st.textContent = t('media.videoOk');\n state.mediaFilter.tab = 'jobs';\n await renderMedia();\n return;\n }\n\n const body = {\n prompt,\n aspect_ratio: aspect,\n n,\n response_format: 'url',\n };\n if (model) body.model = model;\n if (apiKeyId) body.apiKeyId = apiKeyId;\n if (format) body.format = format;\n const res = await api('/media/generate', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const ids = res?.data?.omni?.asset_ids || [];\n if (st) st.textContent = t('media.generateOk');\n state.mediaFilter.tab = 'assets';\n state.mediaFilter.offset = 0;\n await renderMedia();\n if (ids[0]) {\n try {\n const blob = await fetchMediaBlob(ids[0]);\n openMediaPreviewLightbox(\n {\n id: ids[0],\n mime: blob.type || 'image/png',\n filename: `generated-${String(ids[0]).slice(0, 8)}`,\n kind: 'image',\n bytes: blob.size,\n prompt,\n },\n blob,\n );\n } catch {\n /* ignore */\n }\n }\n } catch (e) {\n onErr(e);\n if (st) st.textContent = e.message || t('media.generateFail');\n if (btn) {\n btn.disabled = false;\n setMediaMode(mediaMode);\n }\n }\n });\n }\n\n if (tab === 'assets' || tab === 'jobs') {\n bindSortHeaders(state.mediaFilter, () => renderMedia().catch(onErr));\n }\n if (tab === 'assets') {\n bindPager('media', state.mediaFilter, () => renderMedia().catch(onErr));\n\n document\n .querySelector('#media-tab-assets [data-filter-apply]')\n ?.addEventListener('click', () => {\n state.mediaFilter.q =\n document.getElementById('mf-q')?.value.trim() || '';\n state.mediaFilter.kind =\n document.getElementById('mf-kind')?.value || '';\n state.mediaFilter.provider =\n document.getElementById('mf-provider')?.value.trim() || '';\n state.mediaFilter.from =\n document.getElementById('mf-from')?.value || '';\n state.mediaFilter.to = document.getElementById('mf-to')?.value || '';\n state.mediaFilter.offset = 0;\n renderMedia().catch(onErr);\n });\n document\n .querySelector('#media-tab-assets [data-filter-reset]')\n ?.addEventListener('click', () => {\n const keepTab = state.mediaFilter.tab;\n state.mediaFilter = {\n tab: keepTab,\n q: '',\n kind: '',\n provider: '',\n from: '',\n to: '',\n sortBy: 'createdAt',\n sortDir: 'desc',\n jobSortBy: 'createdAt',\n jobSortDir: 'desc',\n limit: 20,\n offset: 0,\n };\n renderMedia().catch(onErr);\n });\n\n document.querySelectorAll('[data-media-preview]').forEach((btn) => {\n btn.addEventListener('click', async () => {\n try {\n const id = btn.getAttribute('data-media-preview');\n if (!id) return;\n const mime = btn.getAttribute('data-media-mime') || '';\n const filename = btn.getAttribute('data-media-name') || '';\n const kind = btn.getAttribute('data-media-kind') || '';\n const bytesRaw = btn.getAttribute('data-media-bytes') || '';\n const prompt = btn.getAttribute('data-media-prompt') || '';\n const blob = await fetchMediaBlob(id);\n // Prefer server mime; fall back to blob.type\n openMediaPreviewLightbox(\n {\n id,\n mime: mime || blob.type || '',\n filename,\n kind,\n bytes: bytesRaw ? Number(bytesRaw) : blob.size,\n prompt,\n },\n blob,\n );\n } catch (e) {\n onErr(e);\n }\n });\n });\n\n document.querySelectorAll('[data-media-dl]').forEach((btn) => {\n btn.addEventListener('click', async () => {\n try {\n const id = btn.getAttribute('data-media-dl');\n const name = btn.getAttribute('data-media-name') || '';\n const blob = await fetchMediaBlob(id);\n const a = document.createElement('a');\n a.href = URL.createObjectURL(blob);\n a.download = name || `media-${String(id).slice(0, 8)}`;\n a.click();\n setTimeout(() => URL.revokeObjectURL(a.href), 30_000);\n } catch (e) {\n onErr(e);\n }\n });\n });\n\n document.querySelectorAll('[data-media-del]').forEach((btn) => {\n btn.addEventListener('click', async () => {\n const id = btn.getAttribute('data-media-del');\n if (\n !(await uiConfirm({\n message: t('media.deleteConfirm'),\n variant: 'danger',\n confirmText: t('media.delete'),\n }))\n )\n return;\n try {\n await api(`/media/assets/${id}`, { method: 'DELETE' });\n await renderMedia();\n } catch (e) {\n onErr(e);\n }\n });\n });\n }\n}\n\n/**\n * Pick a source image from Documents library or Media assets (admin-wide).\n * @param {{ imagesOnly?: boolean, audioOnly?: boolean, onPick: (item: { kind: 'asset'|'document', id: string, name: string, mime: string }) => void }} opts\n */\nasync function openMediaSourceLibraryPicker(opts) {\n const audioOnly = Boolean(opts.audioOnly);\n const imagesOnly = !audioOnly && opts.imagesOnly !== false;\n let libTab = 'documents'; // 'documents' | 'assets'\n let loadSeq = 0;\n /** @type {{ kind: 'asset'|'document', id: string, name: string, mime: string } | null} */\n let selected = null;\n\n openAppModal({\n title: t('media.libraryTitle'),\n subtitle: escapeHtml(t('media.librarySubtitle')),\n size: 'md',\n bodyHtml: `\n <div class=\"chat-lib media-lib\">\n <div class=\"seg-tabs\" role=\"tablist\" style=\"margin-bottom:0.75rem\">\n <button type=\"button\" class=\"seg-tab is-active\" data-mlib-tab=\"documents\">${escapeHtml(t('media.libraryTabDocs'))}</button>\n <button type=\"button\" class=\"seg-tab\" data-mlib-tab=\"assets\">${escapeHtml(t('media.libraryTabAssets'))}</button>\n </div>\n <div class=\"chat-lib-toolbar\">\n <input type=\"search\" id=\"mlib-q\" class=\"chat-lib-search\" placeholder=\"${escapeHtml(t('media.librarySearch'))}\" autocomplete=\"off\" />\n <span class=\"muted chat-lib-count\" id=\"mlib-count\"></span>\n </div>\n <div class=\"muted chat-lib-formats\">${escapeHtml(audioOnly ? t('media.libraryFormatsAudio') : t('media.libraryFormats'))}</div>\n <div id=\"mlib-list\" class=\"chat-lib-list\" role=\"listbox\">\n <div class=\"muted chat-lib-status\">${escapeHtml(t('common.loading') || '…')}</div>\n </div>\n </div>`,\n footerHtml: `\n <button type=\"button\" class=\"btn secondary sm\" id=\"mlib-cancel\">${escapeHtml(t('common.cancel'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"mlib-add\" disabled>${escapeHtml(t('media.librarySelect'))}</button>`,\n });\n\n const listEl = document.getElementById('mlib-list');\n const qEl = document.getElementById('mlib-q');\n const addBtn = document.getElementById('mlib-add');\n document.getElementById('mlib-cancel')?.addEventListener('click', () => closeAppModal());\n\n const paintSelection = () => {\n if (addBtn) {\n addBtn.disabled = !selected;\n addBtn.textContent = selected\n ? `${t('media.librarySelect')} · ${selected.name.slice(0, 24)}`\n : t('media.librarySelect');\n }\n };\n\n const isImageMime = (m) => String(m || '').startsWith('image/');\n const isImageName = (n) =>\n /\\.(png|jpe?g|webp|gif|bmp|svg)$/i.test(String(n || ''));\n const isAudioMime = (m) => String(m || '').startsWith('audio/');\n const isAudioName = (n) =>\n /\\.(wav|mp3|m4a|aac|ogg|oga|flac|opus|webm)$/i.test(String(n || ''));\n const passMime = (mime, name) => {\n if (audioOnly) return isAudioMime(mime) || isAudioName(name);\n if (imagesOnly) return isImageMime(mime) || isImageName(name);\n return true;\n };\n\n const renderRows = (items) => {\n if (!listEl) return;\n if (!items.length) {\n listEl.innerHTML = `<div class=\"data-empty chat-lib-empty\"><strong>${escapeHtml(t('media.libraryEmpty'))}</strong></div>`;\n return;\n }\n listEl.innerHTML = items\n .map((it) => {\n const checked = selected?.id === it.id && selected?.kind === it.kind;\n return `\n <label class=\"chat-lib-row ${checked ? 'is-selected' : ''}\" data-kind=\"${escapeHtml(it.kind)}\" data-id=\"${escapeHtml(it.id)}\">\n <input type=\"radio\" name=\"mlib-pick\" ${checked ? 'checked' : ''} />\n <span class=\"chat-lib-meta\">\n <span class=\"chat-lib-name\" title=\"${escapeHtml(it.name)}\">${escapeHtml(it.name)}</span>\n <span class=\"muted\">${escapeHtml(it.kindLabel)} · ${escapeHtml(it.mime || '—')}${it.size != null ? ` · ${fmtBytes(it.size)}` : ''}</span>\n </span>\n </label>`;\n })\n .join('');\n\n listEl.querySelectorAll('.chat-lib-row').forEach((row) => {\n row.addEventListener('click', () => {\n const kind = row.getAttribute('data-kind');\n const id = row.getAttribute('data-id');\n const it = items.find((x) => x.id === id && x.kind === kind);\n if (!it) return;\n selected = {\n kind: it.kind,\n id: it.id,\n name: it.name,\n mime: it.mime,\n };\n listEl.querySelectorAll('.chat-lib-row').forEach((r) => {\n r.classList.toggle(\n 'is-selected',\n r.getAttribute('data-id') === id &&\n r.getAttribute('data-kind') === kind,\n );\n const inp = r.querySelector('input');\n if (inp) {\n inp.checked =\n r.getAttribute('data-id') === id &&\n r.getAttribute('data-kind') === kind;\n }\n });\n paintSelection();\n });\n });\n };\n\n const load = async () => {\n const seq = ++loadSeq;\n if (listEl) {\n listEl.innerHTML = `<div class=\"muted chat-lib-status\">${escapeHtml(t('common.loading') || '…')}</div>`;\n }\n try {\n const q = (qEl?.value || '').trim();\n let items = [];\n if (libTab === 'assets') {\n const params = new URLSearchParams({ limit: '80', offset: '0' });\n if (q) params.set('q', q);\n if (imagesOnly) params.set('kind', 'image');\n if (audioOnly) params.set('kind', 'audio');\n const res = await api(`/media/assets?${params}`);\n items = (res.data || [])\n .filter((a) => passMime(a.mime, a.filename))\n .map((a) => ({\n kind: 'asset',\n kindLabel: t('media.sourceKindAsset'),\n id: a.id,\n name: a.filename || a.prompt || a.id,\n mime: a.mime || '',\n size: a.bytes,\n }));\n } else {\n const params = new URLSearchParams({ limit: '80', offset: '0' });\n if (q) params.set('q', q);\n const res = await api(`/documents?${params}`);\n items = (res.data || [])\n .filter((d) => passMime(d.mimeType, d.originalName))\n .map((d) => ({\n kind: 'document',\n kindLabel: t('media.sourceKindDocument'),\n id: d.id,\n name: d.originalName || d.id,\n mime: d.mimeType || '',\n size: d.sizeBytes,\n }));\n }\n if (seq !== loadSeq) return;\n renderRows(items);\n } catch (e) {\n if (seq !== loadSeq) return;\n if (listEl) {\n listEl.innerHTML = `<div class=\"error-box\">${escapeHtml(e.message || t('media.libraryLoadFail'))}</div>`;\n }\n }\n };\n\n document.querySelectorAll('[data-mlib-tab]').forEach((btn) => {\n btn.addEventListener('click', () => {\n libTab =\n btn.getAttribute('data-mlib-tab') === 'assets' ? 'assets' : 'documents';\n document.querySelectorAll('[data-mlib-tab]').forEach((b) => {\n b.classList.toggle(\n 'is-active',\n b.getAttribute('data-mlib-tab') === libTab,\n );\n });\n selected = null;\n paintSelection();\n load();\n });\n });\n\n let searchTimer = null;\n qEl?.addEventListener('input', () => {\n if (searchTimer) clearTimeout(searchTimer);\n searchTimer = setTimeout(() => load(), 280);\n });\n\n addBtn?.addEventListener('click', () => {\n if (!selected) return;\n opts.onPick(selected);\n closeAppModal();\n });\n\n paintSelection();\n await load();\n}\n\nasync function renderUsage() {\n const uf = state.usageFilter;\n if (!uf.sortBy) uf.sortBy = 'lastUsedAt';\n if (!uf.sortDir) uf.sortDir = 'desc';\n if (!uf.modelSortBy) uf.modelSortBy = 'requests';\n if (!uf.modelSortDir) uf.modelSortDir = 'desc';\n const uq = new URLSearchParams();\n appendSortParams(uq, uf);\n if (uf.modelSortBy) uq.set('modelSortBy', uf.modelSortBy);\n if (uf.modelSortDir === 'asc' || uf.modelSortDir === 'desc') {\n uq.set('modelSortDir', uf.modelSortDir);\n }\n const { data } = await api(`/usage?${uq}`);\n const tot = data.totals || {};\n const limits = data.limits || {};\n const ps = uf.pageSize || 10;\n\n let models = data.byModel || [];\n if (uf.modelQ.trim()) {\n const qq = uf.modelQ.trim().toLowerCase();\n models = models.filter((m) => String(m.model || '').toLowerCase().includes(qq));\n }\n const modelTotal = models.length;\n const modelSlice = models.slice(uf.modelPage * ps, uf.modelPage * ps + ps);\n const modelRows = modelSlice\n .map(\n (m) =>\n `<tr><td class=\"cell-primary\">${escapeHtml(m.model)}</td><td>${m.requests}</td></tr>`,\n )\n .join('');\n\n let keys = data.perKey || [];\n if (uf.keyQ.trim()) {\n const qq = uf.keyQ.trim().toLowerCase();\n keys = keys.filter(\n (k) =>\n String(k.name || '').toLowerCase().includes(qq) ||\n String(k.keyPrefix || '').toLowerCase().includes(qq),\n );\n }\n if (uf.keyActive === 'true') keys = keys.filter((k) => k.isActive);\n if (uf.keyActive === 'false') keys = keys.filter((k) => !k.isActive);\n const keyTotal = keys.length;\n const keySlice = keys.slice(uf.keyPage * ps, uf.keyPage * ps + ps);\n const keyRows = keySlice\n .map((k) => {\n const util = Math.round((k.utilization || 0) * 100);\n return `<tr>\n <td><div class=\"cell-primary\">${escapeHtml(k.name)}</div><div class=\"cell-sub\">${escapeHtml(k.keyPrefix)}</div></td>\n <td>${k.requests}</td>\n <td>${fmtPerMin(k.rateLimit)}</td>\n <td>\n <div>${tf('common.percent', { n: util })}</div>\n <div class=\"usage-bar ${util > 80 ? 'warn' : ''}\"><span style=\"width:${util}%\"></span></div>\n </td>\n <td>${k.isActive ? `<span class=\"badge success\">${escapeHtml(t('common.active'))}</span>` : `<span class=\"badge error\">${escapeHtml(t('common.revoked'))}</span>`}</td>\n <td class=\"muted\">${k.lastUsedAt ? fmtTime(k.lastUsedAt) : '—'}</td>\n </tr>`;\n })\n .join('');\n\n const modelPager = pagerHtml({\n total: modelTotal,\n limit: ps,\n offset: uf.modelPage * ps,\n idPrefix: 'umodel',\n });\n const keyPager = pagerHtml({\n total: keyTotal,\n limit: ps,\n offset: uf.keyPage * ps,\n idPrefix: 'ukey',\n });\n\n const tab = uf.tab === 'key' ? 'key' : 'model';\n const modelFilter = filterPanelHtml({\n title: t('usage.byModel'),\n hint: t('common.filterHint'),\n searchHtml: `<div class=\"data-filter-search\"><label>${escapeHtml(t('common.search'))}<input type=\"search\" id=\"uf-model\" value=\"${escapeHtml(uf.modelQ)}\" placeholder=\"${escapeHtml(t('chats.model'))}\" /></label></div>`,\n gridHtml: '',\n });\n const modelTable = dataTablePanelHtml({\n headHtml: `\n ${sortThHtml({ field: 'model', label: t('chats.model'), filterRef: uf, sortByKey: 'modelSortBy', sortDirKey: 'modelSortDir' })}\n ${sortThHtml({ field: 'requests', label: t('usage.requests'), filterRef: uf, sortByKey: 'modelSortBy', sortDirKey: 'modelSortDir' })}`,\n bodyHtml: modelRows,\n colSpan: 2,\n emptyText: t('common.empty'),\n pagerHtml: modelPager,\n });\n const keyFilter = filterPanelHtml({\n title: t('usage.byKey'),\n hint: t('common.filterHint'),\n searchHtml: `<div class=\"data-filter-search\"><label>${escapeHtml(t('common.search'))}<input type=\"search\" id=\"uf-key\" value=\"${escapeHtml(uf.keyQ)}\" placeholder=\"${escapeHtml(t('keys.name'))}\" /></label></div>`,\n gridHtml: `<label>${escapeHtml(t('keys.status'))}\n <select id=\"uf-active\">\n <option value=\"\">${escapeHtml(t('common.all'))}</option>\n <option value=\"true\" ${uf.keyActive === 'true' ? 'selected' : ''}>${escapeHtml(t('common.active'))}</option>\n <option value=\"false\" ${uf.keyActive === 'false' ? 'selected' : ''}>${escapeHtml(t('common.revoked'))}</option>\n </select>\n </label>`,\n });\n const keyTable = dataTablePanelHtml({\n headHtml: `\n ${sortThHtml({ field: 'name', label: t('keys.name'), filterRef: uf })}\n ${sortThHtml({ field: 'requests', label: t('usage.requests'), filterRef: uf })}\n ${sortThHtml({ field: 'rateLimit', label: t('usage.rateLimit'), filterRef: uf })}\n ${sortThHtml({ field: 'utilization', label: t('usage.util'), filterRef: uf })}\n ${sortThHtml({ field: 'isActive', label: t('keys.status'), filterRef: uf })}\n ${sortThHtml({ field: 'lastUsedAt', label: t('usage.lastUsed') || t('media.created'), filterRef: uf })}`,\n bodyHtml: keyRows,\n colSpan: 6,\n emptyText: t('common.empty'),\n pagerHtml: keyPager,\n });\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('usage.title'))}</h2>\n <button class=\"btn secondary sm\" id=\"btn-usage-refresh\">${escapeHtml(t('usage.refresh'))}</button>\n </div>\n ${pageMetaHtml([\n `${t('usage.window')}: ${fmtTime(data.from)} → ${fmtTime(data.to)} (${tf('common.minutes', { n: data.windowMinutes })})`,\n ])}\n <div class=\"grid\">\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.requests'))}</div><div class=\"value\">${tot.requests ?? 0}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.success'))}</div><div class=\"value\">${tot.success ?? 0}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.errors'))}</div><div class=\"value\">${tot.errors ?? 0}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.errorRate'))}</div><div class=\"value\">${Math.round((tot.errorRate || 0) * 100)}%</div></div>\n </div>\n <div class=\"panel data-table-panel\" style=\"margin-bottom:14px\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('usage.limits'))}</strong></div>\n <div class=\"panel-pad\">\n <div class=\"grid\">\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.global'))}</div><div class=\"value value-sm\">${limits.globalMax} / ${limits.globalWindowMs}ms</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.ipMax'))}</div><div class=\"value value-sm\">${limits.ipMax}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.burst'))}</div><div class=\"value value-sm\">${limits.chatBurstMax}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.block'))}</div><div class=\"value value-sm\">${limits.blockFailedAuthThreshold}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('usage.concurrent'))}</div><div class=\"value value-sm\">${limits.engineMaxConcurrent}</div></div>\n </div>\n </div>\n </div>\n\n <div class=\"usage-tabs-panel panel\">\n <div class=\"seg-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('usage.title'))}\">\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'model' ? 'is-active' : ''}\" data-usage-tab=\"model\" aria-selected=\"${tab === 'model'}\">\n ${escapeHtml(t('usage.byModel'))}\n <span class=\"seg-tab-count\">${modelTotal}</span>\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'key' ? 'is-active' : ''}\" data-usage-tab=\"key\" aria-selected=\"${tab === 'key'}\">\n ${escapeHtml(t('usage.byKey'))}\n <span class=\"seg-tab-count\">${keyTotal}</span>\n </button>\n </div>\n <div class=\"usage-tab-body\">\n <div class=\"usage-tab-pane\" id=\"usage-tab-model\" ${tab === 'model' ? '' : 'hidden'}>\n ${modelFilter}\n ${modelTable}\n </div>\n <div class=\"usage-tab-pane\" id=\"usage-tab-key\" ${tab === 'key' ? '' : 'hidden'}>\n ${keyFilter}\n ${keyTable}\n </div>\n </div>\n </div>\n `);\n bindShell();\n bindSortHeaders(state.usageFilter, () => renderUsage().catch(onErr));\n document.getElementById('btn-usage-refresh').onclick = () =>\n renderUsage().catch(onErr);\n\n document.querySelectorAll('[data-usage-tab]').forEach((btn) => {\n btn.onclick = () => {\n const next = btn.dataset.usageTab === 'key' ? 'key' : 'model';\n if (state.usageFilter.tab === next) return;\n state.usageFilter.tab = next;\n renderUsage().catch(onErr);\n };\n });\n\n // Model pager (client-side pages)\n document.getElementById('umodel-prev')?.addEventListener('click', () => {\n state.usageFilter.modelPage = Math.max(0, uf.modelPage - 1);\n renderUsage().catch(onErr);\n });\n document.getElementById('umodel-next')?.addEventListener('click', () => {\n if ((uf.modelPage + 1) * ps < modelTotal) {\n state.usageFilter.modelPage += 1;\n renderUsage().catch(onErr);\n }\n });\n document.getElementById('umodel-limit')?.addEventListener('change', (e) => {\n state.usageFilter.pageSize = Number(e.target.value) || 10;\n state.usageFilter.modelPage = 0;\n renderUsage().catch(onErr);\n });\n document.getElementById('ukey-prev')?.addEventListener('click', () => {\n state.usageFilter.keyPage = Math.max(0, uf.keyPage - 1);\n renderUsage().catch(onErr);\n });\n document.getElementById('ukey-next')?.addEventListener('click', () => {\n if ((uf.keyPage + 1) * ps < keyTotal) {\n state.usageFilter.keyPage += 1;\n renderUsage().catch(onErr);\n }\n });\n document.getElementById('ukey-limit')?.addEventListener('change', (e) => {\n state.usageFilter.pageSize = Number(e.target.value) || 10;\n state.usageFilter.keyPage = 0;\n renderUsage().catch(onErr);\n });\n\n // Filters only affect the active tab's pane\n document.querySelectorAll('#usage-tab-model [data-filter-apply]').forEach((btn) => {\n btn.onclick = () => {\n state.usageFilter.modelQ = document.getElementById('uf-model')?.value?.trim() || '';\n state.usageFilter.modelPage = 0;\n renderUsage().catch(onErr);\n };\n });\n document.querySelectorAll('#usage-tab-model [data-filter-reset]').forEach((btn) => {\n btn.onclick = () => {\n state.usageFilter.modelQ = '';\n state.usageFilter.modelPage = 0;\n renderUsage().catch(onErr);\n };\n });\n document.querySelectorAll('#usage-tab-key [data-filter-apply]').forEach((btn) => {\n btn.onclick = () => {\n state.usageFilter.keyQ = document.getElementById('uf-key')?.value?.trim() || '';\n state.usageFilter.keyActive = document.getElementById('uf-active')?.value || '';\n state.usageFilter.keyPage = 0;\n renderUsage().catch(onErr);\n };\n });\n document.querySelectorAll('#usage-tab-key [data-filter-reset]').forEach((btn) => {\n btn.onclick = () => {\n state.usageFilter.keyQ = '';\n state.usageFilter.keyActive = '';\n state.usageFilter.keyPage = 0;\n renderUsage().catch(onErr);\n };\n });\n}\n\nfunction versionStatusMeta(v) {\n const status =\n v.versionStatus ||\n (v.updateAvailable ? 'update_available' : v.latest ? 'up_to_date' : 'unknown');\n if (status === 'update_available') {\n return {\n badge: `<span class=\"badge warn\" title=\"${escapeHtml(t('system.statusHintUpdate'))}\">${escapeHtml(t('system.badgeUpdate'))}</span>`,\n hint: t('system.statusHintUpdate'),\n };\n }\n if (status === 'ahead') {\n return {\n badge: `<span class=\"badge pending\" title=\"${escapeHtml(t('system.statusHintAhead'))}\">${escapeHtml(t('system.badgeAhead'))}</span>`,\n hint: t('system.statusHintAhead'),\n };\n }\n if (status === 'up_to_date') {\n return {\n badge: `<span class=\"badge success\" title=\"${escapeHtml(t('system.statusHintOk'))}\">${escapeHtml(t('system.badgeOk'))}</span>`,\n hint: t('system.statusHintOk'),\n };\n }\n return {\n badge: `<span class=\"badge pending\" title=\"${escapeHtml(t('system.statusHintUnknown'))}\">${escapeHtml(t('system.badgeUnknown'))}</span>`,\n hint: t('system.statusHintUnknown'),\n };\n}\n\nfunction channelLabel(channel) {\n if (channel === 'git') return t('system.channelGit');\n if (channel === 'npm-global') return t('system.channelNpmGlobal');\n if (channel === 'npm-local') return t('system.channelNpmLocal');\n return t('system.channelUnknown');\n}\n\nfunction softwareLevelLabel(level) {\n if (level === 'required') return t('system.levelRequired');\n if (level === 'recommended') return t('system.levelRecommended');\n if (level === 'optional') return t('system.levelOptional');\n if (level === 'bundled') return t('system.levelBundled');\n return level || '—';\n}\n\nfunction softwareStatusBadge(c) {\n if (!c.installed) {\n return c.level === 'required' || c.level === 'bundled'\n ? `<span class=\"badge error\">${escapeHtml(t('system.softMissing'))}</span>`\n : `<span class=\"badge pending\">${escapeHtml(t('system.softMissing'))}</span>`;\n }\n if (!c.ok) {\n return `<span class=\"badge warn\">${escapeHtml(t('system.softWarn'))}</span>`;\n }\n return `<span class=\"badge success\">${escapeHtml(t('system.softOk'))}</span>`;\n}\n\nfunction runtimeBadge(state) {\n if (state === 'up') return `<span class=\"badge success\">${escapeHtml(t('system.up'))}</span>`;\n return `<span class=\"badge error\">${escapeHtml(t('system.down'))}</span>`;\n}\n\nasync function renderSystem() {\n const { data } = await api('/system');\n if (state.page !== 'system') return;\n\n const v = data.version || {};\n const vs = versionStatusMeta(v);\n const soft = data.software || { checks: [], allRequiredOk: true };\n const checks = soft.checks || [];\n const tab =\n state.systemTab === 'package' || state.systemTab === 'env'\n ? state.systemTab\n : 'software';\n state.systemTab = tab;\n\n const softBody = checks\n .map(\n (c) => `\n <tr>\n <td><div class=\"cell-primary\">${escapeHtml(c.name || c.id)}</div>${c.requiredVersion ? `<div class=\"cell-sub\">${escapeHtml(c.requiredVersion)}</div>` : ''}</td>\n <td>${escapeHtml(softwareLevelLabel(c.level))}</td>\n <td>${escapeHtml(c.installed ? t('system.yes') : t('system.no'))}${c.path ? `<div class=\"cell-sub soft-path\">${escapeHtml(c.path)}</div>` : ''}</td>\n <td><code class=\"cell-code\">${escapeHtml(c.version || '—')}</code></td>\n <td>${softwareStatusBadge(c)}</td>\n <td class=\"muted\">${escapeHtml(c.detail || '')}</td>\n </tr>`,\n )\n .join('');\n\n const softSummary = soft.allRequiredOk\n ? `<span class=\"badge success\">${escapeHtml(t('system.allRequiredOk'))}</span>`\n : `<span class=\"badge error\">${escapeHtml(t('system.requiredMissing'))}</span>`;\n\n const encReady = data.encryption && data.encryption.ready;\n const channelText = channelLabel(v.channel);\n const installText = v.installSource\n ? `${channelText} · ${v.installSource}`\n : channelText;\n\n const softTable = dataTablePanelHtml({\n headHtml: `\n <th>${escapeHtml(t('system.softName'))}</th>\n <th>${escapeHtml(t('system.softLevel'))}</th>\n <th>${escapeHtml(t('system.softInstalled'))}</th>\n <th>${escapeHtml(t('system.softVersion'))}</th>\n <th>${escapeHtml(t('system.softStatus'))}</th>\n <th>${escapeHtml(t('system.softDetail'))}</th>`,\n bodyHtml: softBody,\n colSpan: 6,\n emptyText: t('common.empty'),\n });\n\n // KPI strip — same pattern as queue / media\n const kpiGrid = `\n <div class=\"grid system-kpi-grid\" id=\"system-kpi-grid\">\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('system.database'))}</div>\n <div class=\"value value-sm\">${runtimeBadge(data.database)}</div>\n <div class=\"muted card-sub\">${escapeHtml(t('system.runtime'))}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('system.textEngine'))}</div>\n <div class=\"value value-sm\">${runtimeBadge(data.textEngine)}</div>\n <div class=\"muted card-sub\">llama-server</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('system.concurrency'))}</div>\n <div class=\"value value-sm\">${data.concurrency?.active ?? 0}<span class=\"dash-kpi-den\">/${data.concurrency?.max ?? '—'}</span></div>\n <div class=\"muted card-sub\">${escapeHtml(t('system.concurrency'))}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('system.encryption'))}</div>\n <div class=\"value value-sm\">${\n encReady\n ? `<span class=\"badge success\">${escapeHtml(t('system.ready'))}</span>`\n : `<span class=\"badge error\">${escapeHtml(t('system.notReady'))}</span>`\n }</div>\n <div class=\"muted card-sub\">${escapeHtml(t('system.runtime'))}</div>\n </div>\n </div>`;\n\n const softwarePane = `\n <div class=\"system-tab-toolbar\">\n <span class=\"muted\">${escapeHtml(t('system.softwareHint'))}</span>\n ${softSummary}\n </div>\n ${softTable}`;\n\n const packagePane = `\n <div class=\"panel data-table-panel system-package-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('system.selfUpdate'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(vs.hint)}</span>\n </div>\n ${vs.badge}\n </div>\n <div class=\"panel-pad\">\n <div class=\"grid\">\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('system.current'))}</div><div class=\"value value-sm\">${escapeHtml(v.current || '-')} ${vs.badge}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('system.npm'))}</div><div class=\"value value-sm\">${escapeHtml(v.latestNpm || 'n/a')}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('system.github'))}</div><div class=\"value value-sm\">${escapeHtml(v.latestGithub || 'n/a')}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('system.install'))}</div><div class=\"value value-sm\">${escapeHtml(installText)}</div></div>\n </div>\n <pre id=\"update-log\" class=\"pre\" style=\"display:none;margin-top:12px\"></pre>\n </div>\n </div>`;\n\n const envPane = `\n <div class=\"panel data-table-panel system-env-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('system.envTitle'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('system.envHint'))}</span>\n </div>\n </div>\n <div class=\"panel-pad\">\n <pre class=\"pre system-env-pre\">${escapeHtml(JSON.stringify({ env: data.env, version: v }, null, 2))}</pre>\n </div>\n </div>`;\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('system.title'))}</h2>\n <div class=\"toolbar\">\n <button class=\"btn secondary sm\" id=\"btn-check-update\" title=\"${escapeHtml(t('system.selfHint'))}\">${escapeHtml(t('system.checkUpdate'))}</button>\n <button class=\"btn sm\" id=\"btn-one-click-update\" title=\"${escapeHtml(t('system.confirmUpdate'))}\">${escapeHtml(t('system.oneClick'))}</button>\n </div>\n </div>\n ${pageMetaHtml([t('system.selfHint')])}\n ${kpiGrid}\n\n <div class=\"usage-tabs-panel panel system-tabs-panel\">\n <div class=\"seg-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('system.title'))}\">\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'software' ? 'is-active' : ''}\" data-system-tab=\"software\" aria-selected=\"${tab === 'software'}\">\n ${escapeHtml(t('system.tabSoftware'))}\n <span class=\"seg-tab-count\">${checks.length}</span>\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'package' ? 'is-active' : ''}\" data-system-tab=\"package\" aria-selected=\"${tab === 'package'}\">\n ${escapeHtml(t('system.tabPackage'))}\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'env' ? 'is-active' : ''}\" data-system-tab=\"env\" aria-selected=\"${tab === 'env'}\">\n ${escapeHtml(t('system.tabEnv'))}\n </button>\n </div>\n <div class=\"usage-tab-body\">\n <div class=\"usage-tab-pane system-tab-pane-software\" id=\"system-tab-software\" ${tab === 'software' ? '' : 'hidden'}>\n ${softwarePane}\n </div>\n <div class=\"usage-tab-pane system-tab-pane-package\" id=\"system-tab-package\" ${tab === 'package' ? '' : 'hidden'}>\n ${packagePane}\n </div>\n <div class=\"usage-tab-pane system-tab-pane-env\" id=\"system-tab-env\" ${tab === 'env' ? '' : 'hidden'}>\n ${envPane}\n </div>\n </div>\n </div>\n `);\n bindShell();\n\n document.querySelectorAll('[data-system-tab]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const raw = btn.getAttribute('data-system-tab') || 'software';\n const next =\n raw === 'package' || raw === 'env' || raw === 'software'\n ? raw\n : 'software';\n if (state.systemTab === next) return;\n state.systemTab = next;\n renderSystem().catch(onErr);\n });\n });\n\n document.getElementById('btn-check-update').onclick = async () => {\n try {\n const res = await api('/system/update-check');\n const d = res.data || {};\n const meta = versionStatusMeta(d);\n await uiAlert({\n title: t('system.checkResult'),\n message:\n `${t('system.current')}: ${d.current || '?'}\\n` +\n `${t('system.npm')}: ${d.latestNpm || 'n/a'}\\n` +\n `${t('system.github')}: ${d.latestGithub || 'n/a'}\\n` +\n `${meta.hint}`,\n });\n state.systemTab = 'package';\n renderSystem().catch(onErr);\n } catch (e) {\n onErr(e);\n }\n };\n document.getElementById('btn-one-click-update').onclick = async () => {\n if (\n !(await uiConfirm({\n message: t('system.confirmUpdate'),\n variant: 'danger',\n confirmText: t('system.oneClick'),\n }))\n )\n return;\n // Ensure package tab is visible so update-log is on screen\n if (state.systemTab !== 'package') {\n state.systemTab = 'package';\n await renderSystem();\n }\n const logEl = document.getElementById('update-log');\n try {\n const btn = document.getElementById('btn-one-click-update');\n if (btn) btn.disabled = true;\n const res = await api('/system/update', {\n method: 'POST',\n body: JSON.stringify({ restart: true }),\n });\n if (logEl) {\n logEl.style.display = 'block';\n logEl.textContent =\n (res.data && (res.data.message || JSON.stringify(res.data, null, 2))) ||\n t('system.scheduled');\n }\n await uiAlert((res.data && res.data.message) || t('system.scheduled'));\n } catch (e) {\n onErr(e);\n }\n };\n}\n\n\nfunction banSourceLabel(source) {\n if (!source) return '—';\n const key = `ddos.sources.${source}`;\n const label = t(key);\n return label === key ? source : label;\n}\n\nfunction msToSec(ms) {\n return Math.max(1, Math.round(Number(ms || 0) / 1000));\n}\nfunction msToMin(ms) {\n return Math.max(1, Math.round(Number(ms || 0) / 60_000));\n}\nfunction secToMs(sec) {\n return Math.max(1000, Math.round(Number(sec || 0) * 1000));\n}\nfunction minToMs(min) {\n return Math.max(1000, Math.round(Number(min || 0) * 60_000));\n}\n\nfunction numVal(id, fallback) {\n const n = Number(document.getElementById(id)?.value);\n return Number.isFinite(n) ? n : fallback;\n}\nfunction boolVal(id) {\n return document.getElementById(id)?.checked === true;\n}\n\nfunction readDdosPolicyForm() {\n const wl = (document.getElementById('dp-whitelist')?.value || '')\n .split(/[\\n,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n const trustedProxies = (document.getElementById('dp-trustedProxies')?.value || '')\n .split(/[\\n,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n // Master auto-ban lives in topbar toggle (hidden input kept for applyDdosPolicyToForm compat)\n const masterOn = document.getElementById('ddos-master-autoban')\n ? isMasterToggleOn('ddos-master-autoban')\n : boolVal('dp-autoBanEnabled') ||\n document.getElementById('dp-autoBanEnabled')?.value === '1';\n return {\n autoBanEnabled: masterOn,\n rateLimitWindowMs: secToMs(numVal('dp-rateWindowSec', 60)),\n rateLimitMax: Math.floor(numVal('dp-rateMaxKey', 120)),\n rateLimitIpMax: Math.floor(numVal('dp-rateMaxIp', 60)),\n chatBurstWindowMs: secToMs(numVal('dp-burstWindowSec', 10)),\n chatBurstMax: Math.floor(numVal('dp-burstMax', 20)),\n autoAuthEnabled: boolVal('dp-autoAuthEnabled'),\n failedAuthThreshold: Math.floor(numVal('dp-authThreshold', 20)),\n failedAuthWindowMs: secToMs(numVal('dp-authWindowSec', 300)),\n authBanDurationMs: minToMs(numVal('dp-authBanMin', 10)),\n autoRateEnabled: boolVal('dp-autoRateEnabled'),\n rateHitThreshold: Math.floor(numVal('dp-rateHitThreshold', 30)),\n rateHitWindowMs: secToMs(numVal('dp-rateHitWindowSec', 60)),\n rateBanDurationMs: minToMs(numVal('dp-rateBanMin', 15)),\n autoConnEnabled: boolVal('dp-autoConnEnabled'),\n maxConcurrentPerIp: Math.floor(numVal('dp-maxConcurrent', 20)),\n connBanDurationMs: minToMs(numVal('dp-connBanMin', 10)),\n autoVelocityEnabled: boolVal('dp-autoVelocityEnabled'),\n velocityMaxRequests: Math.floor(numVal('dp-velocityMax', 200)),\n velocityWindowMs: secToMs(numVal('dp-velocityWindowSec', 60)),\n velocityBanDurationMs: minToMs(numVal('dp-velocityBanMin', 10)),\n escalateEnabled: boolVal('dp-escalateEnabled'),\n escalateAfterBans: Math.floor(numVal('dp-escalateAfter', 3)),\n escalateDurationMs: minToMs(numVal('dp-escalateMin', 1440)),\n whitelist: wl,\n proxyTrustHops: Math.max(0, Math.min(10, Math.floor(numVal('dp-proxyTrustHops', 1)))),\n proxyIpSource: document.getElementById('dp-proxyIpSource')?.value || 'auto',\n trustedProxies: trustedProxies.length ? trustedProxies : ['127.0.0.1', '::1'],\n };\n}\n\n/** Fields used to decide relaxed / balanced / strict / custom. */\nconst DDOS_PRESET_KEYS = [\n 'autoBanEnabled',\n 'rateLimitWindowMs',\n 'rateLimitMax',\n 'rateLimitIpMax',\n 'chatBurstWindowMs',\n 'chatBurstMax',\n 'autoAuthEnabled',\n 'failedAuthThreshold',\n 'failedAuthWindowMs',\n 'authBanDurationMs',\n 'autoRateEnabled',\n 'rateHitThreshold',\n 'rateHitWindowMs',\n 'rateBanDurationMs',\n 'autoConnEnabled',\n 'maxConcurrentPerIp',\n 'connBanDurationMs',\n 'autoVelocityEnabled',\n 'velocityMaxRequests',\n 'velocityWindowMs',\n 'velocityBanDurationMs',\n 'escalateEnabled',\n 'escalateAfterBans',\n 'escalateDurationMs',\n];\n\nfunction normalizeDdosPolicySlice(p) {\n if (!p) return {};\n const out = {};\n for (const k of DDOS_PRESET_KEYS) {\n const v = p[k];\n if (typeof v === 'boolean') out[k] = v;\n else if (typeof v === 'number' && Number.isFinite(v)) out[k] = Math.round(v);\n else if (v == null) out[k] = null;\n else out[k] = v;\n }\n return out;\n}\n\nfunction ddosPoliciesEqual(a, b) {\n return (\n JSON.stringify(normalizeDdosPolicySlice(a)) ===\n JSON.stringify(normalizeDdosPolicySlice(b))\n );\n}\n\n/** @returns {'relaxed'|'balanced'|'strict'|'custom'} */\nfunction matchDdosPreset(policy) {\n const presets = state._ddosPresetsCache;\n if (!presets || !policy) return 'custom';\n for (const name of ['relaxed', 'balanced', 'strict']) {\n if (presets[name] && ddosPoliciesEqual(policy, presets[name])) return name;\n }\n return 'custom';\n}\n\nfunction ddosPresetLabel(name) {\n if (name === 'relaxed') return t('ddos.presetRelaxed');\n if (name === 'balanced') return t('ddos.presetBalanced');\n if (name === 'strict') return t('ddos.presetStrict');\n return t('ddos.presetCustom');\n}\n\nfunction ddosPresetBadgeHtml(name, { unsaved = false } = {}) {\n const label = ddosPresetLabel(name);\n const tone =\n name === 'relaxed'\n ? 'relaxed'\n : name === 'balanced'\n ? 'balanced'\n : name === 'strict'\n ? 'strict'\n : 'custom';\n const status = unsaved\n ? tf('ddos.presetFormLabel', { name: label })\n : tf('ddos.presetActiveLabel', { name: label });\n return `<span class=\"ddos-preset-badge is-${tone}\" id=\"ddos-preset-badge\" title=\"${escapeHtml(status)}\">${escapeHtml(status)}</span>`;\n}\n\nfunction updateDdosPresetUI() {\n if (!document.getElementById('ddos-policy-panel')) return;\n let formPol;\n try {\n formPol = readDdosPolicyForm();\n } catch {\n return;\n }\n const formMatch = matchDdosPreset(formPol);\n const savedMatch = matchDdosPreset(state._ddosPolicyCache || formPol);\n const unsaved = !ddosPoliciesEqual(formPol, state._ddosPolicyCache || formPol);\n\n document.querySelectorAll('[data-ddos-preset]').forEach((btn) => {\n const name = btn.dataset.ddosPreset;\n const isForm = name === formMatch;\n const isSaved = name === savedMatch;\n btn.classList.toggle('is-active', isForm);\n btn.classList.toggle('is-saved', isSaved && !isForm);\n btn.setAttribute('aria-pressed', isForm ? 'true' : 'false');\n // live label: 目前 / 已套用\n const base =\n name === 'relaxed'\n ? t('ddos.presetRelaxed')\n : name === 'balanced'\n ? t('ddos.presetBalanced')\n : t('ddos.presetStrict');\n if (isForm && isSaved) {\n btn.innerHTML = `${escapeHtml(base)} <span class=\"preset-tag\">${escapeHtml(t('ddos.presetTagActive'))}</span>`;\n } else if (isForm && unsaved) {\n btn.innerHTML = `${escapeHtml(base)} <span class=\"preset-tag preset-tag--draft\">${escapeHtml(t('ddos.presetTagDraft'))}</span>`;\n } else if (isSaved) {\n btn.innerHTML = `${escapeHtml(base)} <span class=\"preset-tag preset-tag--saved\">${escapeHtml(t('ddos.presetTagSaved'))}</span>`;\n } else {\n btn.textContent = base;\n }\n });\n\n const badgeHost = document.getElementById('ddos-preset-badge');\n if (badgeHost) {\n const html = ddosPresetBadgeHtml(formMatch, {\n unsaved: unsaved && formMatch !== savedMatch,\n });\n // replace node to refresh classes\n badgeHost.outerHTML = html;\n }\n\n const customBtn = document.getElementById('ddos-preset-custom');\n if (customBtn) {\n customBtn.classList.toggle('is-active', formMatch === 'custom');\n customBtn.setAttribute(\n 'aria-pressed',\n formMatch === 'custom' ? 'true' : 'false',\n );\n }\n\n const hint = document.getElementById('ddos-preset-hint');\n if (hint) {\n if (unsaved && formMatch !== savedMatch) {\n hint.textContent = tf('ddos.presetUnsavedHint', {\n form: ddosPresetLabel(formMatch),\n saved: ddosPresetLabel(savedMatch),\n });\n hint.hidden = false;\n } else if (formMatch === 'custom') {\n hint.textContent = t('ddos.presetCustomHint');\n hint.hidden = false;\n } else {\n hint.textContent = tf('ddos.presetActiveHint', {\n name: ddosPresetLabel(formMatch),\n });\n hint.hidden = false;\n }\n }\n}\n\nfunction applyDdosPolicyToForm(p) {\n if (!p || !document.getElementById('dp-autoBanEnabled')) return;\n const set = (id, v) => {\n const el = document.getElementById(id);\n if (!el) return;\n if (el.type === 'checkbox') el.checked = Boolean(v);\n else el.value = v;\n };\n const hid = document.getElementById('dp-autoBanEnabled');\n if (hid) {\n if (hid.type === 'checkbox') hid.checked = Boolean(p.autoBanEnabled);\n else hid.value = p.autoBanEnabled ? '1' : '0';\n }\n setMasterToggle(\n 'ddos-master-autoban',\n Boolean(p.autoBanEnabled),\n t('ddos.masterOn'),\n t('ddos.masterOff'),\n );\n setFeatureRootOff('ddos-root', !p.autoBanEnabled);\n setFeatureOffBanner('ddos-disabled-banner', !p.autoBanEnabled);\n set('dp-rateWindowSec', msToSec(p.rateLimitWindowMs));\n set('dp-rateMaxKey', p.rateLimitMax);\n set('dp-rateMaxIp', p.rateLimitIpMax);\n set('dp-burstWindowSec', msToSec(p.chatBurstWindowMs));\n set('dp-burstMax', p.chatBurstMax);\n set('dp-autoAuthEnabled', p.autoAuthEnabled);\n set('dp-authThreshold', p.failedAuthThreshold);\n set('dp-authWindowSec', msToSec(p.failedAuthWindowMs));\n set('dp-authBanMin', msToMin(p.authBanDurationMs));\n set('dp-autoRateEnabled', p.autoRateEnabled);\n set('dp-rateHitThreshold', p.rateHitThreshold);\n set('dp-rateHitWindowSec', msToSec(p.rateHitWindowMs));\n set('dp-rateBanMin', msToMin(p.rateBanDurationMs));\n set('dp-autoConnEnabled', p.autoConnEnabled);\n set('dp-maxConcurrent', p.maxConcurrentPerIp);\n set('dp-connBanMin', msToMin(p.connBanDurationMs));\n set('dp-autoVelocityEnabled', p.autoVelocityEnabled);\n set('dp-velocityMax', p.velocityMaxRequests);\n set('dp-velocityWindowSec', msToSec(p.velocityWindowMs));\n set('dp-velocityBanMin', msToMin(p.velocityBanDurationMs));\n set('dp-escalateEnabled', p.escalateEnabled);\n set('dp-escalateAfter', p.escalateAfterBans);\n set('dp-escalateMin', msToMin(p.escalateDurationMs));\n set('dp-whitelist', (p.whitelist || []).join('\\n'));\n set('dp-proxyTrustHops', p.proxyTrustHops ?? 1);\n set('dp-proxyIpSource', p.proxyIpSource || 'auto');\n set(\n 'dp-trustedProxies',\n (p.trustedProxies && p.trustedProxies.length\n ? p.trustedProxies\n : ['127.0.0.1', '::1']\n ).join('\\n'),\n );\n updateDdosAutoBadge(p.autoBanEnabled);\n updateDdosPresetUI();\n}\n\nfunction updateDdosAutoBadge(on) {\n const el = document.getElementById('ddos-auto-badge');\n if (!el) return;\n el.className = `badge ${on ? 'success' : 'pending'}`;\n el.textContent = on ? t('ddos.autoOn') : t('ddos.autoOff');\n}\n\nfunction ddosPolicyPanelHtml(p) {\n const check = (id, on) =>\n `<label class=\"data-filter-check policy-enable\"><input type=\"checkbox\" id=\"${id}\" ${on ? 'checked' : ''} /> <span>${escapeHtml(t('ddos.enableRule'))}</span></label>`;\n const field = (label, id, value, step = '1') =>\n `<label>${escapeHtml(label)}<input type=\"number\" id=\"${id}\" value=\"${escapeHtml(String(value))}\" min=\"1\" step=\"${step}\" /></label>`;\n\n const savedMatch = matchDdosPreset(p);\n const presetBadge = ddosPresetBadgeHtml(savedMatch);\n\n return `\n <div class=\"panel data-table-panel ddos-policy-panel\" id=\"ddos-policy-panel\">\n <div class=\"panel-h\">\n <div>\n <strong>${escapeHtml(t('ddos.policyTitle'))}</strong>\n <span class=\"muted\">${escapeHtml(t('ddos.policyHint'))}</span>\n </div>\n <div class=\"ddos-header-badges\">\n ${presetBadge}\n <span class=\"badge ${p.autoBanEnabled ? 'success' : 'pending'}\" id=\"ddos-auto-badge\">${escapeHtml(p.autoBanEnabled ? t('ddos.autoOn') : t('ddos.autoOff'))}</span>\n </div>\n </div>\n <div class=\"panel-pad\">\n <div class=\"ddos-preset-block\">\n <div class=\"ddos-preset-block-h\">\n <strong>${escapeHtml(t('ddos.presetTitle'))}</strong>\n <span class=\"muted\">${escapeHtml(t('ddos.presetHint'))}</span>\n </div>\n <div class=\"ddos-presets\" role=\"group\" aria-label=\"${escapeHtml(t('ddos.presetTitle'))}\">\n <button type=\"button\" class=\"ddos-preset-btn\" data-ddos-preset=\"relaxed\" aria-pressed=\"false\">${escapeHtml(t('ddos.presetRelaxed'))}</button>\n <button type=\"button\" class=\"ddos-preset-btn\" data-ddos-preset=\"balanced\" aria-pressed=\"false\">${escapeHtml(t('ddos.presetBalanced'))}</button>\n <button type=\"button\" class=\"ddos-preset-btn\" data-ddos-preset=\"strict\" aria-pressed=\"false\">${escapeHtml(t('ddos.presetStrict'))}</button>\n <button type=\"button\" class=\"ddos-preset-btn ddos-preset-btn--custom\" id=\"ddos-preset-custom\" disabled aria-pressed=\"false\">${escapeHtml(t('ddos.presetCustom'))}</button>\n </div>\n <p class=\"ddos-preset-hint\" id=\"ddos-preset-hint\"></p>\n </div>\n <p class=\"muted policy-master-hint\">${escapeHtml(t('ddos.autoBanMasterHint'))}</p>\n <input type=\"hidden\" id=\"dp-autoBanEnabled\" value=\"${p.autoBanEnabled ? '1' : '0'}\" />\n\n <div class=\"policy-section\">\n <h4>${escapeHtml(t('ddos.sectionProxy'))}</h4>\n <p class=\"muted\" style=\"margin:0 0 10px\">${escapeHtml(t('ddos.proxyHint'))}</p>\n <div class=\"form-grid\">\n <label>${escapeHtml(t('ddos.proxyTrustHops'))}\n <input type=\"number\" id=\"dp-proxyTrustHops\" value=\"${escapeHtml(String(p.proxyTrustHops ?? 1))}\" min=\"0\" max=\"10\" step=\"1\" />\n <span class=\"field-hint\">${escapeHtml(t('ddos.proxyTrustHopsHint'))}</span>\n </label>\n <label>${escapeHtml(t('ddos.proxyIpSource'))}\n <select id=\"dp-proxyIpSource\">\n <option value=\"auto\" ${(p.proxyIpSource || 'auto') === 'auto' ? 'selected' : ''}>${escapeHtml(t('ddos.proxySrcAuto'))}</option>\n <option value=\"cloudflare\" ${p.proxyIpSource === 'cloudflare' ? 'selected' : ''}>${escapeHtml(t('ddos.proxySrcCf'))}</option>\n <option value=\"nginx\" ${p.proxyIpSource === 'nginx' ? 'selected' : ''}>${escapeHtml(t('ddos.proxySrcNginx'))}</option>\n <option value=\"x-forwarded-for\" ${p.proxyIpSource === 'x-forwarded-for' ? 'selected' : ''}>${escapeHtml(t('ddos.proxySrcXff'))}</option>\n <option value=\"socket\" ${p.proxyIpSource === 'socket' ? 'selected' : ''}>${escapeHtml(t('ddos.proxySrcSocket'))}</option>\n </select>\n <span class=\"field-hint\">${escapeHtml(t('ddos.proxyIpSourceHint'))}</span>\n </label>\n <label class=\"full\">${escapeHtml(t('ddos.trustedProxies'))}\n <textarea id=\"dp-trustedProxies\" rows=\"3\" class=\"policy-whitelist\">${escapeHtml((p.trustedProxies && p.trustedProxies.length ? p.trustedProxies : ['127.0.0.1', '::1']).join('\\n'))}</textarea>\n <span class=\"field-hint\">${escapeHtml(t('ddos.trustedProxiesHint'))}</span>\n </label>\n </div>\n </div>\n\n <div class=\"policy-section\">\n <h4>${escapeHtml(t('ddos.sectionLimits'))}</h4>\n <div class=\"form-grid\">\n ${field(t('ddos.rateWindow'), 'dp-rateWindowSec', msToSec(p.rateLimitWindowMs))}\n ${field(t('ddos.rateMaxKey'), 'dp-rateMaxKey', p.rateLimitMax)}\n ${field(t('ddos.rateMaxIp'), 'dp-rateMaxIp', p.rateLimitIpMax)}\n ${field(t('ddos.burstWindow'), 'dp-burstWindowSec', msToSec(p.chatBurstWindowMs))}\n ${field(t('ddos.burstMax'), 'dp-burstMax', p.chatBurstMax)}\n </div>\n </div>\n\n <div class=\"policy-section\">\n <div class=\"policy-section-h\"><h4>${escapeHtml(t('ddos.sectionAuth'))}</h4>${check('dp-autoAuthEnabled', p.autoAuthEnabled)}</div>\n <div class=\"form-grid\">\n ${field(t('ddos.threshold'), 'dp-authThreshold', p.failedAuthThreshold)}\n ${field(t('ddos.windowSec'), 'dp-authWindowSec', msToSec(p.failedAuthWindowMs))}\n ${field(t('ddos.banMin'), 'dp-authBanMin', msToMin(p.authBanDurationMs))}\n </div>\n </div>\n\n <div class=\"policy-section\">\n <div class=\"policy-section-h\"><h4>${escapeHtml(t('ddos.sectionRate'))}</h4>${check('dp-autoRateEnabled', p.autoRateEnabled)}</div>\n <div class=\"form-grid\">\n ${field(t('ddos.threshold'), 'dp-rateHitThreshold', p.rateHitThreshold)}\n ${field(t('ddos.windowSec'), 'dp-rateHitWindowSec', msToSec(p.rateHitWindowMs))}\n ${field(t('ddos.banMin'), 'dp-rateBanMin', msToMin(p.rateBanDurationMs))}\n </div>\n </div>\n\n <div class=\"policy-section\">\n <div class=\"policy-section-h\"><h4>${escapeHtml(t('ddos.sectionConn'))}</h4>${check('dp-autoConnEnabled', p.autoConnEnabled)}</div>\n <div class=\"form-grid\">\n ${field(t('ddos.maxConcurrent'), 'dp-maxConcurrent', p.maxConcurrentPerIp)}\n ${field(t('ddos.banMin'), 'dp-connBanMin', msToMin(p.connBanDurationMs))}\n </div>\n </div>\n\n <div class=\"policy-section\">\n <div class=\"policy-section-h\"><h4>${escapeHtml(t('ddos.sectionVelocity'))}</h4>${check('dp-autoVelocityEnabled', p.autoVelocityEnabled)}</div>\n <div class=\"form-grid\">\n ${field(t('ddos.velocityMax'), 'dp-velocityMax', p.velocityMaxRequests)}\n ${field(t('ddos.windowSec'), 'dp-velocityWindowSec', msToSec(p.velocityWindowMs))}\n ${field(t('ddos.banMin'), 'dp-velocityBanMin', msToMin(p.velocityBanDurationMs))}\n </div>\n </div>\n\n <div class=\"policy-section\">\n <div class=\"policy-section-h\"><h4>${escapeHtml(t('ddos.sectionEscalate'))}</h4>${check('dp-escalateEnabled', p.escalateEnabled)}</div>\n <div class=\"form-grid\">\n ${field(t('ddos.escalateAfter'), 'dp-escalateAfter', p.escalateAfterBans)}\n ${field(t('ddos.escalateMin'), 'dp-escalateMin', msToMin(p.escalateDurationMs))}\n </div>\n </div>\n\n <div class=\"policy-section\">\n <h4>${escapeHtml(t('ddos.sectionWhitelist'))}</h4>\n <p class=\"muted\" style=\"margin:0 0 8px\">${escapeHtml(t('ddos.whitelistHint'))}</p>\n <textarea id=\"dp-whitelist\" rows=\"4\" class=\"policy-whitelist\">${escapeHtml((p.whitelist || []).join('\\n'))}</textarea>\n </div>\n\n <div class=\"ddos-policy-actions\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"dp-reset\">${escapeHtml(t('ddos.resetPolicy'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"dp-save\">${escapeHtml(t('ddos.savePolicy'))}</button>\n </div>\n </div>\n </div>`;\n}\n\nfunction ddosEventsRows(events) {\n if (!events?.length) {\n return `<tr class=\"empty-row\"><td colspan=\"5\"><div class=\"data-empty\"><strong>${escapeHtml(t('ddos.emptyEvents'))}</strong></div></td></tr>`;\n }\n return events\n .map(\n (e) => `\n <tr>\n <td>${fmtTime(e.at)}</td>\n <td class=\"cell-primary\">${escapeHtml(e.ip)}</td>\n <td><span class=\"badge ${e.escalated ? 'warn' : 'pending'}\">${escapeHtml(banSourceLabel(e.source))}</span></td>\n <td class=\"muted\" style=\"max-width:280px;word-break:break-word\">${escapeHtml(e.reason || '')}</td>\n <td>${escapeHtml(msToMin(e.durationMs))} min</td>\n </tr>`,\n )\n .join('');\n}\n\nasync function renderDdos(opts = {}) {\n const soft = Boolean(opts.soft) && document.getElementById('ddos-root');\n const mainEl = document.querySelector('.main');\n const savedScroll = mainEl ? mainEl.scrollTop : 0;\n\n if (ddosTimer) {\n clearInterval(ddosTimer);\n ddosTimer = null;\n }\n\n const df = state.ddosFilter;\n if (!df.liveSortBy) df.liveSortBy = 'startedAt';\n if (!df.liveSortDir) df.liveSortDir = 'desc';\n if (!df.banSortBy) df.banSortBy = 'createdAt';\n if (!df.banSortDir) df.banSortDir = 'desc';\n if (!df.eventSortBy) df.eventSortBy = 'at';\n if (!df.eventSortDir) df.eventSortDir = 'desc';\n\n const connQ = new URLSearchParams();\n appendSortParams(connQ, df, 'liveSortBy', 'liveSortDir');\n const banQ = new URLSearchParams();\n appendSortParams(banQ, df, 'banSortBy', 'banSortDir');\n const evQ = new URLSearchParams();\n appendSortParams(evQ, df, 'eventSortBy', 'eventSortDir');\n\n const fetches = [\n api(`/ddos/connections?${connQ}`),\n api(`/ddos/blacklist?${banQ}`),\n api('/ddos/stats'),\n api(`/ddos/events?${evQ}`),\n ];\n if (!soft) fetches.push(api('/ddos/policy'));\n const results = await Promise.all(fetches);\n const [conn, bl, st, evRes] = results;\n const policyRes = soft ? null : results[4];\n const ps = df.pageSize || 15;\n let active = conn.data?.active || [];\n let recent = conn.data?.recent || [];\n let bans = bl.data || [];\n const stats = st.data || {};\n const events = evRes.data || [];\n const policy = policyRes?.data || state._ddosPolicyCache || null;\n const presets = policyRes?.presets || state._ddosPresetsCache || null;\n if (policy) state._ddosPolicyCache = policy;\n if (presets) state._ddosPresetsCache = presets;\n const whitelist = (state._ddosPolicyCache?.whitelist || []).map(String);\n\n if (df.liveQ.trim()) {\n const qq = df.liveQ.trim().toLowerCase();\n const match = (c) =>\n [c.ip, c.path, c.method, c.apiKeyName, c.apiKeyPrefix]\n .filter(Boolean)\n .some((x) => String(x).toLowerCase().includes(qq));\n active = active.filter(match);\n recent = recent.filter(match);\n }\n if (df.banQ.trim()) {\n const qq = df.banQ.trim().toLowerCase();\n bans = bans.filter(\n (b) =>\n String(b.ip || '').toLowerCase().includes(qq) ||\n String(b.reason || '').toLowerCase().includes(qq),\n );\n }\n if (df.banSource) {\n bans = bans.filter((b) => b.source === df.banSource);\n }\n const liveSlice = active.slice(df.livePage * ps, df.livePage * ps + ps);\n const banSlice = bans.slice(df.banPage * ps, df.banPage * ps + ps);\n\n const liveRows = liveSlice\n .map(\n (c) => `\n <tr>\n <td class=\"cell-primary\">${escapeHtml(c.ip)}</td>\n <td>${escapeHtml(c.method)}</td>\n <td class=\"muted\" style=\"max-width:220px;word-break:break-all\">${escapeHtml(c.path)}</td>\n <td>${escapeHtml(c.apiKeyName || c.apiKeyPrefix || '—')}</td>\n <td><span class=\"badge pending\">${escapeHtml(t('status.active'))}</span></td>\n <td>${fmtMs(Date.now() - c.startedAt)}</td>\n <td><div class=\"row-actions\"><button class=\"btn danger sm\" data-ban=\"${escapeHtml(c.ip)}\">${escapeHtml(t('ddos.ban'))}</button></div></td>\n </tr>`,\n )\n .join('');\n\n const recentRows = recent\n .slice(0, 40)\n .map(\n (c) => `\n <tr>\n <td class=\"cell-primary\">${escapeHtml(c.ip)}</td>\n <td>${escapeHtml(c.method)} ${escapeHtml(c.path)}</td>\n <td>${c.statusCode ?? '—'}</td>\n <td>${fmtMs(c.durationMs)}</td>\n <td><div class=\"row-actions\"><button class=\"btn danger sm\" data-ban=\"${escapeHtml(c.ip)}\">${escapeHtml(t('ddos.ban'))}</button></div></td>\n </tr>`,\n )\n .join('');\n\n const banRows = banSlice\n .map(\n (b) => `\n <tr>\n <td class=\"cell-primary\">${escapeHtml(b.ip)}</td>\n <td>${escapeHtml(b.reason || '—')}</td>\n <td><span class=\"badge pending\">${escapeHtml(banSourceLabel(b.source))}</span></td>\n <td>${b.expiresAt ? fmtTime(b.expiresAt) : escapeHtml(t('ddos.permanent'))}</td>\n <td><div class=\"row-actions\"><button class=\"btn secondary sm\" data-unban=\"${escapeHtml(b.ip)}\">${escapeHtml(t('ddos.unban'))}</button></div></td>\n </tr>`,\n )\n .join('');\n\n const topIps = (stats.topIps || [])\n .map(\n (x) => `<tr><td class=\"cell-primary\">${escapeHtml(x.ip)}</td><td>${x.requests}</td>\n <td><div class=\"row-actions\"><button class=\"btn danger sm\" data-ban=\"${escapeHtml(x.ip)}\">${escapeHtml(t('ddos.ban'))}</button></div></td></tr>`,\n )\n .join('');\n\n const eventRows = ddosEventsRows(events);\n const emptyLive = `<tr class=\"empty-row\"><td colspan=\"7\"><div class=\"data-empty\"><strong>${escapeHtml(t('ddos.emptyLive'))}</strong></div></td></tr>`;\n const emptyRecent = `<tr class=\"empty-row\"><td colspan=\"5\"><div class=\"data-empty\"><strong>${escapeHtml(t('common.empty'))}</strong></div></td></tr>`;\n const emptyBan = `<tr class=\"empty-row\"><td colspan=\"5\"><div class=\"data-empty\"><strong>${escapeHtml(t('ddos.emptyBan'))}</strong></div></td></tr>`;\n const emptyTop = `<tr class=\"empty-row\"><td colspan=\"3\"><div class=\"data-empty\"><strong>${escapeHtml(t('common.empty'))}</strong></div></td></tr>`;\n\n const sourceOpts = [\n '',\n 'manual',\n 'auto-auth',\n 'auto-rate',\n 'auto-conn',\n 'auto-velocity',\n 'auto-escalate',\n ]\n .map((s) => {\n if (!s) return `<option value=\"\">${escapeHtml(t('common.all'))}</option>`;\n return `<option value=\"${s}\" ${df.banSource === s ? 'selected' : ''}>${escapeHtml(banSourceLabel(s))}</option>`;\n })\n .join('');\n\n if (soft) {\n const set = (id, html) => {\n const el = document.getElementById(id);\n if (el) el.innerHTML = html;\n };\n const setText = (id, text) => {\n const el = document.getElementById(id);\n if (el) el.textContent = text;\n };\n setText('ddos-stat-active', String(stats.activeConnections ?? active.length));\n setText('ddos-stat-rate', String(stats.rateLimitedHits ?? 0));\n setText('ddos-stat-blocked', String(stats.blockedHits ?? 0));\n setText('ddos-stat-ban', String(bans.length));\n setText('ddos-stat-auto', String(stats.autoBanTotal ?? 0));\n setText('ddos-tab-count-live', String(active.length));\n setText('ddos-tab-count-ban', String(bans.length));\n setText('ddos-tab-count-events', String(events.length));\n set('ddos-live-body', liveRows || emptyLive);\n set('ddos-recent-body', recentRows || emptyRecent);\n set('ddos-ban-body', banRows || emptyBan);\n set('ddos-top-body', topIps || emptyTop);\n set('ddos-events-body', eventRows);\n enhanceResponsiveTables(document);\n if (stats.policySummary) {\n updateDdosAutoBadge(Boolean(stats.policySummary.autoBanEnabled));\n }\n bindDdosActions();\n if (mainEl) mainEl.scrollTop = savedScroll;\n } else {\n const pol = policy || {\n autoBanEnabled: true,\n rateLimitWindowMs: 60000,\n rateLimitMax: 120,\n rateLimitIpMax: 60,\n chatBurstWindowMs: 10000,\n chatBurstMax: 20,\n autoAuthEnabled: true,\n failedAuthThreshold: 20,\n failedAuthWindowMs: 300000,\n authBanDurationMs: 600000,\n autoRateEnabled: true,\n rateHitThreshold: 30,\n rateHitWindowMs: 60000,\n rateBanDurationMs: 900000,\n autoConnEnabled: true,\n maxConcurrentPerIp: 20,\n connBanDurationMs: 600000,\n autoVelocityEnabled: true,\n velocityMaxRequests: 200,\n velocityWindowMs: 60000,\n velocityBanDurationMs: 600000,\n escalateEnabled: true,\n escalateAfterBans: 3,\n escalateDurationMs: 86400000,\n whitelist: ['127.0.0.1', '::1'],\n proxyTrustHops: 1,\n proxyIpSource: 'auto',\n trustedProxies: ['127.0.0.1', '::1'],\n };\n\n const autoBanOn = Boolean(pol.autoBanEnabled);\n const tab =\n df.tab === 'live' ||\n df.tab === 'blacklist' ||\n df.tab === 'events' ||\n df.tab === 'policy'\n ? df.tab\n : 'policy';\n state.ddosFilter.tab = tab;\n\n const kpiGrid = `\n <div class=\"grid ddos-kpi-grid\">\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('ddos.activeConn'))}</div><div class=\"value value-sm\" id=\"ddos-stat-active\">${stats.activeConnections ?? active.length}</div><div class=\"muted card-sub\">${escapeHtml(t('ddos.live'))}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('ddos.rateHits'))}</div><div class=\"value value-sm\" id=\"ddos-stat-rate\">${stats.rateLimitedHits ?? 0}</div><div class=\"muted card-sub\">${escapeHtml(t('ddos.stats'))}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('ddos.blockedHits'))}</div><div class=\"value value-sm\" id=\"ddos-stat-blocked\">${stats.blockedHits ?? 0}</div><div class=\"muted card-sub\">${escapeHtml(t('ddos.stats'))}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('ddos.blacklist'))}</div><div class=\"value value-sm\" id=\"ddos-stat-ban\">${bans.length}</div><div class=\"muted card-sub\">${escapeHtml(t('ddos.tabBlacklist'))}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('ddos.autoBans'))}</div><div class=\"value value-sm\" id=\"ddos-stat-auto\">${stats.autoBanTotal ?? 0}</div><div class=\"muted card-sub\">${escapeHtml(t('ddos.tabEvents'))}</div></div>\n </div>`;\n\n const policyPane = ddosPolicyPanelHtml(pol);\n\n const livePane = `\n <div class=\"panel data-filter-panel ddos-filter-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('common.filterTitle'))}</strong></div>\n <div class=\"data-filter\">\n <div class=\"data-filter-grid\">\n <label class=\"full\">${escapeHtml(t('ddos.live'))} / ${escapeHtml(t('ddos.recent'))}\n <input type=\"search\" id=\"ddos-live-q\" value=\"${escapeHtml(df.liveQ)}\" placeholder=\"IP / path / key\" />\n </label>\n </div>\n <div class=\"data-filter-actions\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"ddos-live-filter-reset\">${escapeHtml(t('common.reset'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"ddos-live-filter-apply\">${escapeHtml(t('common.apply'))}</button>\n </div>\n </div>\n </div>\n <div class=\"panel data-table-panel ddos-stack-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('ddos.live'))}</strong>\n <span class=\"muted\">${escapeHtml(tf('common.pagerTotal', { n: active.length }))}</span>\n </div>\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr>\n ${sortThHtml({ field: 'ip', label: t('ddos.ip'), filterRef: df, sortByKey: 'liveSortBy', sortDirKey: 'liveSortDir' })}\n ${sortThHtml({ field: 'method', label: t('ddos.method'), filterRef: df, sortByKey: 'liveSortBy', sortDirKey: 'liveSortDir' })}\n ${sortThHtml({ field: 'path', label: t('ddos.path'), filterRef: df, sortByKey: 'liveSortBy', sortDirKey: 'liveSortDir' })}\n <th>${escapeHtml(t('ddos.key'))}</th>\n <th>${escapeHtml(t('ddos.state'))}</th>\n ${sortThHtml({ field: 'durationMs', label: t('ddos.duration'), filterRef: df, sortByKey: 'liveSortBy', sortDirKey: 'liveSortDir' })}\n <th>${escapeHtml(t('common.actions'))}</th>\n </tr></thead>\n <tbody id=\"ddos-live-body\">${liveRows || emptyLive}</tbody>\n </table>\n </div>\n ${pagerHtml({ total: active.length, limit: ps, offset: df.livePage * ps, idPrefix: 'ddoslive' })}\n </div>\n <div class=\"panel data-table-panel ddos-stack-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('ddos.recent'))}</strong></div>\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr>\n ${sortThHtml({ field: 'ip', label: t('ddos.ip'), filterRef: df, sortByKey: 'liveSortBy', sortDirKey: 'liveSortDir' })}\n ${sortThHtml({ field: 'path', label: t('ddos.path'), filterRef: df, sortByKey: 'liveSortBy', sortDirKey: 'liveSortDir' })}\n ${sortThHtml({ field: 'statusCode', label: t('common.httpStatus'), filterRef: df, sortByKey: 'liveSortBy', sortDirKey: 'liveSortDir' })}\n ${sortThHtml({ field: 'durationMs', label: t('ddos.duration'), filterRef: df, sortByKey: 'liveSortBy', sortDirKey: 'liveSortDir' })}\n <th>${escapeHtml(t('common.actions'))}</th>\n </tr></thead>\n <tbody id=\"ddos-recent-body\">${recentRows || emptyRecent}</tbody>\n </table>\n </div>\n </div>`;\n\n const blacklistPane = `\n <div class=\"panel data-filter-panel ddos-filter-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('common.filterTitle'))}</strong></div>\n <div class=\"data-filter\">\n <div class=\"data-filter-grid\">\n <label>${escapeHtml(t('ddos.blacklist'))}\n <input type=\"search\" id=\"ddos-ban-q\" value=\"${escapeHtml(df.banQ)}\" placeholder=\"IP / reason\" />\n </label>\n <label>${escapeHtml(t('ddos.source'))}\n <select id=\"ddos-ban-source\">${sourceOpts}</select>\n </label>\n </div>\n <div class=\"data-filter-actions\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"ddos-ban-filter-reset\">${escapeHtml(t('common.reset'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"ddos-ban-filter-apply\">${escapeHtml(t('common.apply'))}</button>\n </div>\n </div>\n </div>\n <div class=\"panel data-table-panel ddos-stack-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('ddos.blacklist'))}</strong>\n <span class=\"muted\">${escapeHtml(tf('common.pagerTotal', { n: bans.length }))}</span>\n </div>\n <div class=\"filter-bar\">\n <label>${escapeHtml(t('ddos.ip'))}<input id=\"ban-ip\" placeholder=\"${escapeHtml(t('ddos.ipPlaceholder'))}\" /></label>\n <label>${escapeHtml(t('ddos.reason'))}<input id=\"ban-reason\" placeholder=\"${escapeHtml(t('ddos.reasonPh'))}\" class=\"wide\" /></label>\n <label>${escapeHtml(t('ddos.ttl'))}\n <select id=\"ban-ttl\">\n <option value=\"\">${escapeHtml(t('ddos.ttlPerm'))}</option>\n <option value=\"3600\">${escapeHtml(t('ddos.ttl1h'))}</option>\n <option value=\"86400\">${escapeHtml(t('ddos.ttl24h'))}</option>\n <option value=\"604800\">${escapeHtml(t('ddos.ttl7d'))}</option>\n </select>\n </label>\n <button class=\"btn sm\" id=\"ban-add\">${escapeHtml(t('ddos.addBan'))}</button>\n </div>\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr>\n ${sortThHtml({ field: 'ip', label: t('ddos.ip'), filterRef: df, sortByKey: 'banSortBy', sortDirKey: 'banSortDir' })}\n ${sortThHtml({ field: 'reason', label: t('ddos.reason'), filterRef: df, sortByKey: 'banSortBy', sortDirKey: 'banSortDir' })}\n ${sortThHtml({ field: 'source', label: t('ddos.source'), filterRef: df, sortByKey: 'banSortBy', sortDirKey: 'banSortDir' })}\n ${sortThHtml({ field: 'expiresAt', label: t('ddos.expires'), filterRef: df, sortByKey: 'banSortBy', sortDirKey: 'banSortDir' })}\n <th>${escapeHtml(t('common.actions'))}</th>\n </tr></thead>\n <tbody id=\"ddos-ban-body\">${banRows || emptyBan}</tbody>\n </table>\n </div>\n ${pagerHtml({ total: bans.length, limit: ps, offset: df.banPage * ps, idPrefix: 'ddosban' })}\n </div>`;\n\n const eventsPane = `\n <div class=\"panel data-table-panel ddos-stack-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('ddos.eventsTitle'))}</strong>\n <span class=\"muted\">${escapeHtml(tf('common.pagerTotal', { n: events.length }))}</span>\n </div>\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr>\n ${sortThHtml({ field: 'at', label: t('ddos.eventTime'), filterRef: df, sortByKey: 'eventSortBy', sortDirKey: 'eventSortDir' })}\n ${sortThHtml({ field: 'ip', label: t('ddos.ip'), filterRef: df, sortByKey: 'eventSortBy', sortDirKey: 'eventSortDir' })}\n ${sortThHtml({ field: 'source', label: t('ddos.eventSource'), filterRef: df, sortByKey: 'eventSortBy', sortDirKey: 'eventSortDir' })}\n ${sortThHtml({ field: 'reason', label: t('ddos.reason'), filterRef: df, sortByKey: 'eventSortBy', sortDirKey: 'eventSortDir' })}\n ${sortThHtml({ field: 'durationMs', label: t('ddos.eventDuration'), filterRef: df, sortByKey: 'eventSortBy', sortDirKey: 'eventSortDir' })}\n </tr></thead>\n <tbody id=\"ddos-events-body\">${eventRows}</tbody>\n </table>\n </div>\n </div>\n <div class=\"panel data-table-panel ddos-stack-panel\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('ddos.topIps'))}</strong></div>\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr><th>${escapeHtml(t('ddos.ip'))}</th><th>${escapeHtml(t('usage.requests'))}</th><th>${escapeHtml(t('common.actions'))}</th></tr></thead>\n <tbody id=\"ddos-top-body\">${topIps || emptyTop}</tbody>\n </table>\n </div>\n </div>`;\n\n document.getElementById('app').innerHTML = shell(`\n <div id=\"ddos-root\" class=\"${autoBanOn ? '' : 'is-feature-off'}\">\n <div class=\"topbar\">\n <h2>${escapeHtml(t('ddos.title'))}</h2>\n <div class=\"toolbar\">\n ${masterToggleBtnHtml({\n id: 'ddos-master-autoban',\n on: autoBanOn,\n onLabel: t('ddos.masterOn'),\n offLabel: t('ddos.masterOff'),\n title: t('ddos.autoBanMasterHint'),\n })}\n <button class=\"btn secondary sm\" id=\"ddos-refresh\">${escapeHtml(t('ddos.refresh'))}</button>\n <button class=\"btn secondary sm\" id=\"ddos-pause\">${escapeHtml(ddosPaused ? t('ddos.resume') : t('ddos.pause'))}</button>\n </div>\n </div>\n ${pageMetaHtml([t('ddos.policyHint')])}\n <div class=\"feature-off-banner\" id=\"ddos-disabled-banner\" ${autoBanOn ? 'hidden' : ''} role=\"status\">\n <strong>${escapeHtml(t('common.featureOff'))}</strong>\n <span>${escapeHtml(t('ddos.disabledBanner'))}</span>\n </div>\n ${kpiGrid}\n\n <div class=\"usage-tabs-panel panel ddos-tabs-panel\">\n <div class=\"seg-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('ddos.title'))}\">\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'policy' ? 'is-active' : ''}\" data-ddos-tab=\"policy\" aria-selected=\"${tab === 'policy'}\">\n ${escapeHtml(t('ddos.tabPolicy'))}\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'live' ? 'is-active' : ''}\" data-ddos-tab=\"live\" aria-selected=\"${tab === 'live'}\">\n ${escapeHtml(t('ddos.tabLive'))}\n <span class=\"seg-tab-count\" id=\"ddos-tab-count-live\">${active.length}</span>\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'blacklist' ? 'is-active' : ''}\" data-ddos-tab=\"blacklist\" aria-selected=\"${tab === 'blacklist'}\">\n ${escapeHtml(t('ddos.tabBlacklist'))}\n <span class=\"seg-tab-count\" id=\"ddos-tab-count-ban\">${bans.length}</span>\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'events' ? 'is-active' : ''}\" data-ddos-tab=\"events\" aria-selected=\"${tab === 'events'}\">\n ${escapeHtml(t('ddos.tabEvents'))}\n <span class=\"seg-tab-count\" id=\"ddos-tab-count-events\">${events.length}</span>\n </button>\n </div>\n <div class=\"usage-tab-body\">\n <div class=\"usage-tab-pane ddos-tab-pane ddos-tab-pane-policy\" id=\"ddos-tab-policy\" ${tab === 'policy' ? '' : 'hidden'}>\n ${policyPane}\n </div>\n <div class=\"usage-tab-pane ddos-tab-pane ddos-tab-pane-stack\" id=\"ddos-tab-live\" ${tab === 'live' ? '' : 'hidden'}>\n ${livePane}\n </div>\n <div class=\"usage-tab-pane ddos-tab-pane ddos-tab-pane-stack\" id=\"ddos-tab-blacklist\" ${tab === 'blacklist' ? '' : 'hidden'}>\n ${blacklistPane}\n </div>\n <div class=\"usage-tab-pane ddos-tab-pane ddos-tab-pane-stack\" id=\"ddos-tab-events\" ${tab === 'events' ? '' : 'hidden'}>\n ${eventsPane}\n </div>\n </div>\n </div>\n </div>\n `);\n bindShell();\n bindDdosActions(true, whitelist);\n bindSortHeaders(state.ddosFilter, () => renderDdos().catch(onErr));\n\n document.querySelectorAll('[data-ddos-tab]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const raw = btn.getAttribute('data-ddos-tab') || 'policy';\n const next =\n raw === 'live' ||\n raw === 'blacklist' ||\n raw === 'events' ||\n raw === 'policy'\n ? raw\n : 'policy';\n if (state.ddosFilter.tab === next) return;\n state.ddosFilter.tab = next;\n renderDdos().catch(onErr);\n });\n });\n\n document.getElementById('ddos-live-filter-apply')?.addEventListener('click', () => {\n state.ddosFilter.liveQ =\n document.getElementById('ddos-live-q')?.value?.trim() || '';\n state.ddosFilter.livePage = 0;\n renderDdos().catch(onErr);\n });\n document.getElementById('ddos-live-filter-reset')?.addEventListener('click', () => {\n state.ddosFilter.liveQ = '';\n state.ddosFilter.liveSortBy = 'startedAt';\n state.ddosFilter.liveSortDir = 'desc';\n state.ddosFilter.livePage = 0;\n renderDdos().catch(onErr);\n });\n document.getElementById('ddos-ban-filter-apply')?.addEventListener('click', () => {\n state.ddosFilter.banQ =\n document.getElementById('ddos-ban-q')?.value?.trim() || '';\n state.ddosFilter.banSource =\n document.getElementById('ddos-ban-source')?.value || '';\n state.ddosFilter.banPage = 0;\n renderDdos().catch(onErr);\n });\n document.getElementById('ddos-ban-filter-reset')?.addEventListener('click', () => {\n state.ddosFilter.banQ = '';\n state.ddosFilter.banSource = '';\n state.ddosFilter.banSortBy = 'createdAt';\n state.ddosFilter.banSortDir = 'desc';\n state.ddosFilter.banPage = 0;\n renderDdos().catch(onErr);\n });\n document.getElementById('ddoslive-prev')?.addEventListener('click', () => {\n state.ddosFilter.livePage = Math.max(0, df.livePage - 1);\n renderDdos().catch(onErr);\n });\n document.getElementById('ddoslive-next')?.addEventListener('click', () => {\n if ((df.livePage + 1) * ps < active.length) {\n state.ddosFilter.livePage += 1;\n renderDdos().catch(onErr);\n }\n });\n document.getElementById('ddosban-prev')?.addEventListener('click', () => {\n state.ddosFilter.banPage = Math.max(0, df.banPage - 1);\n renderDdos().catch(onErr);\n });\n document.getElementById('ddosban-next')?.addEventListener('click', () => {\n if ((df.banPage + 1) * ps < bans.length) {\n state.ddosFilter.banPage += 1;\n renderDdos().catch(onErr);\n }\n });\n const main2 = document.querySelector('.main');\n if (main2) {\n main2.onscroll = () => {\n state._ddosScrollPauseUntil = Date.now() + 4000;\n };\n }\n }\n\n if (!ddosPaused && state.page === 'ddos') {\n ddosTimer = setInterval(() => {\n if (state.page !== 'ddos' || ddosPaused) return;\n if (state._ddosScrollPauseUntil && Date.now() < state._ddosScrollPauseUntil) return;\n renderDdos({ soft: true }).catch(() => undefined);\n }, 2000);\n }\n}\n\nfunction bindDdosActions(full = false, whitelist = []) {\n const wl = whitelist.length\n ? whitelist\n : state._ddosPolicyCache?.whitelist || [];\n\n const banIp = async (ip) => {\n if (!ip) return;\n const onWl = wl.some((w) => String(w) === ip || String(w).startsWith(ip));\n if (\n !(await uiConfirm({\n message: onWl ? t('ddos.banWhitelistWarn') : t('ddos.banConfirm'),\n variant: 'danger',\n confirmText: t('ddos.ban'),\n }))\n )\n return;\n await api('/ddos/blacklist', {\n method: 'POST',\n body: JSON.stringify({\n ip,\n reason: t('ddos.banReasonDefault'),\n ttlSeconds: null,\n }),\n });\n renderDdos({ soft: true }).catch(onErr);\n };\n\n document.querySelectorAll('[data-ban]').forEach((b) => {\n b.onclick = () => banIp(b.dataset.ban);\n });\n document.querySelectorAll('[data-unban]').forEach((b) => {\n b.onclick = async () => {\n if (\n !(await uiConfirm({\n message: t('ddos.unbanConfirm'),\n variant: 'danger',\n confirmText: t('ddos.unban'),\n }))\n )\n return;\n await api(`/ddos/blacklist/${encodeURIComponent(b.dataset.unban)}`, {\n method: 'DELETE',\n });\n renderDdos({ soft: true }).catch(onErr);\n };\n });\n\n if (full) {\n document.getElementById('ban-add').onclick = async () => {\n const ip = document.getElementById('ban-ip').value.trim();\n if (!ip) return;\n const onWl = wl.some((w) => String(w) === ip);\n if (onWl) {\n if (\n !(await uiConfirm({\n message: t('ddos.banWhitelistWarn'),\n variant: 'danger',\n confirmText: t('ddos.ban'),\n }))\n )\n return;\n }\n const ttl = document.getElementById('ban-ttl').value;\n await api('/ddos/blacklist', {\n method: 'POST',\n body: JSON.stringify({\n ip,\n reason:\n document.getElementById('ban-reason').value.trim() || undefined,\n ttlSeconds: ttl ? Number(ttl) : null,\n }),\n });\n renderDdos({ soft: true }).catch(onErr);\n };\n document.getElementById('ddos-refresh').onclick = () =>\n renderDdos({ soft: false }).catch(onErr);\n document.getElementById('ddos-pause').onclick = () => {\n ddosPaused = !ddosPaused;\n const btn = document.getElementById('ddos-pause');\n if (btn) btn.textContent = ddosPaused ? t('ddos.resume') : t('ddos.pause');\n if (!ddosPaused) renderDdos({ soft: true }).catch(onErr);\n };\n\n document.getElementById('ddos-master-autoban')?.addEventListener('click', async () => {\n const next = !isMasterToggleOn('ddos-master-autoban');\n setMasterToggle(\n 'ddos-master-autoban',\n next,\n t('ddos.masterOn'),\n t('ddos.masterOff'),\n );\n const hid = document.getElementById('dp-autoBanEnabled');\n if (hid) {\n if (hid.type === 'checkbox') hid.checked = next;\n else hid.value = next ? '1' : '0';\n }\n updateDdosAutoBadge(next);\n setFeatureRootOff('ddos-root', !next);\n setFeatureOffBanner('ddos-disabled-banner', !next);\n updateDdosPresetUI();\n // Immediate save of master switch (full form snapshot)\n try {\n const body = readDdosPolicyForm();\n const res = await api('/ddos/policy', {\n method: 'PUT',\n body: JSON.stringify(body),\n });\n state._ddosPolicyCache = res.data;\n updateDdosPresetUI();\n } catch (e) {\n setMasterToggle(\n 'ddos-master-autoban',\n !next,\n t('ddos.masterOn'),\n t('ddos.masterOff'),\n );\n setFeatureRootOff('ddos-root', next);\n setFeatureOffBanner('ddos-disabled-banner', next);\n onErr(e);\n }\n });\n\n // Live-detect custom vs preset when user edits any field\n const policyPanel = document.getElementById('ddos-policy-panel');\n policyPanel?.addEventListener('input', () => updateDdosPresetUI());\n policyPanel?.addEventListener('change', () => updateDdosPresetUI());\n\n document.querySelectorAll('[data-ddos-preset]').forEach((btn) => {\n btn.onclick = () => {\n const name = btn.dataset.ddosPreset;\n if (name === 'custom') return;\n const preset = state._ddosPresetsCache?.[name];\n if (preset) applyDdosPolicyToForm(preset);\n };\n });\n\n updateDdosPresetUI();\n\n document.getElementById('dp-save')?.addEventListener('click', async () => {\n try {\n const body = readDdosPolicyForm();\n const res = await api('/ddos/policy', {\n method: 'PUT',\n body: JSON.stringify(body),\n });\n state._ddosPolicyCache = res.data;\n applyDdosPolicyToForm(res.data);\n updateDdosPresetUI();\n await uiAlert({ title: t('ddos.policyTitle'), message: t('ddos.policySaved') });\n renderDdos({ soft: true }).catch(onErr);\n } catch (e) {\n onErr(e);\n }\n });\n\n document.getElementById('dp-reset')?.addEventListener('click', async () => {\n if (\n !(await uiConfirm({\n message: t('ddos.confirmReset'),\n variant: 'danger',\n confirmText: t('ddos.resetPolicy'),\n }))\n )\n return;\n try {\n const res = await api('/ddos/policy/reset', { method: 'POST' });\n state._ddosPolicyCache = res.data;\n applyDdosPolicyToForm(res.data);\n updateDdosPresetUI();\n await uiAlert({ title: t('ddos.policyTitle'), message: t('ddos.policyReset') });\n renderDdos({ soft: true }).catch(onErr);\n } catch (e) {\n onErr(e);\n }\n });\n }\n}\n\nfunction runnerLabel(runner) {\n if (runner === 'pm2') return t('pm2.runnerPm2');\n if (runner === 'ysk-omni') return t('pm2.runnerGctoac');\n if (runner === 'none') return t('pm2.runnerNone');\n return t('pm2.runnerUnknown');\n}\n\n/** Localize PM2 API status / switch messages via messageKey + params */\nfunction formatPm2Message(data) {\n if (!data) return '';\n const key = data.messageKey;\n if (key && typeof key === 'string') {\n if (key === 'pm2.msgOk') return '';\n const params = data.messageParams || {};\n const out = tf(key, params);\n // if missing i18n key, tf/t returns path — fall back to English message\n if (out && out !== key) return out;\n }\n const raw = data.message || '';\n if (!raw || raw === 'ok') return '';\n return raw;\n}\n\n/**\n * After runner switch / restart: show localized notice and auto-reload Admin.\n * Never rely on backend English `message` — always prefer messageKey / mode.\n */\nfunction scheduleAdminReload(seconds = 10) {\n const ms = Math.max(1, Number(seconds) || 10) * 1000;\n window.setTimeout(() => {\n try {\n window.location.reload();\n } catch {\n window.location.href = window.location.href;\n }\n }, ms);\n}\n\n/**\n * @param {'pm2'|'ysk-omni'} mode\n * @param {any} data API data from /pm2/switch or scheduled payload\n */\nfunction buildPm2SwitchAlertMessage(mode, data) {\n const keyFromApi =\n data?.messageKey ||\n (mode === 'pm2' ? 'pm2.msgSwitchPm2' : 'pm2.msgSwitchGctoac');\n let body = formatPm2Message({\n messageKey: keyFromApi,\n messageParams: data?.messageParams,\n message: undefined, // never show raw English from API\n });\n if (!body) {\n body =\n mode === 'pm2' ? t('pm2.msgSwitchPm2') : t('pm2.msgSwitchGctoac');\n }\n const port =\n data?.port ||\n data?.messageParams?.port ||\n (typeof location !== 'undefined' && location.port\n ? location.port\n : '3850');\n const lines = [\n body,\n tf('pm2.portAfterRestart', { port }),\n tf('pm2.autoRefreshIn', { n: 10 }),\n ];\n return lines.filter(Boolean).join('\\n');\n}\n\nfunction runnerBadge(runner) {\n if (runner === 'pm2') return `<span class=\"badge success\">${escapeHtml(runnerLabel(runner))}</span>`;\n if (runner === 'ysk-omni') return `<span class=\"badge agent\">${escapeHtml(runnerLabel(runner))}</span>`;\n if (runner === 'none') return `<span class=\"badge pending\">${escapeHtml(runnerLabel(runner))}</span>`;\n return `<span class=\"badge warn\">${escapeHtml(runnerLabel(runner))}</span>`;\n}\n\nfunction envExtraToText(extra) {\n if (!extra || typeof extra !== 'object') return '';\n return Object.entries(extra)\n .map(([k, v]) => `${k}=${v}`)\n .join('\\n');\n}\n\nfunction textToEnvExtra(text) {\n const out = {};\n for (const line of (text || '').split('\\n')) {\n const tline = line.trim();\n if (!tline || tline.startsWith('#')) continue;\n const eq = tline.indexOf('=');\n if (eq <= 0) continue;\n out[tline.slice(0, eq).trim()] = tline.slice(eq + 1).trim();\n }\n return out;\n}\n\nfunction readPm2ConfigForm() {\n const bool = (id) => document.getElementById(id)?.checked === true;\n const val = (id) => document.getElementById(id)?.value ?? '';\n let instances = val('pm2-cfg-instances').trim();\n if (instances !== 'max') {\n const n = Number(instances);\n instances = Number.isFinite(n) && n >= 1 ? n : 1;\n }\n const portRaw = val('pm2-cfg-port').trim();\n const portNum = Number(portRaw);\n return {\n port: Number.isFinite(portNum) && portNum >= 1 && portNum <= 65535 ? portNum : undefined,\n name: val('pm2-cfg-name').trim() || 'ysk-omni',\n script: val('pm2-cfg-script').trim() || 'dist/server.js',\n cwd: val('pm2-cfg-cwd').trim() || undefined,\n instances,\n exec_mode: val('pm2-cfg-exec') === 'cluster' ? 'cluster' : 'fork',\n autorestart: bool('pm2-cfg-autorestart'),\n watch: bool('pm2-cfg-watch'),\n max_memory_restart: val('pm2-cfg-maxmem').trim() || '512M',\n max_restarts: Number(val('pm2-cfg-maxrestarts')) || 10,\n min_uptime: val('pm2-cfg-minuptime').trim() || '5s',\n restart_delay: Number(val('pm2-cfg-restartdelay')) || 2000,\n exp_backoff_restart_delay: Number(val('pm2-cfg-backoff')) || 1000,\n merge_logs: bool('pm2-cfg-mergelogs'),\n time: bool('pm2-cfg-time'),\n error_file: val('pm2-cfg-errfile').trim() || 'logs/pm2-error.log',\n out_file: val('pm2-cfg-outfile').trim() || 'logs/pm2-out.log',\n env_extra: textToEnvExtra(val('pm2-cfg-envextra')),\n preferred_runner: val('pm2-cfg-preferred') === 'pm2' ? 'pm2' : 'ysk-omni',\n };\n}\n\nasync function renderPm2() {\n const st = await api('/pm2/status');\n const d = st.data || {};\n const app = d.app;\n const cfg = d.config || {};\n const holders = d.portHolders || {};\n const portBusy = (holders.pids && holders.pids.length > 0) || false;\n const msg = formatPm2Message(d);\n let logsText = '';\n let logsMeta = null;\n try {\n const lg = await api('/pm2/logs?lines=80');\n logsText = (lg.data?.stdout || '') + (lg.data?.stderr ? '\\n' + lg.data.stderr : '');\n logsMeta = lg.data || null;\n } catch (e) {\n logsText = e.message || '';\n }\n if (d.lastError) {\n logsText = `===== last errors =====\\n${d.lastError}\\n\\n${logsText}`;\n }\n const logFiles = logsMeta?.files || [];\n const logSizeLine = logFiles.length\n ? logFiles\n .filter((f) => f.exists)\n .map(\n (f) =>\n `${f.label}: ${f.size < 1024 ? f.size + ' B' : Math.round(f.size / 1024) + ' KB'}`,\n )\n .join(' · ')\n : '';\n const maxMb = logsMeta?.maxBytes\n ? Math.round(logsMeta.maxBytes / (1024 * 1024))\n : 5;\n const keepKb = logsMeta?.keepBytes\n ? Math.round(logsMeta.keepBytes / 1024)\n : 512;\n\n const statusRaw = app?.status || '—';\n const statusLabel =\n statusRaw === 'online'\n ? t('pm2.statusOnline')\n : statusRaw === 'errored'\n ? t('pm2.statusErrored')\n : statusRaw === 'stopped'\n ? t('pm2.statusStopped')\n : statusRaw;\n const statusBadge =\n statusRaw === 'online'\n ? `<span class=\"badge success\">${escapeHtml(statusLabel)}</span>`\n : statusRaw === 'errored'\n ? `<span class=\"badge error\">${escapeHtml(statusLabel)}</span>`\n : escapeHtml(statusLabel);\n\n const canStart = d.available;\n const canControl = d.available && app;\n const runner = d.runner || 'unknown';\n const isWarnOnly =\n msg &&\n statusRaw !== 'errored' &&\n d.available !== false &&\n d.messageKey !== 'pm2.msgErrored';\n\n const envExtraText = envExtraToText(cfg.env_extra);\n const tab =\n state.pm2Tab === 'port' ||\n state.pm2Tab === 'config' ||\n state.pm2Tab === 'logs' ||\n state.pm2Tab === 'runner'\n ? state.pm2Tab\n : 'runner';\n state.pm2Tab = tab;\n\n const kpiGrid = `\n <div class=\"grid pm2-kpi-grid\" id=\"pm2-kpi-grid\">\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('pm2.app'))}</div>\n <div class=\"value value-sm\">${escapeHtml(d.appName || cfg.name || 'ysk-omni')}</div>\n <div class=\"muted card-sub\">${runnerBadge(runner)}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('pm2.status'))}</div>\n <div class=\"value value-sm\">${statusBadge}</div>\n <div class=\"muted card-sub\">${escapeHtml(t('pm2.pid'))}: ${app?.pid && app.pid !== 0 ? app.pid : '—'}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('pm2.restarts'))}</div>\n <div class=\"value value-sm\">${app?.restarts ?? '—'}</div>\n <div class=\"muted card-sub\">CPU ${app?.cpu != null ? app.cpu + '%' : '—'} · ${\n app?.memory != null\n ? tf('common.mb', { n: Math.round(app.memory / 1024 / 1024) })\n : '—'\n }</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('pm2.port'))}</div>\n <div class=\"value value-sm\">${d.port ?? '—'}</div>\n <div class=\"muted card-sub\">${escapeHtml(t('pm2.portBusy'))}: ${portBusy ? t('common.yes') : t('common.no')}</div>\n </div>\n </div>`;\n\n const runnerPane = `\n <div class=\"panel data-table-panel pm2-section-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('pm2.switchTitle'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('pm2.switchHint'))}</span>\n </div>\n ${runnerBadge(runner)}\n </div>\n <div class=\"panel-pad\">\n <div class=\"grid\">\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('pm2.currentRunner'))}</div><div class=\"value value-sm\">${runnerBadge(runner)}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('pm2.omniPid'))}</div><div class=\"value value-sm\">${d.omni?.running && d.omni?.pid ? d.ysk-omni.pid : '—'}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('pm2.port'))}</div><div class=\"value value-sm\">${d.port ?? '—'}</div></div>\n <div class=\"card\"><div class=\"label\">${escapeHtml(t('pm2.portBusy'))}</div><div class=\"value value-sm\">${portBusy ? t('common.yes') : t('common.no')}</div></div>\n </div>\n <div class=\"toolbar settings-save-bar\">\n <button class=\"btn sm\" id=\"pm2-switch-pm2\" ${!canStart ? 'disabled' : ''}>${escapeHtml(t('pm2.switchToPm2'))}</button>\n <button class=\"btn secondary sm\" id=\"pm2-switch-ysk-omni\">${escapeHtml(t('pm2.switchToGctoac'))}</button>\n </div>\n </div>\n </div>`;\n\n const portPane = `\n <div class=\"panel data-table-panel pm2-section-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('pm2.portTitle'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('pm2.portHint'))}</span>\n </div>\n </div>\n <div class=\"panel-pad\">\n <div class=\"form-grid\">\n <label class=\"full\">${escapeHtml(t('pm2.fieldPort'))}\n <input type=\"number\" id=\"pm2-cfg-port\" min=\"1\" max=\"65535\" step=\"1\" value=\"${escapeHtml(String(d.port ?? 3850))}\" placeholder=\"3850\" />\n <span class=\"hint\">${escapeHtml(t('pm2.portDefaultNote'))}</span>\n </label>\n </div>\n <div class=\"toolbar settings-save-bar\">\n <button type=\"button\" class=\"btn sm\" id=\"pm2-port-save\">${escapeHtml(t('pm2.savePort'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"pm2-port-default\">${escapeHtml(t('pm2.useDefaultPort'))}</button>\n </div>\n </div>\n </div>`;\n\n const configPane = `\n <div class=\"panel data-table-panel pm2-section-panel\" id=\"pm2-config-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('pm2.configTitle'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('pm2.configHint'))}</span>\n </div>\n </div>\n <div class=\"panel-pad\">\n <div class=\"form-grid pm2-config-form\">\n <label>${escapeHtml(t('pm2.fieldName'))}<input id=\"pm2-cfg-name\" value=\"${escapeHtml(cfg.name || '')}\" /></label>\n <label>${escapeHtml(t('pm2.fieldScript'))}<input id=\"pm2-cfg-script\" value=\"${escapeHtml(cfg.script || 'dist/server.js')}\" /></label>\n <label>${escapeHtml(t('pm2.fieldCwd'))}<input id=\"pm2-cfg-cwd\" value=\"${escapeHtml(cfg.cwd || '')}\" placeholder=\"${escapeHtml(t('pm2.phCwd'))}\" /></label>\n <label>${escapeHtml(t('pm2.fieldInstances'))}<input id=\"pm2-cfg-instances\" value=\"${escapeHtml(String(cfg.instances ?? 1))}\" placeholder=\"${escapeHtml(t('pm2.phInstances'))}\" /></label>\n <label>${escapeHtml(t('pm2.fieldExecMode'))}\n <select id=\"pm2-cfg-exec\">\n <option value=\"fork\" ${cfg.exec_mode !== 'cluster' ? 'selected' : ''}>${escapeHtml(t('pm2.modeFork'))}</option>\n <option value=\"cluster\" ${cfg.exec_mode === 'cluster' ? 'selected' : ''}>${escapeHtml(t('pm2.modeCluster'))}</option>\n </select>\n </label>\n <label>${escapeHtml(t('pm2.fieldMaxMem'))}<input id=\"pm2-cfg-maxmem\" value=\"${escapeHtml(cfg.max_memory_restart || '512M')}\" /></label>\n <label>${escapeHtml(t('pm2.fieldMaxRestarts'))}<input id=\"pm2-cfg-maxrestarts\" type=\"number\" value=\"${escapeHtml(String(cfg.max_restarts ?? 10))}\" /></label>\n <label>${escapeHtml(t('pm2.fieldMinUptime'))}<input id=\"pm2-cfg-minuptime\" value=\"${escapeHtml(String(cfg.min_uptime ?? '5s'))}\" /></label>\n <label>${escapeHtml(t('pm2.fieldRestartDelay'))}<input id=\"pm2-cfg-restartdelay\" type=\"number\" value=\"${escapeHtml(String(cfg.restart_delay ?? 2000))}\" /></label>\n <label>${escapeHtml(t('pm2.fieldBackoff'))}<input id=\"pm2-cfg-backoff\" type=\"number\" value=\"${escapeHtml(String(cfg.exp_backoff_restart_delay ?? 1000))}\" /></label>\n <label>${escapeHtml(t('pm2.fieldErrorFile'))}<input id=\"pm2-cfg-errfile\" value=\"${escapeHtml(cfg.error_file || 'logs/pm2-error.log')}\" /></label>\n <label>${escapeHtml(t('pm2.fieldOutFile'))}<input id=\"pm2-cfg-outfile\" value=\"${escapeHtml(cfg.out_file || 'logs/pm2-out.log')}\" /></label>\n <label>${escapeHtml(t('pm2.fieldPreferred'))}\n <select id=\"pm2-cfg-preferred\">\n <option value=\"ysk-omni\" ${cfg.preferred_runner !== 'pm2' ? 'selected' : ''}>ysk-omni</option>\n <option value=\"pm2\" ${cfg.preferred_runner === 'pm2' ? 'selected' : ''}>pm2</option>\n </select>\n </label>\n <label class=\"check\"><input type=\"checkbox\" id=\"pm2-cfg-autorestart\" ${cfg.autorestart !== false ? 'checked' : ''}/> ${escapeHtml(t('pm2.fieldAutorestart'))}</label>\n <label class=\"check\"><input type=\"checkbox\" id=\"pm2-cfg-watch\" ${cfg.watch ? 'checked' : ''}/> ${escapeHtml(t('pm2.fieldWatch'))}</label>\n <label class=\"check\"><input type=\"checkbox\" id=\"pm2-cfg-mergelogs\" ${cfg.merge_logs !== false ? 'checked' : ''}/> ${escapeHtml(t('pm2.fieldMergeLogs'))}</label>\n <label class=\"check\"><input type=\"checkbox\" id=\"pm2-cfg-time\" ${cfg.time !== false ? 'checked' : ''}/> ${escapeHtml(t('pm2.fieldTime'))}</label>\n <label class=\"full\">${escapeHtml(t('pm2.fieldEnvExtra'))}<textarea id=\"pm2-cfg-envextra\" rows=\"4\" placeholder=\"${escapeHtml(t('pm2.phEnv'))}\">${escapeHtml(envExtraText)}</textarea></label>\n </div>\n <div class=\"toolbar settings-save-bar\">\n <button class=\"btn sm\" id=\"pm2-cfg-save\">${escapeHtml(t('pm2.saveConfig'))}</button>\n <button class=\"btn secondary sm\" id=\"pm2-cfg-save-only\">${escapeHtml(t('pm2.saveOnly'))}</button>\n <button class=\"btn secondary sm\" id=\"pm2-cfg-reset\">${escapeHtml(t('pm2.resetConfig'))}</button>\n </div>\n </div>\n </div>`;\n\n const logsPane = `\n <div class=\"panel data-table-panel pm2-section-panel pm2-logs-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('pm2.logs'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('pm2.logsHint'))}</span>\n </div>\n <div class=\"toolbar\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"pm2-logs-refresh\">${escapeHtml(t('pm2.refresh'))}</button>\n <button type=\"button\" class=\"btn danger sm\" id=\"pm2-logs-clear\">${escapeHtml(t('pm2.clearLogs'))}</button>\n </div>\n </div>\n <div class=\"panel-pad\">\n <p class=\"muted\" style=\"margin:0 0 8px;font-size:0.82rem\">\n ${escapeHtml(tf('pm2.logsAutoTrim', { maxMb, keepKb }))}\n ${logSizeLine ? ` · ${escapeHtml(logSizeLine)}` : ''}\n </p>\n <pre class=\"pre pre-logs\" id=\"pm2-logs-pre\">${escapeHtml(logsText || t('common.empty'))}</pre>\n </div>\n </div>`;\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('pm2.title'))}</h2>\n <div class=\"toolbar\">\n <button class=\"btn secondary sm\" id=\"pm2-refresh\">${escapeHtml(t('pm2.refresh'))}</button>\n <button class=\"btn sm\" id=\"pm2-start\" ${!canStart ? 'disabled' : ''}>${escapeHtml(t('pm2.start'))}</button>\n <button class=\"btn secondary sm\" id=\"pm2-stop\" ${!canControl ? 'disabled' : ''}>${escapeHtml(t('pm2.stop'))}</button>\n <button class=\"btn sm\" id=\"pm2-restart\" ${!canStart ? 'disabled' : ''}>${escapeHtml(t('pm2.restart'))}</button>\n <button class=\"btn secondary sm\" id=\"pm2-reload\" ${!canControl || app?.status !== 'online' ? 'disabled' : ''}>${escapeHtml(t('pm2.reload'))}</button>\n </div>\n </div>\n ${pageMetaHtml([t('pm2.hint')])}\n ${\n msg\n ? `<div class=\"error-box${isWarnOnly ? ' warn-box' : ''}\">${escapeHtml(msg)}</div>`\n : !d.available\n ? `<div class=\"error-box\">${escapeHtml(t('pm2.unavailable'))}</div>`\n : ''\n }\n ${kpiGrid}\n\n <div class=\"usage-tabs-panel panel pm2-tabs-panel\">\n <div class=\"seg-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('pm2.title'))}\">\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'runner' ? 'is-active' : ''}\" data-pm2-tab=\"runner\" aria-selected=\"${tab === 'runner'}\">\n ${escapeHtml(t('pm2.tabRunner'))}\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'port' ? 'is-active' : ''}\" data-pm2-tab=\"port\" aria-selected=\"${tab === 'port'}\">\n ${escapeHtml(t('pm2.tabPort'))}\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'config' ? 'is-active' : ''}\" data-pm2-tab=\"config\" aria-selected=\"${tab === 'config'}\">\n ${escapeHtml(t('pm2.tabConfig'))}\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'logs' ? 'is-active' : ''}\" data-pm2-tab=\"logs\" aria-selected=\"${tab === 'logs'}\">\n ${escapeHtml(t('pm2.tabLogs'))}\n </button>\n </div>\n <div class=\"usage-tab-body\">\n <div class=\"usage-tab-pane pm2-tab-pane\" id=\"pm2-tab-runner\" ${tab === 'runner' ? '' : 'hidden'}>\n ${runnerPane}\n </div>\n <div class=\"usage-tab-pane pm2-tab-pane\" id=\"pm2-tab-port\" ${tab === 'port' ? '' : 'hidden'}>\n ${portPane}\n </div>\n <div class=\"usage-tab-pane pm2-tab-pane\" id=\"pm2-tab-config\" ${tab === 'config' ? '' : 'hidden'}>\n ${configPane}\n </div>\n <div class=\"usage-tab-pane pm2-tab-pane\" id=\"pm2-tab-logs\" ${tab === 'logs' ? '' : 'hidden'}>\n ${logsPane}\n </div>\n </div>\n </div>\n `);\n bindShell();\n\n document.querySelectorAll('[data-pm2-tab]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const raw = btn.getAttribute('data-pm2-tab') || 'runner';\n const next =\n raw === 'port' || raw === 'config' || raw === 'logs' || raw === 'runner'\n ? raw\n : 'runner';\n if (state.pm2Tab === next) return;\n state.pm2Tab = next;\n renderPm2().catch(onErr);\n });\n });\n\n document.getElementById('pm2-logs-refresh')?.addEventListener('click', () => {\n state.pm2Tab = 'logs';\n renderPm2().catch(onErr);\n });\n document.getElementById('pm2-logs-clear')?.addEventListener('click', async () => {\n if (\n !(await uiConfirm({\n message: t('pm2.confirmClearLogs'),\n variant: 'danger',\n confirmText: t('pm2.clearLogs'),\n }))\n )\n return;\n try {\n const res = await api('/pm2/logs/clear', {\n method: 'POST',\n body: JSON.stringify({ which: 'all' }),\n });\n const n = res.data?.cleared?.length || 0;\n await uiAlert({\n message: tf('pm2.logsCleared', { n }),\n });\n renderPm2().catch(onErr);\n } catch (e) {\n onErr(e);\n }\n });\n\n const doSwitch = async (mode) => {\n const okConfirm = await uiConfirm({\n message:\n mode === 'pm2' ? t('pm2.confirmSwitchPm2') : t('pm2.confirmSwitchGctoac'),\n variant: 'confirm',\n confirmText:\n mode === 'pm2' ? t('pm2.switchToPm2') : t('pm2.switchToGctoac'),\n });\n if (!okConfirm) return;\n try {\n const res = await api('/pm2/switch', {\n method: 'POST',\n body: JSON.stringify({ mode }),\n });\n const payload = res?.data || res || {};\n const alertMsg = buildPm2SwitchAlertMessage(\n mode === 'pm2' ? 'pm2' : 'ysk-omni',\n payload,\n );\n // Auto F5 after 10s (server restarts under new runner)\n scheduleAdminReload(10);\n await uiAlert({\n title: t('common.notice'),\n message: alertMsg,\n confirmText: t('common.ok'),\n });\n // If user confirms early, reload immediately\n try {\n window.location.reload();\n } catch {\n window.location.href = window.location.href;\n }\n } catch (e) {\n onErr(e);\n }\n };\n\n document.getElementById('pm2-refresh').onclick = () => renderPm2().catch(onErr);\n document.getElementById('pm2-switch-pm2').onclick = () => doSwitch('pm2');\n document.getElementById('pm2-switch-ysk-omni').onclick = () => doSwitch('ysk-omni');\n document.getElementById('pm2-start').onclick = () => doSwitch('pm2');\n document.getElementById('pm2-stop').onclick = async () => {\n if (\n !(await uiConfirm({\n message: t('pm2.confirmStop'),\n variant: 'danger',\n confirmText: t('pm2.stop'),\n }))\n )\n return;\n try {\n await api('/pm2/stop', { method: 'POST', body: '{}' });\n renderPm2().catch(onErr);\n } catch (e) {\n onErr(e);\n }\n };\n document.getElementById('pm2-restart').onclick = async () => {\n if (\n !(await uiConfirm({\n message: t('pm2.confirmRestart'),\n variant: 'confirm',\n confirmText: t('pm2.restart'),\n }))\n )\n return;\n try {\n await doSwitch('pm2');\n } catch (e) {\n onErr(e);\n }\n };\n document.getElementById('pm2-reload').onclick = async () => {\n try {\n await api('/pm2/reload', { method: 'POST', body: '{}' });\n renderPm2().catch(onErr);\n } catch (e) {\n onErr(e);\n }\n };\n\n const saveCfg = async (restart) => {\n try {\n const body = { ...readPm2ConfigForm(), restart };\n if (body.port == null) {\n await uiAlert({ message: t('pm2.portInvalid') });\n return;\n }\n const res = await api('/pm2/config', {\n method: 'PUT',\n body: JSON.stringify(body),\n });\n if (res.data?.scheduled) {\n const portMsg = res.data.portChange\n ? `\\n${tf('pm2.portChangedMsg', { from: res.data.portChange.previous, to: res.data.portChange.port })}`\n : '';\n const scheduledBody =\n formatPm2Message(res.data.scheduled) ||\n t('pm2.switchScheduled');\n scheduleAdminReload(10);\n await uiAlert({\n title: t('common.notice'),\n message:\n scheduledBody +\n portMsg +\n `\\n${tf('pm2.autoRefreshIn', { n: 10 })}`,\n });\n try {\n window.location.reload();\n } catch {\n window.location.href = window.location.href;\n }\n } else {\n await uiAlert(\n res.data?.portChange\n ? tf('pm2.portSavedNeedRestart', {\n port: res.data.port,\n })\n : t('pm2.configSaved'),\n );\n renderPm2().catch(onErr);\n }\n } catch (e) {\n onErr(e);\n }\n };\n document.getElementById('pm2-cfg-save').onclick = () => saveCfg(true);\n document.getElementById('pm2-cfg-save-only').onclick = () => saveCfg(false);\n\n document.getElementById('pm2-port-default')?.addEventListener('click', () => {\n const el = document.getElementById('pm2-cfg-port');\n if (el) el.value = '3850';\n });\n document.getElementById('pm2-port-save')?.addEventListener('click', async () => {\n const port = Number(document.getElementById('pm2-cfg-port')?.value);\n if (!Number.isFinite(port) || port < 1 || port > 65535) {\n await uiAlert({ message: t('pm2.portInvalid') });\n return;\n }\n if (\n !(await uiConfirm({\n message: tf('pm2.confirmPortChange', { port }),\n variant: 'confirm',\n confirmText: t('pm2.savePort'),\n }))\n )\n return;\n try {\n const res = await api('/pm2/config', {\n method: 'PUT',\n body: JSON.stringify({ port, restart: true }),\n });\n const base =\n res.data?.scheduled?.message ||\n (res.data?.portChange\n ? tf('pm2.portChangedMsg', {\n from: res.data.portChange.previous,\n to: res.data.portChange.port,\n })\n : t('pm2.configSaved'));\n await uiAlert(base + '\\n' + tf('pm2.portAfterRestart', { port }));\n } catch (e) {\n onErr(e);\n }\n });\n document.getElementById('pm2-cfg-reset').onclick = async () => {\n if (\n !(await uiConfirm({\n message: t('pm2.confirmReset'),\n variant: 'danger',\n confirmText: t('pm2.resetConfig'),\n }))\n )\n return;\n try {\n await api('/pm2/config/reset', { method: 'POST', body: '{}' });\n renderPm2().catch(onErr);\n } catch (e) {\n onErr(e);\n }\n };\n}\n\n\n/**\n * @typedef {{ role: string, content: string, reasoning?: string, streaming?: boolean, error?: boolean, docs?: { id: string, name: string }[] }} ChatMsg\n */\n/** @type {ChatMsg[]} */\nlet chatMessages = [];\n/** @type {AbortController | null} */\nlet chatAbort = null;\n/** Pending attachments for next send: { id, name, mime, size } */\nlet chatPendingDocs = [];\n/** True while LLM compress is in flight */\nlet chatCompressing = false;\n/** How many older messages are folded (render window) */\nlet chatRenderSkip = 0;\n/** @type {Map<string, string>} */\nconst chatMdCache = new Map();\n\n/** UI prefs preserved across re-renders */\nconst chatUi = {\n /** selected API key id; empty = signed-in admin key */\n keyId: '',\n model: '',\n reasoning: true,\n /** Reasoning effort; empty = engine default */\n effort: '',\n /** Session UUID */\n resumeId: '',\n forkSession: false,\n memory: false,\n noPlan: false,\n permissionMode: '',\n /** optional system prompt (sent every turn, not stored in chat history bubbles) */\n systemPrompt: '',\n systemOpen: false,\n /** mobile: full toolbar is collapsed so the transcript stays visible */\n settingsOpen: false,\n};\n\n/**\n * Context policy for API turns — does NOT rewrite chatMessages.\n * @type {{ mode: 'full'|'summary'|'recent', recentN: number, summary: string, summaryAt: string|null, summarySourceCount: number }}\n */\nconst chatContext = {\n mode: 'full',\n recentN: 6,\n summary: '',\n summaryAt: null,\n summarySourceCount: 0,\n};\n\nconst CHAT_COMPRESS_MIN_MSGS = 3;\nconst CHAT_RENDER_WINDOW = 40;\nconst CHAT_RENDER_STEP = 20;\nconst CHAT_CONTENT_COLLAPSE = 2200;\n\n/** Persisted multi-turn conversation session (playground) */\nconst chatSession = {\n conversationId: null,\n historyPage: 0,\n historyLimit: 20,\n historyQ: '',\n historyTotal: 0,\n historyItems: [],\n historyLoading: false,\n historyOpenMobile: false,\n saving: false,\n saveQueued: false,\n /** conversation id currently editing title inline */\n renamingId: null,\n};\n/** @type {ReturnType<typeof setTimeout> | null} */\nlet chatHistorySearchTimer = null;\n\nconst CHAT_MAX_DOCS = 10;\n\n/** UUID v1–v8 (loose) — match backend z.string().uuid() */\nconst DOC_ID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\nfunction chatFileExt(name) {\n const base = String(name || '').split(/[/\\\\]/).pop() || '';\n const i = base.lastIndexOf('.');\n if (i < 0) return '';\n return base.slice(i).toLowerCase();\n}\n\nfunction isChatAllowedFilename(name) {\n return CHAT_ALLOWED_EXTENSIONS.has(chatFileExt(name));\n}\n\nfunction chatFormatsShort() {\n return t('chat.formatsHint');\n}\n\nfunction resetChatContext() {\n chatContext.mode = 'full';\n chatContext.recentN = 6;\n chatContext.summary = '';\n chatContext.summaryAt = null;\n chatContext.summarySourceCount = 0;\n chatRenderSkip = 0;\n chatMdCache.clear();\n}\n\nfunction conversationDisplayTitle(item) {\n const title = (item?.title || '').trim();\n if (title) return title;\n const preview = (item?.preview || '').trim();\n if (preview) return preview;\n return t('chat.untitled');\n}\n\nfunction messagesForSave() {\n return chatMessages\n .filter((m) => !m.streaming)\n .map((m) => {\n /** @type {{ role: string, content: string, reasoning?: string, docs?: {id:string,name:string}[], error?: boolean }} */\n const out = {\n role: m.role,\n content: m.content || '',\n };\n if (m.reasoning) out.reasoning = m.reasoning;\n if (m.docs && m.docs.length) out.docs = m.docs;\n if (m.error) out.error = true;\n return out;\n });\n}\n\nfunction contextPayloadForSave() {\n return {\n contextMode: chatContext.mode,\n contextRecentN: chatContext.recentN,\n summaryText: chatContext.summary || '',\n summaryAt: chatContext.summaryAt,\n summarySourceCount: chatContext.summarySourceCount || 0,\n };\n}\n\nfunction applyContextFromApi(data) {\n if (!data) return;\n chatContext.mode =\n data.contextMode === 'summary' || data.contextMode === 'recent'\n ? data.contextMode\n : 'full';\n chatContext.recentN = Math.min(\n 40,\n Math.max(2, Number(data.contextRecentN) || 6),\n );\n chatContext.summary = (data.summaryText || '').trim();\n chatContext.summaryAt = data.summaryAt || null;\n chatContext.summarySourceCount = Number(data.summarySourceCount) || 0;\n if (chatContext.mode === 'summary' && !chatContext.summary) {\n chatContext.mode = 'full';\n }\n}\n\nfunction chatMessageChars(msgs) {\n return msgs.reduce(\n (n, m) => n + (m.content || '').length + (m.reasoning || '').length,\n 0,\n );\n}\n\nfunction chatCompressEligible() {\n const ready = chatMessages.filter((m) => !m.streaming);\n if (ready.length < 2) return false;\n if (ready.length >= CHAT_COMPRESS_MIN_MSGS) return true;\n return chatMessageChars(ready) >= 800;\n}\n\n/**\n * Build messages array for playground API based on context policy.\n * Full history stays in chatMessages / UI.\n */\nfunction buildApiMessages() {\n const systemBase = (chatUi.systemPrompt || '').trim();\n const ready = chatMessages.filter((m) => !m.streaming);\n const n = Math.min(\n 40,\n Math.max(2, Number(chatContext.recentN) || 6),\n );\n\n /** @type {{ role: string, content: string }[]} */\n let slice = ready.map((m) => ({\n role: m.role,\n content: m.content || '',\n }));\n\n let system = systemBase;\n\n if (chatContext.mode === 'summary' && chatContext.summary) {\n const summaryBlock =\n (getLocale() === 'zh-Hant'\n ? '【先前對話摘要 — 僅供延續語境,完整記錄仍在用戶介面】\\n'\n : '[Prior conversation summary — full history remains in the UI]\\n') +\n chatContext.summary;\n system = system\n ? `${system}\\n\\n${summaryBlock}`\n : summaryBlock;\n // Prefer messages after summary was made; else last N\n const after = ready.slice(chatContext.summarySourceCount || 0);\n const tailSrc = after.length ? after : ready.slice(-n);\n slice = tailSrc.slice(-n).map((m) => ({\n role: m.role,\n content: m.content || '',\n }));\n } else if (chatContext.mode === 'recent') {\n slice = ready.slice(-n).map((m) => ({\n role: m.role,\n content: m.content || '',\n }));\n }\n\n /** @type {{ role: string, content: string }[]} */\n const api = slice.map((m) => ({ role: m.role, content: m.content }));\n if (system) api.unshift({ role: 'system', content: system });\n return api;\n}\n\nfunction contextModeLabel() {\n if (chatContext.mode === 'summary' && chatContext.summary) {\n return tf('chat.ctxModeSummaryLabel', { n: chatContext.recentN });\n }\n if (chatContext.mode === 'recent') {\n return tf('chat.ctxModeRecentLabel', { n: chatContext.recentN });\n }\n return t('chat.ctxModeFullLabel');\n}\n\nfunction updateChatCompressButton() {\n const btn = document.getElementById('chat-compress');\n if (!btn) return;\n const streaming = chatMessages.some((m) => m.streaming);\n const busy = Boolean(chatAbort) || chatCompressing || streaming;\n const ok = chatCompressEligible();\n btn.disabled = busy || !ok;\n btn.textContent = chatCompressing ? t('chat.compressing') : t('chat.compress');\n btn.title = !ok ? t('chat.compressNeedMore') : t('chat.compress');\n paintContextBanner();\n syncContextControls();\n}\n\nfunction syncContextControls() {\n const modeEl = document.getElementById('chat-ctx-mode');\n const nEl = document.getElementById('chat-ctx-n');\n if (modeEl) {\n const m =\n chatContext.mode === 'summary' && !chatContext.summary\n ? 'full'\n : chatContext.mode;\n modeEl.value = m;\n // disable summary option if no summary\n const optSum = modeEl.querySelector('option[value=\"summary\"]');\n if (optSum) optSum.disabled = !chatContext.summary;\n }\n if (nEl) {\n nEl.value = String(chatContext.recentN);\n nEl.disabled = chatContext.mode === 'full';\n }\n paintChatSettingsBar();\n}\n\nfunction paintContextBanner() {\n const host = document.getElementById('chat-compress-banner');\n if (!host) return;\n const hasSummary = Boolean(chatContext.summary);\n const longThread =\n chatMessages.filter((m) => !m.streaming).length > 40 ||\n chatMessageChars(chatMessages) > 60000;\n\n if (!hasSummary && chatContext.mode === 'full' && !longThread) {\n host.hidden = true;\n host.innerHTML = '';\n return;\n }\n\n host.hidden = false;\n const preview = hasSummary\n ? chatContext.summary.length > 160\n ? `${chatContext.summary.slice(0, 159)}…`\n : chatContext.summary\n : '';\n const warn = longThread\n ? `<p class=\"chat-compress-warn\">${escapeHtml(t('chat.ctxLongHint'))}</p>`\n : '';\n\n host.innerHTML = `\n <div class=\"chat-compress-banner-inner\">\n <div class=\"chat-compress-banner-text\">\n <strong>${escapeHtml(t('chat.ctxPolicyTitle'))}</strong>\n <span class=\"muted\">${escapeHtml(contextModeLabel())}</span>\n <p class=\"chat-compress-remark\">${escapeHtml(t('chat.ctxRemark'))}</p>\n ${preview ? `<p class=\"chat-compress-preview\">${escapeHtml(preview)}</p>` : ''}\n ${warn}\n </div>\n <div class=\"chat-compress-banner-actions\">\n ${\n hasSummary\n ? `<button type=\"button\" class=\"btn secondary sm\" id=\"chat-summary-view\">${escapeHtml(t('chat.compressView'))}</button>`\n : ''\n }\n </div>\n </div>`;\n document.getElementById('chat-summary-view')?.addEventListener('click', () => {\n openSummaryPopup();\n });\n}\n\nasync function openSummaryPopup() {\n if (!chatContext.summary) {\n showError(t('chat.compressNeedSummary'));\n return;\n }\n const when = chatContext.summaryAt\n ? fmtTime(chatContext.summaryAt)\n : '—';\n const bodyHtml = formatChatMarkdown(chatContext.summary);\n // Custom large dialog\n if (uiDialogRoot) closeUiDialog(false);\n const root = document.createElement('div');\n root.className = 'ui-dialog-back';\n root.id = 'ui-dialog-back';\n root.dataset.cancelable = '1';\n root.innerHTML = `\n <div class=\"ui-dialog ui-dialog--info ui-dialog--large\" role=\"dialog\" aria-modal=\"true\">\n <div class=\"ui-dialog-h\">\n <div class=\"ui-dialog-icon\" aria-hidden=\"true\">Σ</div>\n <h3 class=\"ui-dialog-title\">${escapeHtml(t('chat.compressResultTitle'))}</h3>\n </div>\n <div class=\"ui-dialog-body ui-dialog-body--md\">\n <p class=\"muted\" style=\"margin:0 0 10px\">${escapeHtml(tf('chat.summaryMeta', { when, n: chatContext.summarySourceCount }))}</p>\n <div class=\"chat-content md\">${bodyHtml}</div>\n </div>\n <div class=\"ui-dialog-actions\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"ui-dialog-copy\">${escapeHtml(t('chat.copy'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"ui-dialog-ok\">${escapeHtml(t('common.ok'))}</button>\n </div>\n </div>`;\n document.body.appendChild(root);\n document.body.classList.add('ui-dialog-open');\n uiDialogRoot = root;\n document.addEventListener('keydown', onUiDialogKeydown, true);\n return new Promise((resolve) => {\n uiDialogResolve = resolve;\n const finish = () => closeUiDialog(true);\n root.querySelector('#ui-dialog-ok')?.addEventListener('click', finish);\n root.addEventListener('click', (e) => {\n if (e.target === root) finish();\n });\n root.querySelector('#ui-dialog-copy')?.addEventListener('click', async () => {\n const ok = await copyTextToClipboard(chatContext.summary);\n const b = root.querySelector('#ui-dialog-copy');\n if (ok && b) {\n b.textContent = t('chat.copied');\n setTimeout(() => {\n if (b.isConnected) b.textContent = t('chat.copy');\n }, 1500);\n }\n });\n });\n}\n\nfunction buildCompressTranscript(msgs) {\n return msgs\n .map((m) => {\n const role = m.role || 'user';\n let body = (m.content || '').trim();\n if (m.docs && m.docs.length) {\n const names = m.docs.map((d) => d.name).join(', ');\n body = body\n ? `${body}\\n[attachments: ${names}]`\n : `[attachments: ${names}]`;\n }\n if (body.length > 5000) body = `${body.slice(0, 4999)}…`;\n return `${role}: ${body}`;\n })\n .join('\\n\\n');\n}\n\nfunction compressSystemPrompt() {\n if (getLocale() === 'zh-Hant') {\n return [\n '你是對話摘要助手。只輸出精簡摘要,不要使用任何工具、不要上網、不要反問。',\n '若已有舊摘要,請合併更新為一份。',\n '請用繁體中文(或對齊原對話語言)條列:',\n '1) 主題與目標 2) 已確定事實/決定 3) 未完成事項 4) 用戶偏好或約束',\n '控制在約 600–1000 字。不要大段複製原文。只輸出摘要正文。',\n ].join('\\n');\n }\n return [\n 'You are a conversation summary assistant. Output only a concise summary.',\n 'Merge any prior summary into one updated summary. No tools, no browsing, no questions.',\n 'Cover: (1) topics/goals (2) facts/decisions (3) open items (4) preferences.',\n 'Keep under ~600–1000 words. Summary body only.',\n ].join('\\n');\n}\n\n/**\n * Generate summary for context policy — never mutates chatMessages.\n */\nasync function compressChatHistory() {\n if (chatCompressing || chatAbort || chatMessages.some((m) => m.streaming)) {\n showError(t('chat.compressBusy'));\n return;\n }\n const ready = chatMessages.filter((m) => !m.streaming);\n if (!chatCompressEligible()) {\n showError(t('chat.compressNeedMore'));\n return;\n }\n if (\n !(await uiConfirm({\n title: t('chat.compress'),\n message: t('chat.compressConfirm'),\n variant: 'confirm',\n confirmText: t('chat.compress'),\n }))\n )\n return;\n\n const auth = playgroundAuthKey();\n if (!auth) {\n showError(t('chat.needKey'));\n return;\n }\n\n captureChatUi();\n chatCompressing = true;\n updateChatCompressButton();\n const sendBtn = document.getElementById('chat-send');\n if (sendBtn) sendBtn.disabled = true;\n const st = document.getElementById('chat-stream-status');\n if (st) {\n st.hidden = false;\n st.textContent = t('chat.compressing');\n }\n\n try {\n // Include previous summary in input so re-compress merges\n let transcript = buildCompressTranscript(ready);\n if (chatContext.summary) {\n transcript =\n (getLocale() === 'zh-Hant'\n ? `先前摘要:\\n${chatContext.summary}\\n\\n完整對話:\\n`\n : `Prior summary:\\n${chatContext.summary}\\n\\nFull conversation:\\n`) +\n transcript;\n }\n\n let model =\n document.getElementById('chat-model')?.value ||\n chatUi.model ||\n 'echo';\n if (classifyPlaygroundKind(model, state.catalogLocal) !== 'text') {\n model =\n (state.catalogLocal || []).find((m) => m.runtime === 'llamacpp')?.id ||\n 'echo';\n }\n const asKeyId = playgroundKeyId();\n const body = {\n model,\n stream: false,\n include_reasoning: false,\n messages: [\n { role: 'system', content: compressSystemPrompt() },\n {\n role: 'user',\n content:\n (getLocale() === 'zh-Hant'\n ? '請為以下對話產生摘要(僅供之後回合作為語境,不會刪除用戶介面中的記錄):\\n\\n'\n : 'Summarize the following conversation (for later context only; UI history is kept):\\n\\n') +\n transcript,\n },\n ],\n };\n const realKeyId = playgroundRealApiKeyId();\n if (realKeyId) body.apiKeyId = realKeyId;\n\n const res = await fetch('/admin/api/chat/completions', {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${auth}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const errText = await res.text();\n let msg = errText;\n try {\n const j = JSON.parse(errText);\n msg = j.error?.message || errText;\n } catch {\n /* */\n }\n throw new Error(msg || t('chat.compressFail'));\n }\n const json = await res.json();\n let summary =\n json?.choices?.[0]?.message?.content ||\n json?.choices?.[0]?.delta?.content ||\n '';\n if (typeof summary !== 'string') summary = String(summary || '');\n summary = summary\n .trim()\n .replace(/^【對話摘要】\\s*/u, '')\n .replace(/^\\[Conversation summary\\]\\s*/i, '');\n if (!summary) throw new Error(t('chat.compressFail'));\n\n chatContext.summary = summary;\n chatContext.summaryAt = new Date().toISOString();\n chatContext.summarySourceCount = ready.length;\n chatContext.mode = 'summary';\n // history untouched\n paintContextBanner();\n syncContextControls();\n showError('');\n if (st) {\n st.hidden = false;\n st.textContent = t('chat.compressOk');\n setTimeout(() => {\n const s2 = document.getElementById('chat-stream-status');\n if (s2 && s2.textContent === t('chat.compressOk')) {\n s2.hidden = true;\n s2.textContent = '';\n }\n }, 2800);\n }\n await saveConversation().catch(() => {});\n await openSummaryPopup();\n } catch (e) {\n showError(e.message || t('chat.compressFail'));\n } finally {\n chatCompressing = false;\n updateChatCompressButton();\n if (sendBtn) sendBtn.disabled = false;\n if (st && st.textContent === t('chat.compressing')) {\n st.hidden = true;\n st.textContent = '';\n }\n }\n}\n\nfunction setChatHistoryMobileOpen(open) {\n chatSession.historyOpenMobile = Boolean(open);\n document.body.classList.toggle('chat-history-open', chatSession.historyOpenMobile);\n}\n\nfunction closeChatHistoryMobile() {\n setChatHistoryMobileOpen(false);\n}\n\nasync function loadConversationList() {\n if (!state.key) return;\n chatSession.historyLoading = true;\n paintChatHistoryList();\n try {\n const offset = chatSession.historyPage * chatSession.historyLimit;\n const params = new URLSearchParams({\n limit: String(chatSession.historyLimit),\n offset: String(offset),\n });\n if (chatSession.historyQ.trim()) {\n params.set('q', chatSession.historyQ.trim());\n }\n const res = await api(`/conversations?${params}`);\n chatSession.historyItems = res.data || [];\n chatSession.historyTotal = res.total ?? 0;\n } catch (e) {\n chatSession.historyItems = [];\n chatSession.historyTotal = 0;\n // soft fail — rail stays usable\n console.warn(e);\n } finally {\n chatSession.historyLoading = false;\n paintChatHistoryList();\n }\n}\n\nfunction paintChatHistoryList() {\n const list = document.getElementById('chat-history-list');\n const pager = document.getElementById('chat-history-pager');\n if (!list) return;\n\n if (chatSession.historyLoading && !chatSession.historyItems.length) {\n list.innerHTML = `<li class=\"chat-history-empty\">${escapeHtml(t('common.loading'))}</li>`;\n } else if (!chatSession.historyItems.length) {\n list.innerHTML = `<li class=\"chat-history-empty\">${escapeHtml(t('chat.historyEmpty'))}</li>`;\n } else {\n list.innerHTML = chatSession.historyItems\n .map((item) => {\n const active =\n chatSession.conversationId === item.id ? ' is-active' : '';\n const title = conversationDisplayTitle(item);\n const preview =\n item.title && item.preview && item.preview !== item.title\n ? item.preview\n : item.model || tf('chat.msgs', { n: item.messageCount || 0 });\n const isRenaming = chatSession.renamingId === item.id;\n // Prefill with what the user currently sees (custom title or preview/untitled)\n const editValue = title;\n const bodyInner = isRenaming\n ? `<input type=\"text\" class=\"chat-history-title-input\" data-title-input=\"${escapeHtml(item.id)}\" value=\"${escapeHtml(editValue)}\" maxlength=\"120\" placeholder=\"${escapeHtml(t('chat.renamePh'))}\" aria-label=\"${escapeHtml(t('chat.renamePh'))}\" />\n <span class=\"preview\">${escapeHtml(preview || '—')}</span>\n <span class=\"meta\"><span>${escapeHtml(fmtTime(item.updatedAt))}</span></span>`\n : `<span class=\"title\" data-title-label=\"${escapeHtml(item.id)}\" title=\"${escapeHtml(t('chat.rename'))}\">${escapeHtml(title)}</span>\n <span class=\"preview\">${escapeHtml(preview || '—')}</span>\n <span class=\"meta\"><span>${escapeHtml(fmtTime(item.updatedAt))}</span></span>`;\n // Never put <input> inside <button> — invalid HTML\n const main = isRenaming\n ? `<div class=\"chat-history-item${active} is-editing\" data-conv-body=\"${escapeHtml(item.id)}\">${bodyInner}</div>`\n : `<div class=\"chat-history-item${active}\" data-open-conv=\"${escapeHtml(item.id)}\" role=\"button\" tabindex=\"0\" title=\"${escapeHtml(title)}\">${bodyInner}</div>`;\n return `\n <li class=\"chat-history-row${active}${isRenaming ? ' is-renaming' : ''}\" data-conv-row=\"${escapeHtml(item.id)}\">\n ${main}\n <div class=\"chat-history-item-actions\">\n <button type=\"button\" class=\"icon-action\" data-rename-conv=\"${escapeHtml(item.id)}\" title=\"${escapeHtml(t('chat.rename'))}\" aria-label=\"${escapeHtml(t('chat.rename'))}\">✎</button>\n <button type=\"button\" class=\"icon-action danger\" data-del-conv=\"${escapeHtml(item.id)}\" title=\"${escapeHtml(t('chat.deleteConversation'))}\" aria-label=\"${escapeHtml(t('chat.deleteConversation'))}\">×</button>\n </div>\n </li>`;\n })\n .join('');\n }\n\n if (pager) {\n const limit = chatSession.historyLimit;\n const totalPages = Math.max(1, Math.ceil(chatSession.historyTotal / limit) || 1);\n const page = Math.min(chatSession.historyPage + 1, totalPages);\n const pageLabel = tf('chat.historyPage', { n: page, total: totalPages });\n const canPrev = chatSession.historyPage > 0;\n const canNext =\n (chatSession.historyPage + 1) * limit < chatSession.historyTotal;\n pager.innerHTML = `\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-hist-prev\" ${canPrev ? '' : 'disabled'}>${escapeHtml(t('chat.historyPrev'))}</button>\n <span>${escapeHtml(pageLabel)}</span>\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-hist-next\" ${canNext ? '' : 'disabled'}>${escapeHtml(t('chat.historyNext'))}</button>\n `;\n const prev = document.getElementById('chat-hist-prev');\n const next = document.getElementById('chat-hist-next');\n if (prev) {\n prev.onclick = () => {\n if (chatSession.historyPage > 0) {\n chatSession.historyPage -= 1;\n loadConversationList();\n }\n };\n }\n if (next) {\n next.onclick = () => {\n if ((chatSession.historyPage + 1) * limit < chatSession.historyTotal) {\n chatSession.historyPage += 1;\n loadConversationList();\n }\n };\n }\n }\n\n // Single-click open (delayed) vs double-click rename — avoid open wiping the row mid-dblclick\n list.querySelectorAll('[data-open-conv]').forEach((el) => {\n const id = el.getAttribute('data-open-conv');\n if (!id) return;\n /** @type {ReturnType<typeof setTimeout> | null} */\n let openTimer = null;\n const clearOpen = () => {\n if (openTimer) {\n clearTimeout(openTimer);\n openTimer = null;\n }\n };\n el.addEventListener('click', (e) => {\n if (chatSession.renamingId) return;\n // ignore clicks that originated on action buttons (they stopPropagation too)\n if (e.target instanceof Element && e.target.closest('.chat-history-item-actions')) {\n return;\n }\n clearOpen();\n openTimer = setTimeout(() => {\n openTimer = null;\n if (chatSession.renamingId) return;\n openConversation(id);\n }, 280);\n });\n el.addEventListener('dblclick', (e) => {\n e.preventDefault();\n e.stopPropagation();\n clearOpen();\n startInlineRename(id);\n });\n el.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (!chatSession.renamingId) openConversation(id);\n }\n });\n });\n // Title label: also start rename on dblclick (same as row)\n list.querySelectorAll('[data-title-label]').forEach((el) => {\n el.addEventListener('dblclick', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const id = el.getAttribute('data-title-label');\n if (id) startInlineRename(id);\n });\n });\n list.querySelectorAll('[data-rename-conv]').forEach((el) => {\n el.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const id = el.getAttribute('data-rename-conv');\n if (id) startInlineRename(id);\n });\n });\n list.querySelectorAll('[data-del-conv]').forEach((el) => {\n el.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const id = el.getAttribute('data-del-conv');\n if (id) deleteConversation(id);\n });\n });\n\n // Focus title input if we just entered rename mode\n if (chatSession.renamingId) {\n const rid = String(chatSession.renamingId).replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n const input = list.querySelector(`[data-title-input=\"${rid}\"]`);\n if (input instanceof HTMLInputElement) {\n bindTitleInput(input, chatSession.renamingId);\n // rAF so layout is ready before select()\n requestAnimationFrame(() => {\n if (!input.isConnected) return;\n input.focus();\n input.select();\n });\n }\n }\n}\n\n/**\n * Begin inline title edit at the history list title position (no window.prompt).\n * @param {string} id\n */\nfunction startInlineRename(id) {\n if (!id) return;\n // Cancel any other rename\n if (chatSession.renamingId && chatSession.renamingId !== id) {\n chatSession.renamingId = null;\n }\n chatSession.renamingId = id;\n paintChatHistoryList();\n}\n\n/**\n * @param {HTMLInputElement} input\n * @param {string} id\n */\nfunction bindTitleInput(input, id) {\n let finished = false;\n const finish = async (save) => {\n if (finished) return;\n finished = true;\n const raw = input.value;\n chatSession.renamingId = null;\n if (!save) {\n paintChatHistoryList();\n return;\n }\n const title = String(raw ?? '')\n .trim()\n .slice(0, 120);\n const item = chatSession.historyItems.find((x) => x.id === id);\n const prevStored = item ? (item.title || '').trim() : '';\n // Skip only when unchanged vs stored custom title\n // (if stored empty, saving the displayed text pins it as custom title)\n if (title === prevStored) {\n paintChatHistoryList();\n return;\n }\n // Optimistic UI\n if (item) item.title = title;\n paintChatHistoryList();\n try {\n await api(`/conversations/${id}`, {\n method: 'PATCH',\n body: JSON.stringify({ title }),\n });\n await loadConversationList();\n } catch (e) {\n showError(e.message || t('chat.saveFail'));\n await loadConversationList();\n }\n };\n\n input.addEventListener('keydown', (e) => {\n e.stopPropagation();\n if (e.key === 'Enter') {\n e.preventDefault();\n finish(true);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n finish(false);\n }\n });\n input.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n input.addEventListener('mousedown', (e) => e.stopPropagation());\n input.addEventListener('dblclick', (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n input.addEventListener('blur', () => {\n setTimeout(() => finish(true), 0);\n });\n}\n\nasync function renameConversation(id) {\n // Back-compat alias\n startInlineRename(id);\n}\n\nasync function openConversation(id) {\n if (!id || chatAbort) {\n if (chatAbort) chatAbort.abort();\n }\n try {\n showError('');\n const res = await api(`/conversations/${id}`);\n const data = res.data || res;\n chatSession.conversationId = data.id;\n chatRenderSkip = 0;\n chatMdCache.clear();\n chatMessages = (data.messages || [])\n .filter((m) => !m.compressed)\n .map((m) => ({\n role: m.role,\n content: m.content || '',\n reasoning: m.reasoning || undefined,\n docs: m.docs,\n error: m.error,\n }));\n chatPendingDocs = [];\n chatUi.systemPrompt = data.systemPrompt || '';\n applyContextFromApi(data);\n if (data.model) chatUi.model = data.model;\n if (data.apiKeyId) {\n chatUi.keyId = data.apiKeyId;\n }\n // sync form controls if present\n const sysEl = document.getElementById('chat-system');\n if (sysEl) sysEl.value = chatUi.systemPrompt;\n const wrap = document.getElementById('chat-system-wrap');\n if (wrap) wrap.hidden = !chatUi.systemPrompt.trim() && !chatUi.systemOpen;\n const modelEl = document.getElementById('chat-model');\n if (modelEl && data.model) modelEl.value = data.model;\n const keyEl = document.getElementById('chat-key-select');\n if (keyEl && data.apiKeyId) {\n const has = [...keyEl.options].some((o) => o.value === data.apiKeyId);\n if (has) {\n keyEl.value = data.apiKeyId;\n chatUi.keyId = data.apiKeyId;\n }\n }\n renderChatBubbles();\n renderChatPending();\n paintChatHistoryList();\n paintContextBanner();\n syncContextControls();\n closeChatHistoryMobile();\n } catch (e) {\n showError(e.message || t('chat.loadFail'));\n }\n}\n\n/** Real API key UUID only — never send OTP session synthetic ids to validators. */\nfunction playgroundRealApiKeyId() {\n const id = playgroundKeyId();\n if (!id) return null;\n if (String(id).startsWith('admin-session:')) return null;\n // basic uuid shape\n if (\n !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(\n id,\n )\n ) {\n return null;\n }\n return id;\n}\n\nasync function saveConversation() {\n const messages = messagesForSave();\n if (!messages.length && !chatContext.summary) return;\n if (chatSession.saving) {\n chatSession.saveQueued = true;\n return;\n }\n chatSession.saving = true;\n chatSession.saveQueued = false;\n captureChatUi();\n const body = {\n messages,\n model: chatUi.model || null,\n systemPrompt: chatUi.systemPrompt || '',\n apiKeyId: playgroundRealApiKeyId(),\n ...contextPayloadForSave(),\n };\n try {\n if (chatSession.conversationId) {\n await api(`/conversations/${chatSession.conversationId}`, {\n method: 'PATCH',\n body: JSON.stringify(body),\n });\n } else {\n if (!messages.length) return;\n const res = await api('/conversations', {\n method: 'POST',\n body: JSON.stringify({ ...body, title: '' }),\n });\n const data = res.data || res;\n chatSession.conversationId = data.id;\n }\n await loadConversationList();\n } catch (e) {\n console.warn(e);\n // non-blocking — keep chat usable\n } finally {\n chatSession.saving = false;\n if (chatSession.saveQueued) {\n chatSession.saveQueued = false;\n saveConversation().catch(() => {});\n }\n }\n}\n\nasync function deleteConversation(id) {\n if (\n !(await uiConfirm({\n title: t('chat.deleteConversation'),\n message: t('chat.deleteConfirm'),\n variant: 'danger',\n confirmText: t('chat.deleteConversation'),\n }))\n )\n return;\n try {\n await api(`/conversations/${id}`, { method: 'DELETE' });\n if (chatSession.conversationId === id) {\n chatSession.conversationId = null;\n chatMessages = [];\n chatPendingDocs = [];\n resetChatContext();\n renderChatBubbles();\n renderChatPending();\n paintContextBanner();\n syncContextControls();\n }\n // if page emptied, go back a page\n if (\n chatSession.historyItems.length <= 1 &&\n chatSession.historyPage > 0\n ) {\n chatSession.historyPage -= 1;\n }\n await loadConversationList();\n } catch (e) {\n showError(e.message || t('common.requestFailed'));\n }\n}\n\nfunction resetChatThread(keepSystem = true) {\n if (chatAbort) chatAbort.abort();\n chatMessages = [];\n chatPendingDocs = [];\n chatSession.conversationId = null;\n resetChatContext();\n if (!keepSystem) {\n chatUi.systemPrompt = '';\n chatUi.systemOpen = false;\n }\n renderChatBubbles();\n renderChatPending();\n paintChatHistoryList();\n paintContextBanner();\n syncContextControls();\n}\n\n/** Signed-in admin bearer (always used for Admin API). */\nfunction playgroundAuthKey() {\n return state.key;\n}\n\n/** Selected key id for acting as (session me.id when empty). */\nfunction playgroundKeyId() {\n const el = document.getElementById('chat-key-select');\n const v = el?.value || chatUi.keyId || '';\n if (v && v !== 'session') return v;\n return state.me?.id || '';\n}\n\nfunction captureChatUi() {\n const keyEl = document.getElementById('chat-key-select');\n const modelEl = document.getElementById('chat-model');\n const reasonEl = document.getElementById('chat-reasoning');\n const sysEl = document.getElementById('chat-system');\n if (keyEl) chatUi.keyId = keyEl.value === 'session' ? '' : keyEl.value;\n if (modelEl) chatUi.model = modelEl.value;\n if (reasonEl) chatUi.reasoning = reasonEl.checked;\n const effortEl = document.getElementById('chat-effort');\n if (effortEl) chatUi.effort = effortEl.value || '';\n const resumeEl = document.getElementById('chat-resume');\n if (resumeEl) chatUi.resumeId = resumeEl.value.trim();\n const forkEl = document.getElementById('chat-fork');\n if (forkEl) chatUi.forkSession = forkEl.checked;\n const memEl = document.getElementById('chat-memory');\n if (memEl) chatUi.memory = memEl.checked;\n const planEl = document.getElementById('chat-no-plan');\n if (planEl) chatUi.noPlan = planEl.checked;\n const permEl = document.getElementById('chat-perm');\n if (permEl) chatUi.permissionMode = permEl.value || '';\n if (sysEl) chatUi.systemPrompt = sysEl.value;\n paintChatSettingsBar();\n}\n\nfunction paintChatSettingsBar() {\n const shellEl = document.querySelector('.chat-shell');\n const btn = document.getElementById('chat-settings-toggle');\n const sum = document.getElementById('chat-settings-summary');\n const lab = document.getElementById('chat-settings-toggle-label');\n if (shellEl) {\n shellEl.classList.toggle('is-settings-open', Boolean(chatUi.settingsOpen));\n }\n if (btn) btn.setAttribute('aria-expanded', chatUi.settingsOpen ? 'true' : 'false');\n if (lab) {\n lab.textContent = chatUi.settingsOpen ? t('chat.settingsHide') : t('chat.settings');\n }\n if (sum) {\n const model = chatUi.model || '—';\n const modeKey =\n chatContext.mode === 'summary'\n ? 'chat.ctxModeSummary'\n : chatContext.mode === 'recent'\n ? 'chat.ctxModeRecent'\n : 'chat.ctxModeFull';\n sum.textContent = `${model} · ${t(modeKey)}`;\n }\n}\n\nfunction renderChatPending() {\n const wrap = document.getElementById('chat-pending');\n if (!wrap) return;\n if (!chatPendingDocs.length) {\n wrap.innerHTML = '';\n wrap.hidden = true;\n return;\n }\n wrap.hidden = false;\n wrap.innerHTML = chatPendingDocs\n .map(\n (d, i) => `\n <div class=\"chat-pending-item\" title=\"${escapeHtml(d.name)}\">\n <span class=\"name\">${escapeHtml(d.name)}</span>\n <span class=\"muted\">${fmtBytes(d.size)}</span>\n <button type=\"button\" class=\"rm\" data-rm-doc=\"${i}\" aria-label=\"${escapeHtml(t('chat.removeFile'))}\">×</button>\n </div>`,\n )\n .join('');\n wrap.querySelectorAll('[data-rm-doc]').forEach((btn) => {\n btn.onclick = () => {\n const idx = Number(btn.getAttribute('data-rm-doc'));\n chatPendingDocs.splice(idx, 1);\n renderChatPending();\n };\n });\n}\n\nfunction mdCacheKey(idx, content) {\n return `${idx}:${(content || '').length}:${(content || '').slice(0, 40)}`;\n}\n\nfunction renderChatBubbles() {\n const box = document.getElementById('chat-messages');\n if (!box) return;\n const nearBottom = box.scrollHeight - box.scrollTop - box.clientHeight < 120;\n const streaming = chatMessages.some((m) => m.streaming);\n\n // Live status under composer\n const st = document.getElementById('chat-stream-status');\n if (st) {\n st.hidden = !streaming;\n st.textContent = streaming ? t('chat.streaming') : '';\n }\n\n if (!chatMessages.length) {\n box.innerHTML = `\n <div class=\"chat-empty\">\n <strong>${escapeHtml(t('chat.emptyTitle'))}</strong>\n <p>${escapeHtml(t('chat.emptyHint'))}</p>\n </div>`;\n updateChatCompressButton();\n return;\n }\n\n // Render window: only last N + skip (load more expands)\n const total = chatMessages.length;\n const maxSkip = Math.max(0, total - CHAT_RENDER_WINDOW);\n if (chatRenderSkip > maxSkip) chatRenderSkip = maxSkip;\n const start = chatRenderSkip;\n const visible = chatMessages.slice(start);\n const hiddenCount = start;\n\n const foldBar =\n hiddenCount > 0\n ? `<div class=\"chat-load-older\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-load-older\">${escapeHtml(tf('chat.loadOlder', { n: hiddenCount }))}</button>\n </div>`\n : '';\n\n box.innerHTML =\n foldBar +\n visible\n .map((m, visIdx) => {\n const idx = start + visIdx;\n const role = m.role === 'user' ? 'user' : 'assistant';\n const roleLabel =\n m.role === 'user' ? t('chat.you') : t('chat.assistant');\n const docs =\n m.docs && m.docs.length\n ? `<div class=\"chat-attach-list\">${m.docs\n .map(\n (d) =>\n `<span class=\"chat-attach-chip\" title=\"${escapeHtml(d.name)}\"><span>📎 ${escapeHtml(d.name)}</span></span>`,\n )\n .join('')}</div>`\n : '';\n const showReasoningBlock = Boolean(m.reasoning);\n const reasoning = showReasoningBlock\n ? `<details class=\"chat-reasoning\" ${m.streaming || !m.content ? 'open' : ''}>\n <summary>${escapeHtml(t('chat.reasoning'))}${m.streaming && !m.content ? ` · ${escapeHtml(t('chat.streaming'))}` : ''}</summary>\n <pre>${escapeHtml(m.reasoning)}</pre>\n </details>`\n : '';\n let bodyText = m.content || '';\n if (!bodyText && m.streaming) {\n bodyText = m.reasoning ? '' : '…';\n }\n const errCls = m.error ? ' error' : '';\n const streamCls = m.streaming ? ' is-streaming' : '';\n // Streaming: plain text only (fast). Done assistant: MD with cache.\n const useMd =\n role === 'assistant' && !m.streaming && Boolean(bodyText);\n let bodyHtml;\n if (useMd) {\n const ck = mdCacheKey(idx, bodyText);\n if (chatMdCache.has(ck)) {\n bodyHtml = chatMdCache.get(ck);\n } else {\n bodyHtml = formatChatMarkdown(bodyText);\n chatMdCache.set(ck, bodyHtml);\n if (chatMdCache.size > 200) {\n const first = chatMdCache.keys().next().value;\n chatMdCache.delete(first);\n }\n }\n } else {\n bodyHtml = escapeHtml(bodyText);\n }\n const long =\n !m.streaming && bodyText.length > CHAT_CONTENT_COLLAPSE;\n const contentCls = `${useMd ? 'chat-content md' : 'chat-content'}${long ? ' is-collapsible' : ''}`;\n const moreBtn = long\n ? `<button type=\"button\" class=\"btn ghost sm chat-expand-btn\" data-expand=\"${idx}\">${escapeHtml(t('chat.showMore'))}</button>`\n : '';\n const spend = formatChatSpend(m);\n const spendHtml = spend\n ? `<div class=\"muted chat-spend\">${escapeHtml(spend)}</div>`\n : '';\n const media = m.media;\n const mediaHtml = media?.assetId\n ? `<div class=\"chat-media\" data-chat-media=\"${escapeHtml(media.assetId)}\" data-chat-media-kind=\"${escapeHtml(media.kind || 'image')}\"></div>\n <a class=\"chat-media-open\" href=\"#/media\">${escapeHtml(t('chat.openInLibrary'))}</a>`\n : '';\n const toolsHtml =\n Array.isArray(m.tools) && m.tools.length\n ? `<div class=\"chat-tools\">${m.tools\n .map(\n (tc) =>\n `<span class=\"chat-tool-chip\" title=\"${escapeHtml(tc.arguments || '')}\">${escapeHtml(tc.name || 'tool')}</span>`,\n )\n .join('')}</div>`\n : '';\n const copyBtn =\n bodyText\n ? `<button type=\"button\" class=\"chat-copy-btn\" data-copy-msg=\"${idx}\" title=\"${escapeHtml(t('chat.copy'))}\">${escapeHtml(t('chat.copy'))}</button>`\n : '';\n return `<div class=\"chat-bubble ${role}${errCls}${streamCls}\" data-msg-idx=\"${idx}\">\n <div class=\"chat-bubble-head\">\n <div class=\"chat-role\">${escapeHtml(roleLabel)}${m.streaming ? ` <span class=\"chat-live\">${escapeHtml(t('chat.streaming'))}</span>` : ''}</div>\n ${copyBtn}\n </div>\n ${docs}\n ${reasoning}\n ${toolsHtml}\n ${mediaHtml}\n <div class=\"${contentCls}\" data-content-idx=\"${idx}\">${bodyHtml}${m.streaming ? '<span class=\"chat-cursor\">▍</span>' : ''}</div>\n ${moreBtn}\n ${spendHtml}\n </div>`;\n })\n .join('');\n\n if (nearBottom || streaming) {\n box.scrollTop = box.scrollHeight;\n }\n updateChatCompressButton();\n hydrateChatMedia().catch(() => {});\n\n document.getElementById('chat-load-older')?.addEventListener('click', () => {\n const prevH = box.scrollHeight;\n chatRenderSkip = Math.max(0, chatRenderSkip - CHAT_RENDER_STEP);\n renderChatBubbles();\n const box2 = document.getElementById('chat-messages');\n if (box2) box2.scrollTop = box2.scrollHeight - prevH;\n });\n\n box.querySelectorAll('[data-expand]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const el = box.querySelector(\n `[data-content-idx=\"${btn.getAttribute('data-expand')}\"]`,\n );\n if (el) {\n el.classList.toggle('is-expanded');\n btn.textContent = el.classList.contains('is-expanded')\n ? t('chat.showLess')\n : t('chat.showMore');\n }\n });\n });\n\n box.querySelectorAll('[data-copy-msg]').forEach((btn) => {\n btn.addEventListener('click', async (e) => {\n e.preventDefault();\n e.stopPropagation();\n const i = Number(btn.getAttribute('data-copy-msg'));\n const msg = chatMessages[i];\n if (!msg?.content) return;\n const ok = await copyTextToClipboard(msg.content);\n if (ok) {\n const prev = btn.textContent;\n btn.textContent = t('chat.copied');\n btn.classList.add('is-copied');\n setTimeout(() => {\n if (btn.isConnected) {\n btn.textContent = prev || t('chat.copy');\n btn.classList.remove('is-copied');\n }\n }, 1600);\n } else {\n showError(t('chat.copyFail'));\n }\n });\n });\n}\n\n/** Parse one SSE buffer chunk into { events, rest } */\nfunction parseSseBuffer(buffer) {\n // Normalize CRLF\n const normalized = buffer.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n const parts = normalized.split('\\n');\n const rest = parts.pop() || '';\n const events = [];\n for (const line of parts) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(':')) continue; // comment / keepalive\n if (!trimmed.startsWith('data:')) continue;\n const data = trimmed.slice(5).trim();\n if (!data) continue;\n events.push(data);\n }\n return { events, rest };\n}\n\nfunction formatChatSpend(m) {\n if (!m || m.streaming) return '';\n const parts = [];\n const u = m.usage;\n if (u && (u.prompt_tokens || u.completion_tokens || u.total_tokens)) {\n const cached = u.prompt_tokens_details?.cached_tokens;\n const cacheBit =\n cached != null ? ` · ${t('chat.cacheTokens')}: ${cached}` : '';\n parts.push(\n `${t('chat.tokens')}: ${u.prompt_tokens || 0}+${u.completion_tokens || 0}=${u.total_tokens || 0}${cacheBit}`,\n );\n }\n const usd = m.omni?.cost?.total_cost_usd;\n if (typeof usd === 'number') {\n parts.push(`${t('chat.cost')}: $${usd.toFixed(6)}`);\n }\n if (m.omni?.sessionId) {\n parts.push(`${t('chat.resume')}: ${m.omni.sessionId}`);\n }\n return parts.join(' · ');\n}\n\nfunction applyStreamDelta(assistant, json) {\n if (!json || typeof json !== 'object') return false;\n // Error payload from our server mid-stream\n if (json.error) {\n const msg = formatApiError({ error: json.error });\n assistant.error = true;\n assistant.content = (assistant.content || '') + `\\n✗ ${msg}`;\n return true;\n }\n const delta = json.choices?.[0]?.delta || {};\n let changed = false;\n if (delta.reasoning_content) {\n assistant.reasoning = (assistant.reasoning || '') + delta.reasoning_content;\n changed = true;\n }\n if (delta.thought && !delta.reasoning_content) {\n // avoid double-append when both aliases sent\n assistant.reasoning = (assistant.reasoning || '') + delta.thought;\n changed = true;\n } else if (delta.thought && delta.reasoning_content && delta.thought !== delta.reasoning_content) {\n assistant.reasoning = (assistant.reasoning || '') + delta.thought;\n changed = true;\n }\n if (typeof delta.content === 'string' && delta.content.length) {\n assistant.content = (assistant.content || '') + delta.content;\n changed = true;\n }\n if (json.usage && typeof json.usage === 'object') {\n assistant.usage = json.usage;\n changed = true;\n }\n if (json.omni && typeof json.omni === 'object') {\n assistant.omni = { ...(assistant.omni || {}), ...json.omni };\n if (assistant.omni.sessionId) {\n chatUi.resumeId = assistant.omni.sessionId;\n const resumeEl = document.getElementById('chat-resume');\n if (resumeEl) resumeEl.value = assistant.omni.sessionId;\n }\n changed = true;\n }\n if (json.omni_event && typeof json.omni_event === 'object') {\n const ge = json.omni_event;\n if (!Array.isArray(assistant.tools)) assistant.tools = [];\n if (ge.type === 'tool_call' || ge.type === 'tool_call_update') {\n const id = ge.toolCallId;\n const existing = id\n ? assistant.tools.find((x) => x.id === id)\n : null;\n const name = ge.toolName || ge.title || existing?.name || 'tool';\n const args =\n ge.rawInput != null\n ? typeof ge.rawInput === 'string'\n ? ge.rawInput\n : JSON.stringify(ge.rawInput)\n : existing?.arguments || '';\n const label = ge.status ? `${name} (${ge.status})` : name;\n if (existing) {\n existing.name = label;\n if (args) existing.arguments = args;\n } else {\n assistant.tools.push({ id, name: label, arguments: args });\n }\n changed = true;\n }\n }\n const tcs = json.choices?.[0]?.delta?.tool_calls;\n if (Array.isArray(tcs) && tcs.length) {\n if (!Array.isArray(assistant.tools)) assistant.tools = [];\n for (const tc of tcs) {\n const name = tc?.function?.name || tc?.name || 'tool';\n const args = tc?.function?.arguments || '';\n assistant.tools.push({\n id: tc?.id,\n name,\n arguments: typeof args === 'string' ? args : JSON.stringify(args || {}),\n });\n }\n changed = true;\n }\n // Non-stream style full message (fallback)\n const msg = json.choices?.[0]?.message;\n if (msg) {\n if (msg.content && !assistant.content) {\n assistant.content = msg.content;\n changed = true;\n }\n if (msg.reasoning_content && !assistant.reasoning) {\n assistant.reasoning = msg.reasoning_content;\n changed = true;\n }\n }\n return changed;\n}\n\n/**\n * Upload one file with progress via XHR (fetch has no upload progress).\n * @param {File} file\n * @param {(p: { loaded: number, total: number, percent: number }) => void} [onProgress]\n */\nfunction uploadChatFile(file, onProgress) {\n const auth = playgroundAuthKey();\n if (!auth) return Promise.reject(new Error(t('chat.needKey')));\n\n return new Promise((resolve, reject) => {\n const fd = new FormData();\n fd.append('file', file, file.name);\n const asId = playgroundRealApiKeyId();\n if (asId) fd.append('apiKeyId', asId);\n\n const xhr = new XMLHttpRequest();\n xhr.open('POST', '/admin/api/documents');\n xhr.setRequestHeader('Authorization', `Bearer ${auth}`);\n\n xhr.upload.onprogress = (ev) => {\n if (!onProgress) return;\n if (ev.lengthComputable && ev.total > 0) {\n const percent = Math.min(100, Math.round((ev.loaded / ev.total) * 100));\n onProgress({ loaded: ev.loaded, total: ev.total, percent });\n } else {\n onProgress({ loaded: ev.loaded || 0, total: 0, percent: -1 });\n }\n };\n\n xhr.onload = () => {\n let data = null;\n try {\n data = xhr.responseText ? JSON.parse(xhr.responseText) : null;\n } catch {\n data = null;\n }\n if (xhr.status < 200 || xhr.status >= 300) {\n const msg =\n data?.error?.message ||\n data?.message ||\n xhr.responseText ||\n xhr.statusText;\n reject(new Error(msg || t('chat.uploadFail')));\n return;\n }\n const doc = data?.data || data;\n const id = doc?.id;\n if (!id || typeof id !== 'string') {\n reject(new Error(t('chat.uploadFail')));\n return;\n }\n resolve({\n id,\n name: doc.originalName || doc.filename || file.name,\n mime: doc.mimeType || file.type || '',\n size: doc.sizeBytes ?? doc.size ?? file.size ?? 0,\n });\n };\n xhr.onerror = () => reject(new Error(t('chat.uploadFail')));\n xhr.onabort = () => reject(new Error(t('chat.uploadFail')));\n xhr.send(fd);\n });\n}\n\nfunction setChatUploadProgress(opts) {\n const wrap = document.getElementById('chat-upload-progress');\n if (!wrap) return;\n const { visible, fileName, fileIndex, fileTotal, percent, indeterminate } =\n opts;\n if (!visible) {\n wrap.hidden = true;\n wrap.setAttribute('aria-hidden', 'true');\n return;\n }\n wrap.hidden = false;\n wrap.setAttribute('aria-hidden', 'false');\n const label = document.getElementById('chat-upload-label');\n const bar = document.getElementById('chat-upload-bar');\n const pctEl = document.getElementById('chat-upload-pct');\n const name = fileName || '';\n const idx = fileIndex || 1;\n const tot = fileTotal || 1;\n if (label) {\n label.textContent =\n tot > 1\n ? tf('chat.uploadProgressMulti', { name, i: idx, n: tot })\n : tf('chat.uploadProgress', { name });\n }\n const ind = Boolean(indeterminate) || percent < 0;\n if (bar) {\n bar.classList.toggle('is-indeterminate', ind);\n if (!ind) {\n bar.style.width = `${Math.max(0, Math.min(100, percent))}%`;\n } else {\n bar.style.width = '40%';\n }\n }\n if (pctEl) {\n pctEl.textContent = ind\n ? t('chat.uploading')\n : tf('common.percent', { n: Math.max(0, Math.min(100, percent)) });\n }\n}\n\n/**\n * Add already-uploaded documents to the pending chips (no re-upload).\n * @param {Array<{ id: string, name?: string, originalName?: string, mime?: string, mimeType?: string, size?: number, sizeBytes?: number }>} docs\n */\nfunction addChatExistingDocs(docs) {\n const list = Array.isArray(docs) ? docs : [];\n if (!list.length) return { added: 0, skipped: 0 };\n let added = 0;\n let skipped = 0;\n const pendingIds = new Set(chatPendingDocs.map((d) => d.id));\n for (const raw of list) {\n if (chatPendingDocs.length >= CHAT_MAX_DOCS) {\n skipped += list.length - added - skipped;\n break;\n }\n const id = raw?.id;\n const name = raw?.name || raw?.originalName || '';\n if (!id || !DOC_ID_RE.test(String(id))) {\n skipped += 1;\n continue;\n }\n if (!isChatAllowedFilename(name)) {\n skipped += 1;\n continue;\n }\n if (pendingIds.has(id)) {\n skipped += 1;\n continue;\n }\n chatPendingDocs.push({\n id,\n name: name || id,\n mime: raw.mime || raw.mimeType || '',\n size: raw.size ?? raw.sizeBytes ?? 0,\n });\n pendingIds.add(id);\n added += 1;\n }\n renderChatPending();\n return { added, skipped };\n}\n\nasync function openChatLibraryPicker() {\n if (!playgroundAuthKey()) {\n showError(t('chat.needKey'));\n return;\n }\n // Library list filters by real key only (session → omit = all admin-visible docs)\n const asKeyId = playgroundRealApiKeyId();\n const room = Math.max(0, CHAT_MAX_DOCS - chatPendingDocs.length);\n if (room <= 0) {\n showError(t('chat.tooManyFiles'));\n return;\n }\n\n /** @type {Map<string, any>} */\n const selected = new Map();\n let loadSeq = 0;\n\n openAppModal({\n title: t('chat.libraryTitle'),\n subtitle: escapeHtml(t('chat.librarySubtitle')),\n size: 'md',\n bodyHtml: `\n <div class=\"chat-lib\">\n <div class=\"chat-lib-toolbar\">\n <input type=\"search\" id=\"chat-lib-q\" class=\"chat-lib-search\" placeholder=\"${escapeHtml(t('chat.librarySearch'))}\" autocomplete=\"off\" />\n <span class=\"muted chat-lib-count\" id=\"chat-lib-count\">${escapeHtml(tf('chat.librarySelected', { n: 0 }))}</span>\n </div>\n <div class=\"muted chat-lib-formats\">${escapeHtml(t('chat.formatsLabel'))}: ${escapeHtml(chatFormatsShort())}</div>\n <div id=\"chat-lib-list\" class=\"chat-lib-list\" role=\"listbox\" aria-multiselectable=\"true\">\n <div class=\"muted chat-lib-status\">${escapeHtml(t('common.loading') || '…')}</div>\n </div>\n </div>`,\n footerHtml: `\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-lib-cancel\">${escapeHtml(t('common.cancel'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"chat-lib-add\" disabled>${escapeHtml(t('chat.libraryAdd'))}</button>`,\n });\n\n const listEl = document.getElementById('chat-lib-list');\n const qEl = document.getElementById('chat-lib-q');\n const countEl = document.getElementById('chat-lib-count');\n const addBtn = document.getElementById('chat-lib-add');\n document.getElementById('chat-lib-cancel')?.addEventListener('click', () => closeAppModal());\n\n const paintCount = () => {\n if (countEl) countEl.textContent = tf('chat.librarySelected', { n: selected.size });\n if (addBtn) {\n addBtn.disabled = selected.size === 0;\n addBtn.textContent =\n selected.size > 0\n ? `${t('chat.libraryAdd')} (${selected.size})`\n : t('chat.libraryAdd');\n }\n };\n\n const renderRows = (items) => {\n if (!listEl) return;\n const pendingIds = new Set(chatPendingDocs.map((d) => d.id));\n const allowed = (items || []).filter((d) => isChatAllowedFilename(d.originalName));\n if (!allowed.length) {\n listEl.innerHTML = `<div class=\"data-empty chat-lib-empty\"><strong>${escapeHtml(t('chat.libraryEmpty'))}</strong></div>`;\n return;\n }\n listEl.innerHTML = allowed\n .map((d) => {\n const already = pendingIds.has(d.id);\n const checked = selected.has(d.id);\n const disabled = already && !checked;\n return `\n <label class=\"chat-lib-row ${already ? 'is-already' : ''} ${checked ? 'is-selected' : ''}\" data-id=\"${escapeHtml(d.id)}\">\n <input type=\"checkbox\" data-lib-id=\"${escapeHtml(d.id)}\" ${checked ? 'checked' : ''} ${disabled ? 'disabled' : ''} />\n <span class=\"chat-lib-meta\">\n <span class=\"chat-lib-name\" title=\"${escapeHtml(d.originalName)}\">${escapeHtml(d.originalName)}</span>\n <span class=\"muted\">${escapeHtml(d.mimeType || '')} · ${fmtBytes(d.sizeBytes || 0)}${\n already ? ` · ${escapeHtml(t('chat.libraryAlready'))}` : ''\n }</span>\n </span>\n </label>`;\n })\n .join('');\n\n listEl.querySelectorAll('input[data-lib-id]').forEach((inp) => {\n inp.addEventListener('change', () => {\n const id = inp.getAttribute('data-lib-id');\n const row = allowed.find((x) => x.id === id);\n if (!row) return;\n if (inp.checked) {\n if (selected.size >= room && !selected.has(id)) {\n inp.checked = false;\n showError(t('chat.tooManyFiles'));\n return;\n }\n selected.set(id, row);\n } else {\n selected.delete(id);\n }\n const lab = inp.closest('.chat-lib-row');\n if (lab) lab.classList.toggle('is-selected', inp.checked);\n paintCount();\n });\n });\n };\n\n const load = async () => {\n const seq = ++loadSeq;\n if (listEl) {\n listEl.innerHTML = `<div class=\"muted chat-lib-status\">${escapeHtml(t('common.loading') || '…')}</div>`;\n }\n try {\n const params = new URLSearchParams({\n limit: '50',\n offset: '0',\n });\n if (asKeyId) params.set('apiKeyId', asKeyId);\n const q = (qEl?.value || '').trim();\n if (q) params.set('q', q);\n const res = await api(`/documents?${params}`);\n if (seq !== loadSeq) return;\n renderRows(res.data || []);\n } catch (e) {\n if (seq !== loadSeq) return;\n if (listEl) {\n listEl.innerHTML = `<div class=\"error-box\">${escapeHtml(e.message || t('chat.libraryLoadFail'))}</div>`;\n }\n }\n };\n\n let searchTimer = null;\n qEl?.addEventListener('input', () => {\n if (searchTimer) clearTimeout(searchTimer);\n searchTimer = setTimeout(() => load(), 280);\n });\n\n addBtn?.addEventListener('click', () => {\n const docs = [...selected.values()];\n const { added } = addChatExistingDocs(\n docs.map((d) => ({\n id: d.id,\n name: d.originalName,\n mime: d.mimeType,\n size: d.sizeBytes,\n })),\n );\n closeAppModal();\n if (added > 0) showError('');\n });\n\n paintCount();\n await load();\n qEl?.focus();\n}\n\nasync function addChatFiles(fileList) {\n const rawFiles = [...(fileList || [])];\n if (!rawFiles.length) return;\n if (!playgroundAuthKey()) {\n showError(t('chat.needKey'));\n return;\n }\n\n const rejected = rawFiles.filter((f) => !isChatAllowedFilename(f.name));\n const files = rawFiles.filter((f) => isChatAllowedFilename(f.name));\n if (rejected.length) {\n showError(\n tf('chat.formatsReject', {\n name: rejected.map((f) => f.name).join(', '),\n formats: chatFormatsShort(),\n }),\n );\n if (!files.length) return;\n }\n\n if (chatPendingDocs.length + files.length > CHAT_MAX_DOCS) {\n showError(t('chat.tooManyFiles'));\n return;\n }\n const attachBtn = document.getElementById('chat-attach');\n const sendBtn = document.getElementById('chat-send');\n if (attachBtn) {\n attachBtn.disabled = true;\n attachBtn.textContent = t('chat.uploading');\n }\n if (sendBtn) sendBtn.disabled = true;\n\n const total = files.length;\n try {\n let i = 0;\n for (const file of files) {\n if (chatPendingDocs.length >= CHAT_MAX_DOCS) break;\n i += 1;\n setChatUploadProgress({\n visible: true,\n fileName: file.name,\n fileIndex: i,\n fileTotal: total,\n percent: 0,\n indeterminate: false,\n });\n const doc = await uploadChatFile(file, ({ percent }) => {\n setChatUploadProgress({\n visible: true,\n fileName: file.name,\n fileIndex: i,\n fileTotal: total,\n percent: percent < 0 ? 0 : percent,\n indeterminate: percent < 0,\n });\n });\n // brief 100% flash\n setChatUploadProgress({\n visible: true,\n fileName: file.name,\n fileIndex: i,\n fileTotal: total,\n percent: 100,\n indeterminate: false,\n });\n // avoid duplicate id if same file re-uploaded in session chips\n if (!chatPendingDocs.some((d) => d.id === doc.id)) {\n chatPendingDocs.push(doc);\n }\n renderChatPending();\n }\n if (!rejected.length) showError('');\n } catch (e) {\n showError(e.message || t('chat.uploadFail'));\n } finally {\n setChatUploadProgress({ visible: false });\n if (attachBtn) {\n attachBtn.disabled = false;\n attachBtn.textContent = t('chat.attach');\n }\n if (sendBtn) sendBtn.disabled = false;\n }\n}\n\nfunction chatKeySelectOptions() {\n const meId = state.me?.id || '';\n const meLabel = state.me\n ? `${t('chat.useSessionKey')} · ${state.me.name || ''} (${state.me.keyPrefix || ''}…)`\n : t('chat.useSessionKey');\n const selected = chatUi.keyId || 'session';\n const keys = (state.keys || []).filter((k) => k.isActive !== false);\n const opts = [\n `<option value=\"session\" ${selected === 'session' || selected === meId || !selected ? 'selected' : ''}>${escapeHtml(meLabel)}</option>`,\n ];\n for (const k of keys) {\n if (meId && k.id === meId) continue;\n const label = `${k.name || 'key'} · ${k.keyPrefix || ''}… · ${k.role || ''}/${k.mode || ''}`;\n opts.push(\n `<option value=\"${escapeHtml(k.id)}\" ${selected === k.id ? 'selected' : ''}>${escapeHtml(label)}</option>`,\n );\n }\n return opts.join('');\n}\n\nconst PIPER_CHAT_ID = 'piper/lessac-high';\n\nfunction classifyPlaygroundKind(id, local) {\n const s = String(id || '');\n if (!s || s === 'echo') return 'text';\n if (s === PIPER_CHAT_ID || /^piper\\//i.test(s)) return 'tts';\n const row = (local || state.catalogLocal || []).find(\n (m) => m.id === s || m.repoId === s,\n );\n const rt = String(row?.runtime || '');\n const mod = String(row?.modality || '');\n if (rt === 'whisper' || mod === 'stt') return 'stt';\n if (rt === 'tts' || mod === 'tts') return 'tts';\n if (\n mod === 'video' ||\n /zeroscope|ltx-video|text-to-video|cogvideox|wan2/i.test(s)\n ) {\n return 'video';\n }\n if (\n rt === 'diffusion' ||\n mod === 'image' ||\n /sdxl|tiny-sd|stable-diffusion/i.test(s)\n ) {\n return 'image';\n }\n return 'text';\n}\n\nfunction playgroundModelLabel(id, local) {\n const kind = classifyPlaygroundKind(id, local);\n const tag = t(`chat.modelKind_${kind}`);\n if (id === PIPER_CHAT_ID) return `Piper lessac-high · ${tag}`;\n return `${id} · ${tag}`;\n}\n\nasync function fetchAdminMediaBlob(id) {\n const r = await fetch(`/admin/api/media/assets/${id}/download`, {\n headers: { Authorization: `Bearer ${state.key}` },\n });\n if (!r.ok) throw new Error(await r.text());\n return r.blob();\n}\n\nasync function hydrateChatMedia() {\n const nodes = document.querySelectorAll('[data-chat-media]');\n for (const el of nodes) {\n if (el.getAttribute('data-hydrated') === '1') continue;\n const id = el.getAttribute('data-chat-media');\n const kind = el.getAttribute('data-chat-media-kind');\n if (!id) continue;\n try {\n const blob = await fetchAdminMediaBlob(id);\n const url = URL.createObjectURL(blob);\n el.setAttribute('data-hydrated', '1');\n if (kind === 'image') {\n el.innerHTML = `<img src=\"${url}\" alt=\"\" />`;\n } else if (kind === 'video') {\n el.innerHTML = `<video controls src=\"${url}\" playsinline></video>`;\n } else if (kind === 'audio') {\n el.innerHTML = `<audio controls src=\"${url}\"></audio>`;\n }\n } catch {\n el.textContent = t('chat.uploadFail');\n }\n }\n}\n\nasync function pollAdminMediaJob(id) {\n for (let i = 0; i < 90; i += 1) {\n const res = await api('/media/jobs?limit=50&offset=0');\n const row = (res.data || []).find((j) => j.id === id);\n if (row && (row.status === 'completed' || row.status === 'failed')) {\n return row;\n }\n await new Promise((r) => setTimeout(r, 2000));\n }\n throw new Error(t('chat.mediaBusy_video'));\n}\n\nasync function runPlaygroundMedia(kind, { text, pending, model, apiKeyId }) {\n const extra = apiKeyId ? { apiKeyId } : {};\n if (kind === 'image') {\n const res = await api('/media/generate', {\n method: 'POST',\n body: JSON.stringify({\n prompt: text,\n model,\n format: 'png',\n n: 1,\n ...extra,\n }),\n });\n const assetId =\n res.data?.omni?.asset_ids?.[0] || res.omni?.asset_ids?.[0];\n if (!assetId) throw new Error(t('chat.emptyReply'));\n return {\n kind: 'image',\n assetId,\n mime: 'image/png',\n caption: t('chat.mediaDone_image'),\n };\n }\n if (kind === 'video') {\n const created = await api('/media/videos', {\n method: 'POST',\n body: JSON.stringify({ prompt: text, model, format: 'mp4', ...extra }),\n });\n const job = created.data || created;\n const jobId = job.id;\n if (!jobId) throw new Error(t('chat.emptyReply'));\n const done = await pollAdminMediaJob(jobId);\n if (done.status !== 'completed' || !done.result_asset_id) {\n throw new Error(done.error || t('chat.emptyReply'));\n }\n return {\n kind: 'video',\n assetId: done.result_asset_id,\n mime: 'video/mp4',\n caption: t('chat.mediaDone_video'),\n };\n }\n if (kind === 'tts') {\n const res = await api('/media/speech', {\n method: 'POST',\n body: JSON.stringify({ input: text, format: 'wav', ...extra }),\n });\n const assetId = res.data?.asset_id;\n if (!assetId) throw new Error(t('chat.emptyReply'));\n return {\n kind: 'audio',\n assetId,\n mime: res.data?.mime || 'audio/wav',\n caption: t('chat.mediaDone_tts'),\n };\n }\n if (kind === 'stt') {\n const docId = pending?.[0]?.id;\n if (!docId) throw new Error(t('chat.needAudioAttach'));\n const fd = new FormData();\n fd.append('sourceDocumentId', docId);\n if (apiKeyId) fd.append('apiKeyId', apiKeyId);\n const res = await parseApiResponse(\n await fetch('/admin/api/media/transcribe', {\n method: 'POST',\n headers: { Authorization: `Bearer ${state.key}` },\n body: fd,\n }),\n );\n return {\n kind: 'text',\n assetId: res.data?.asset_id,\n text: res.data?.text || '',\n caption: res.data?.text || t('chat.mediaDone_stt'),\n };\n }\n throw new Error(t('chat.emptyReply'));\n}\n\nfunction allowedModelsForKeyId(keyId) {\n if (!keyId || keyId === 'session') return null;\n const k = (state.keys || []).find((x) => x.id === keyId);\n const list = k?.allowedModels;\n if (!list || !list.length) return null;\n return list;\n}\n\nfunction filterIdsByAllowlist(ids, keyId) {\n const allow = allowedModelsForKeyId(keyId);\n if (!allow) return ids;\n const set = new Set(allow);\n return ids.filter((id) => set.has(id));\n}\n\nfunction fillPlaygroundModelSelect() {\n const el = document.getElementById('chat-model');\n if (!el) return;\n const all = state.playgroundAllModels || state.models || [];\n const models = filterIdsByAllowlist(all, chatUi.keyId);\n if (models.length && chatUi.model && !models.includes(chatUi.model)) {\n chatUi.model = models[0];\n }\n el.innerHTML = models.length\n ? models\n .map(\n (m) =>\n `<option value=\"${escapeHtml(m)}\" ${chatUi.model === m ? 'selected' : ''}>${escapeHtml(playgroundModelLabel(m, state.catalogLocal))}</option>`,\n )\n .join('')\n : `<option value=\"echo\">echo</option>`;\n}\n\nfunction orderPlaygroundModels(apiModels, loaded, local) {\n const seen = new Set();\n const out = [];\n const add = (id) => {\n const v = String(id || '').trim();\n if (!v || seen.has(v)) return;\n seen.add(v);\n out.push(v);\n };\n for (const e of loaded || []) add(e.id || e);\n for (const m of local || []) add(m.id || m);\n for (const id of apiModels || []) {\n if (id !== 'echo') add(id);\n }\n add(PIPER_CHAT_ID);\n add('echo');\n return out;\n}\n\nasync function renderChatPlayground() {\n const [, , cat] = await Promise.all([\n loadModels(false),\n loadKeys(),\n api('/catalog').catch(() => ({ loaded: [], local: [] })),\n ]);\n state.catalogLocal = cat.local || [];\n const allModels = orderPlaygroundModels(\n state.models || [],\n cat.loaded || [],\n cat.local || [],\n );\n state.playgroundAllModels = allModels;\n const models = filterIdsByAllowlist(allModels, chatUi.keyId);\n state.models = models;\n const preferred =\n (cat.loaded && cat.loaded[0] && cat.loaded[0].id) ||\n models.find((m) => m !== 'echo') ||\n 'echo';\n if (\n !chatUi.model ||\n chatUi.model === 'echo' ||\n !models.includes(chatUi.model)\n ) {\n chatUi.model = preferred;\n }\n const modelOpts = models\n .map(\n (m) =>\n `<option value=\"${escapeHtml(m)}\" ${chatUi.model === m ? 'selected' : ''}>${escapeHtml(playgroundModelLabel(m, state.catalogLocal))}</option>`,\n )\n .join('');\n\n // leaving chat page closes mobile drawer class\n setChatHistoryMobileOpen(false);\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"chat-page\" id=\"chat-page\">\n <div class=\"chat-drop-overlay\" id=\"chat-drop-overlay\" hidden aria-hidden=\"true\">\n <div class=\"chat-drop-overlay-card\">\n <div class=\"chat-drop-overlay-icon\" aria-hidden=\"true\">📎</div>\n <strong>${escapeHtml(t('chat.dropTitle'))}</strong>\n <span class=\"muted\">${escapeHtml(t('chat.dropHint'))}</span>\n </div>\n </div>\n <div class=\"topbar\">\n <h2>${escapeHtml(t('chat.title'))}</h2>\n <div class=\"toolbar\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-history-toggle\">${escapeHtml(t('chat.historyOpen'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-compress\" title=\"${escapeHtml(t('chat.compress'))}\">${escapeHtml(t('chat.compress'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-new\">${escapeHtml(t('chat.new'))}</button>\n </div>\n </div>\n <div class=\"chat-body\">\n <div class=\"chat-history-backdrop\" id=\"chat-history-backdrop\"></div>\n <div class=\"chat-shell${chatUi.settingsOpen ? ' is-settings-open' : ''}\">\n <div class=\"chat-settings-bar\">\n <button type=\"button\" class=\"chat-settings-toggle\" id=\"chat-settings-toggle\" aria-expanded=\"${chatUi.settingsOpen ? 'true' : 'false'}\" aria-controls=\"chat-toolbar\">\n <span class=\"chat-settings-summary\" id=\"chat-settings-summary\"></span>\n <span class=\"chat-settings-caret\" id=\"chat-settings-toggle-label\">${escapeHtml(chatUi.settingsOpen ? t('chat.settingsHide') : t('chat.settings'))}</span>\n </button>\n </div>\n <div class=\"chat-toolbar\" id=\"chat-toolbar\">\n <label class=\"chat-field-full\">${escapeHtml(t('chat.keySelect'))}\n <select id=\"chat-key-select\">${chatKeySelectOptions()}</select>\n </label>\n <label>${escapeHtml(t('chats.model'))}\n <select id=\"chat-model\">${modelOpts || `<option value=\"echo\">echo</option>`}</select>\n </label>\n <label class=\"check-inline\" for=\"chat-reasoning\">\n <input type=\"checkbox\" id=\"chat-reasoning\" ${chatUi.reasoning !== false ? 'checked' : ''} />\n ${escapeHtml(t('chat.includeReasoning'))}\n </label>\n <label class=\"chat-ctx-label\">${escapeHtml(t('chat.effort'))}\n <select id=\"chat-effort\">\n ${['', 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']\n .map((v) => {\n const label = v\n ? t(`chat.effort_${v}`)\n : t('chat.effortDefault');\n const sel = (chatUi.effort || '') === v ? ' selected' : '';\n return `<option value=\"${escapeHtml(v)}\"${sel}>${escapeHtml(label)}</option>`;\n })\n .join('')}\n </select>\n </label>\n <label class=\"chat-ctx-label\">${escapeHtml(t('chat.ctxMode'))}\n <select id=\"chat-ctx-mode\">\n <option value=\"full\">${escapeHtml(t('chat.ctxModeFull'))}</option>\n <option value=\"summary\">${escapeHtml(t('chat.ctxModeSummary'))}</option>\n <option value=\"recent\">${escapeHtml(t('chat.ctxModeRecent'))}</option>\n </select>\n </label>\n <label class=\"chat-ctx-label chat-ctx-n-label\">${escapeHtml(t('chat.ctxRecentN'))}\n <input type=\"number\" id=\"chat-ctx-n\" min=\"2\" max=\"40\" value=\"${chatContext.recentN}\" />\n </label>\n <button type=\"button\" class=\"btn ghost sm chat-field-full\" id=\"chat-system-toggle\" title=\"${escapeHtml(t('chat.systemHint'))}\">\n ${escapeHtml(t('chat.systemPrompt'))}${chatUi.systemPrompt ? ' ·' : ''}\n </button>\n <label class=\"chat-ctx-label chat-field-full\" title=\"${escapeHtml(t('chat.resumeHint'))}\">${escapeHtml(t('chat.resume'))}\n <input type=\"text\" id=\"chat-resume\" value=\"${escapeHtml(chatUi.resumeId || '')}\" placeholder=\"${escapeHtml(t('chat.resumePh'))}\" spellcheck=\"false\" />\n </label>\n <div class=\"chat-checks\">\n <label class=\"check-inline\" for=\"chat-fork\">\n <input type=\"checkbox\" id=\"chat-fork\" ${chatUi.forkSession ? 'checked' : ''} />\n ${escapeHtml(t('chat.fork'))}\n </label>\n <label class=\"check-inline\" for=\"chat-memory\">\n <input type=\"checkbox\" id=\"chat-memory\" ${chatUi.memory ? 'checked' : ''} />\n ${escapeHtml(t('chat.memory'))}\n </label>\n <label class=\"check-inline\" for=\"chat-no-plan\">\n <input type=\"checkbox\" id=\"chat-no-plan\" ${chatUi.noPlan ? 'checked' : ''} />\n ${escapeHtml(t('chat.noPlan'))}\n </label>\n </div>\n <label class=\"chat-ctx-label chat-field-full\">${escapeHtml(t('chat.permission'))}\n <select id=\"chat-perm\">\n ${['', 'default', 'acceptEdits', 'auto', 'dontAsk', 'bypassPermissions', 'plan']\n .map((v) => {\n const label = v || t('chat.effortDefault');\n const sel = (chatUi.permissionMode || '') === v ? ' selected' : '';\n return `<option value=\"${escapeHtml(v)}\"${sel}>${escapeHtml(label)}</option>`;\n })\n .join('')}\n </select>\n </label>\n </div>\n <div class=\"chat-system-wrap\" id=\"chat-system-wrap\" ${chatUi.systemOpen || chatUi.systemPrompt ? '' : 'hidden'}>\n <label class=\"chat-system-label\" for=\"chat-system\">${escapeHtml(t('chat.systemPrompt'))}\n <span class=\"hint\">${escapeHtml(t('chat.systemHint'))}</span>\n </label>\n <textarea id=\"chat-system\" rows=\"3\" placeholder=\"${escapeHtml(t('chat.systemPlaceholder'))}\">${escapeHtml(chatUi.systemPrompt || '')}</textarea>\n </div>\n <div id=\"chat-compress-banner\" class=\"chat-compress-banner\" hidden></div>\n <div id=\"chat-messages\" class=\"chat-messages\"></div>\n <div class=\"chat-composer\" id=\"chat-composer\">\n <div id=\"chat-pending\" class=\"chat-pending\" hidden></div>\n <div id=\"chat-upload-progress\" class=\"chat-upload-progress\" hidden aria-hidden=\"true\">\n <div class=\"chat-upload-meta\">\n <span id=\"chat-upload-label\" class=\"chat-upload-label\"></span>\n <span id=\"chat-upload-pct\" class=\"chat-upload-pct\"></span>\n </div>\n <div class=\"chat-upload-track\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <div id=\"chat-upload-bar\" class=\"chat-upload-bar\"></div>\n </div>\n </div>\n <div id=\"chat-stream-status\" class=\"chat-stream-status\" hidden></div>\n <textarea id=\"chat-input\" rows=\"2\" placeholder=\"${escapeHtml(t('chat.placeholder'))}\"></textarea>\n <div class=\"chat-composer-actions\">\n <div class=\"chat-composer-left\">\n <input type=\"file\" id=\"chat-file\" class=\"chat-file-input\" multiple accept=\"${escapeHtml(CHAT_FILE_ACCEPT)}\" />\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-attach\" title=\"${escapeHtml(t('chat.attachHint'))}\">${escapeHtml(t('chat.attach'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-attach-lib\" title=\"${escapeHtml(t('chat.libraryTitle'))}\">${escapeHtml(t('chat.attachLibrary'))}</button>\n <span class=\"chat-formats-hint\" title=\"${escapeHtml(chatFormatsShort())}\">\n <span class=\"chat-formats-label\">${escapeHtml(t('chat.formatsLabel'))}</span>\n <span class=\"muted\">${escapeHtml(chatFormatsShort())}</span>\n </span>\n </div>\n <div class=\"chat-composer-right\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"chat-stop\" disabled>${escapeHtml(t('chat.stop'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"chat-send\">${escapeHtml(t('chat.send'))}</button>\n </div>\n </div>\n </div>\n </div>\n <aside class=\"chat-history-rail\" id=\"chat-history-rail\" aria-label=\"${escapeHtml(t('chat.history'))}\">\n <div class=\"chat-history-head\">\n <div class=\"chat-history-head-row\">\n <h3>${escapeHtml(t('chat.history'))}</h3>\n <button type=\"button\" class=\"btn ghost sm\" id=\"chat-history-close-mobile\" aria-label=\"${escapeHtml(t('chat.historyClose'))}\">×</button>\n </div>\n <input type=\"search\" id=\"chat-history-search\" class=\"chat-history-search\" placeholder=\"${escapeHtml(t('chat.historySearch'))}\" value=\"${escapeHtml(chatSession.historyQ)}\" />\n </div>\n <ul class=\"chat-history-list\" id=\"chat-history-list\"></ul>\n <div class=\"chat-history-pager\" id=\"chat-history-pager\"></div>\n </aside>\n </div>\n </div>\n `);\n bindShell();\n renderChatBubbles();\n renderChatPending();\n paintChatHistoryList();\n updateChatCompressButton();\n paintContextBanner();\n syncContextControls();\n paintChatSettingsBar();\n loadConversationList().catch(() => {});\n document.getElementById('chat-settings-toggle')?.addEventListener('click', () => {\n chatUi.settingsOpen = !chatUi.settingsOpen;\n paintChatSettingsBar();\n });\n\n document.getElementById('chat-key-select').onchange = () => {\n captureChatUi();\n fillPlaygroundModelSelect();\n };\n const ctxMode = document.getElementById('chat-ctx-mode');\n const ctxN = document.getElementById('chat-ctx-n');\n if (ctxMode) {\n ctxMode.onchange = () => {\n const v = ctxMode.value;\n if (v === 'summary' && !chatContext.summary) {\n showError(t('chat.compressNeedSummary'));\n ctxMode.value = chatContext.mode === 'recent' ? 'recent' : 'full';\n return;\n }\n chatContext.mode = v === 'summary' || v === 'recent' ? v : 'full';\n paintContextBanner();\n syncContextControls();\n saveConversation().catch(() => {});\n };\n }\n if (ctxN) {\n ctxN.onchange = () => {\n chatContext.recentN = Math.min(\n 40,\n Math.max(2, Number(ctxN.value) || 6),\n );\n paintContextBanner();\n saveConversation().catch(() => {});\n };\n }\n document.getElementById('chat-model').onchange = () => captureChatUi();\n document.getElementById('chat-reasoning').onchange = () => captureChatUi();\n document.getElementById('chat-effort')?.addEventListener('change', () =>\n captureChatUi(),\n );\n document.getElementById('chat-resume')?.addEventListener('change', () =>\n captureChatUi(),\n );\n document.getElementById('chat-fork')?.addEventListener('change', () =>\n captureChatUi(),\n );\n document.getElementById('chat-memory')?.addEventListener('change', () =>\n captureChatUi(),\n );\n document.getElementById('chat-no-plan')?.addEventListener('change', () =>\n captureChatUi(),\n );\n document.getElementById('chat-perm')?.addEventListener('change', () =>\n captureChatUi(),\n );\n document.getElementById('chat-system').oninput = () => captureChatUi();\n document.getElementById('chat-system-toggle').onclick = () => {\n captureChatUi();\n chatUi.systemOpen = !chatUi.systemOpen;\n const wrap = document.getElementById('chat-system-wrap');\n if (wrap) wrap.hidden = !chatUi.systemOpen && !chatUi.systemPrompt.trim();\n if (chatUi.systemOpen) document.getElementById('chat-system')?.focus();\n };\n\n document.getElementById('chat-new').onclick = () => {\n resetChatThread(true);\n };\n document.getElementById('chat-compress').onclick = () => {\n compressChatHistory().catch(() => {});\n };\n document.getElementById('chat-stop').onclick = () => {\n if (chatAbort) chatAbort.abort();\n };\n document.getElementById('chat-send').onclick = () => sendChatMessage();\n document.getElementById('chat-attach').onclick = () => {\n document.getElementById('chat-file')?.click();\n };\n document.getElementById('chat-attach-lib')?.addEventListener('click', () => {\n openChatLibraryPicker().catch((e) => showError(e.message || t('chat.libraryLoadFail')));\n });\n document.getElementById('chat-file').onchange = (e) => {\n const input = e.target;\n addChatFiles(input.files).finally(() => {\n input.value = '';\n });\n };\n\n const histToggle = document.getElementById('chat-history-toggle');\n const histBackdrop = document.getElementById('chat-history-backdrop');\n const histClose = document.getElementById('chat-history-close-mobile');\n if (histToggle) {\n histToggle.onclick = () => {\n setChatHistoryMobileOpen(!chatSession.historyOpenMobile);\n };\n }\n if (histBackdrop) {\n histBackdrop.onclick = () => closeChatHistoryMobile();\n }\n if (histClose) {\n histClose.onclick = () => closeChatHistoryMobile();\n }\n const searchEl = document.getElementById('chat-history-search');\n if (searchEl) {\n searchEl.oninput = () => {\n chatSession.historyQ = searchEl.value;\n if (chatHistorySearchTimer) clearTimeout(chatHistorySearchTimer);\n chatHistorySearchTimer = setTimeout(() => {\n chatSession.historyPage = 0;\n loadConversationList();\n }, 280);\n };\n }\n\n // Full-page drag & drop: drop files anywhere on the chat page\n bindChatPageFileDrop();\n\n document.getElementById('chat-input').onkeydown = (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n sendChatMessage();\n }\n };\n}\n\n/**\n * Allow dragging files from the OS into the chat page (whole surface).\n * Prevents the browser from navigating to the dropped file.\n */\nfunction bindChatPageFileDrop() {\n const page = document.getElementById('chat-page');\n const overlay = document.getElementById('chat-drop-overlay');\n const composer = document.getElementById('chat-composer');\n if (!page) return;\n\n let dragDepth = 0;\n\n const hasFiles = (e) => {\n const types = e.dataTransfer?.types;\n if (!types) return false;\n // DOMStringList or array\n if (typeof types.includes === 'function') return types.includes('Files');\n return [...types].includes('Files');\n };\n\n const showOverlay = (on) => {\n page.classList.toggle('is-file-drag', on);\n if (composer) composer.classList.toggle('is-dragover', on);\n if (overlay) {\n overlay.hidden = !on;\n overlay.setAttribute('aria-hidden', on ? 'false' : 'true');\n }\n };\n\n const onDragEnter = (e) => {\n if (!hasFiles(e)) return;\n e.preventDefault();\n e.stopPropagation();\n dragDepth += 1;\n showOverlay(true);\n };\n\n const onDragOver = (e) => {\n if (!hasFiles(e)) return;\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';\n showOverlay(true);\n };\n\n const onDragLeave = (e) => {\n if (!hasFiles(e)) return;\n e.preventDefault();\n e.stopPropagation();\n dragDepth = Math.max(0, dragDepth - 1);\n if (dragDepth === 0) showOverlay(false);\n };\n\n const onDrop = (e) => {\n if (!hasFiles(e)) return;\n e.preventDefault();\n e.stopPropagation();\n dragDepth = 0;\n showOverlay(false);\n const files = e.dataTransfer?.files;\n if (files?.length) {\n addChatFiles(files).catch((err) =>\n showError(err.message || t('chat.uploadFail')),\n );\n }\n };\n\n page.addEventListener('dragenter', onDragEnter);\n page.addEventListener('dragover', onDragOver);\n page.addEventListener('dragleave', onDragLeave);\n page.addEventListener('drop', onDrop);\n\n // Block browser default open-file navigation while on chat page\n const winDragOver = (e) => {\n if (state.page !== 'chat') return;\n if (hasFiles(e)) e.preventDefault();\n };\n const winDrop = (e) => {\n if (state.page !== 'chat') return;\n if (hasFiles(e)) e.preventDefault();\n };\n window.addEventListener('dragover', winDragOver);\n window.addEventListener('drop', winDrop);\n\n // Stash removers on page node for cleanup on next render (node is discarded)\n page._chatDropCleanup = () => {\n window.removeEventListener('dragover', winDragOver);\n window.removeEventListener('drop', winDrop);\n };\n}\n\n/**\n * Collect document IDs: current pending chips + every prior message\n * that still carries `docs` so multi-turn keeps attachments in context.\n * @returns {string[]}\n */\nfunction collectDocumentIdsForSend(pending) {\n const seen = new Set();\n const ids = [];\n const push = (id) => {\n if (!id || typeof id !== 'string') return;\n const t = id.trim();\n if (!DOC_ID_RE.test(t) || seen.has(t)) return;\n seen.add(t);\n ids.push(t);\n };\n for (const d of pending || []) push(d?.id);\n for (const m of chatMessages) {\n if (!m?.docs?.length) continue;\n for (const d of m.docs) push(d?.id);\n }\n return ids;\n}\n\nasync function sendChatMessage() {\n captureChatUi();\n const input = document.getElementById('chat-input');\n let text = input?.value.trim() || '';\n const pending = [...chatPendingDocs];\n\n if (!text && !pending.length) {\n showError(t('chat.needContent'));\n return;\n }\n const auth = playgroundAuthKey();\n if (!auth) {\n showError(t('chat.needKey'));\n return;\n }\n if (!text && pending.length) {\n text = t('chat.fileOnlyPrompt');\n }\n\n // Reject pending chips that never got a server id (broken upload response)\n const badPending = pending.filter((d) => !d?.id || !DOC_ID_RE.test(String(d.id)));\n if (badPending.length) {\n showError(t('chat.uploadFail'));\n return;\n }\n\n const model =\n document.getElementById('chat-model')?.value || chatUi.model || 'echo';\n const mediaKind = classifyPlaygroundKind(model, state.catalogLocal);\n if (mediaKind === 'stt' && !pending.length) {\n showError(t('chat.needAudioAttach'));\n return;\n }\n const includeReasoning =\n document.getElementById('chat-reasoning')?.checked !== false;\n const effort =\n document.getElementById('chat-effort')?.value || chatUi.effort || '';\n const asKeyId = playgroundKeyId();\n\n // Pending for this user bubble only; API gets pending + history docs\n const docMeta = pending.map((d) => ({ id: d.id, name: d.name }));\n const docIds = collectDocumentIdsForSend(pending);\n\n chatMessages.push({\n role: 'user',\n content: text,\n docs: docMeta.length ? docMeta : undefined,\n });\n if (input) input.value = '';\n chatPendingDocs = [];\n renderChatPending();\n\n const assistant = {\n role: 'assistant',\n content: '',\n reasoning: '',\n streaming: true,\n };\n chatMessages.push(assistant);\n // Keep viewport on newest messages for long threads\n const maxSkip = Math.max(0, chatMessages.length - CHAT_RENDER_WINDOW);\n chatRenderSkip = maxSkip;\n renderChatBubbles();\n\n // Context policy: full | summary+recent N | recent N (history UI unchanged)\n const apiMessages = buildApiMessages();\n\n const sendBtn = document.getElementById('chat-send');\n const stopBtn = document.getElementById('chat-stop');\n const attachBtn = document.getElementById('chat-attach');\n const libBtn = document.getElementById('chat-attach-lib');\n if (sendBtn) sendBtn.disabled = true;\n if (attachBtn) attachBtn.disabled = true;\n if (libBtn) libBtn.disabled = true;\n if (stopBtn) stopBtn.disabled = false;\n\n chatAbort = new AbortController();\n try {\n if (mediaKind !== 'text') {\n assistant.content = t(`chat.mediaBusy_${mediaKind}`);\n renderChatBubbles();\n const media = await runPlaygroundMedia(mediaKind, {\n text,\n pending,\n model,\n apiKeyId: playgroundRealApiKeyId(),\n });\n assistant.streaming = false;\n assistant.content = media.caption || '';\n assistant.media = media;\n renderChatBubbles();\n return;\n }\n const body = {\n model,\n stream: true,\n include_reasoning: includeReasoning,\n messages: apiMessages,\n };\n if (effort) body.reasoning_effort = effort;\n captureChatUi();\n if (chatUi.resumeId) body.resume = chatUi.resumeId;\n if (chatUi.forkSession) body.fork_session = true;\n if (chatUi.memory) body.experimental_memory = true;\n if (chatUi.noPlan) body.no_plan = true;\n if (chatUi.permissionMode) body.permission_mode = chatUi.permissionMode;\n // Always pass document_ids when any attachment is in the thread\n if (docIds.length) body.document_ids = docIds;\n // Only send real key UUID — session actor is already on the Bearer token\n const realKeyId = playgroundRealApiKeyId();\n if (realKeyId) body.apiKeyId = realKeyId;\n\n // Admin playground proxy — select key by id (no raw secret)\n const res = await fetch('/admin/api/chat/completions', {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${auth}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal: chatAbort.signal,\n });\n\n if (!res.ok) {\n const errText = await res.text();\n let msg = errText;\n try {\n const j = JSON.parse(errText);\n msg = j.error?.message || errText;\n } catch {\n /* */\n }\n throw new Error(msg || res.statusText);\n }\n\n // Prefer real streaming via ReadableStream\n if (res.body && typeof res.body.getReader === 'function') {\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let lastPaint = 0;\n const paint = (force = false) => {\n const now = performance.now();\n if (force || now - lastPaint > 40) {\n lastPaint = now;\n renderChatBubbles();\n }\n };\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const { events, rest } = parseSseBuffer(buffer);\n buffer = rest;\n let changed = false;\n for (const data of events) {\n if (data === '[DONE]') continue;\n try {\n const json = JSON.parse(data);\n if (applyStreamDelta(assistant, json)) changed = true;\n } catch {\n /* skip incomplete / non-json */\n }\n }\n if (changed) paint(false);\n }\n // flush trailing buffer (no final newline)\n if (buffer.trim()) {\n const { events } = parseSseBuffer(buffer + '\\n');\n for (const data of events) {\n if (data === '[DONE]') continue;\n try {\n applyStreamDelta(assistant, JSON.parse(data));\n } catch {\n /* ignore */\n }\n }\n }\n paint(true);\n } else {\n // Fallback: no stream body (some proxies) — read full text as SSE\n const text = await res.text();\n const { events } = parseSseBuffer(text + '\\n');\n for (const data of events) {\n if (data === '[DONE]') continue;\n try {\n applyStreamDelta(assistant, JSON.parse(data));\n } catch {\n /* try non-SSE JSON completion */\n try {\n const full = JSON.parse(text);\n applyStreamDelta(assistant, full);\n } catch {\n /* ignore */\n }\n }\n }\n renderChatBubbles();\n }\n\n if (!assistant.content && !assistant.reasoning) {\n assistant.content = t('chat.emptyReply');\n }\n showError('');\n } catch (e) {\n if (e.name === 'AbortError') {\n assistant.content =\n (assistant.content || '') + `\\n[${t('chat.stopped')}]`;\n } else {\n assistant.error = true;\n assistant.content =\n (assistant.content || '') + `\\n✗ ${e.message || e}`;\n showError(e.message || String(e));\n }\n } finally {\n assistant.streaming = false;\n chatAbort = null;\n renderChatBubbles();\n updateChatCompressButton();\n if (sendBtn) sendBtn.disabled = false;\n if (attachBtn) attachBtn.disabled = false;\n if (libBtn) libBtn.disabled = false;\n if (stopBtn) stopBtn.disabled = true;\n // Persist thread (non-blocking on failure)\n saveConversation().catch(() => {});\n }\n}\n\nconst SUPPORT_EMAIL = 'email@ysk.hk';\nconst SUPPORT_SPONSORS = 'https://github.com/sponsors/yanshekki';\nconst SUPPORT_LINKTREE = 'https://linktr.ee/yanshekki';\nconst SUPPORT_SITE = 'https://ysk.hk/';\nconst SUPPORT_DOCS =\n 'https://github.com/yanshekki/ysk-omni#readme';\n\nasync function renderSupport() {\n const wallets = [\n [t('support.netEvm'), 'yanshekki.eth'],\n [t('support.netNear'), 'yanshekki.near'],\n [t('support.netAda'), '$yanshekki'],\n ];\n const walletRows = wallets\n .map(\n ([net, addr]) => `\n <tr>\n <td>${escapeHtml(net)}</td>\n <td><code class=\"cell-code\">${escapeHtml(addr)}</code></td>\n <td class=\"row-actions\"><button type=\"button\" class=\"btn secondary sm\" data-copy=\"${escapeHtml(addr)}\">${escapeHtml(t('support.copy'))}</button></td>\n </tr>`,\n )\n .join('');\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('support.title'))}</h2>\n </div>\n ${pageMetaHtml([t('support.subtitle')])}\n <div class=\"support-pills\" role=\"navigation\">\n <button type=\"button\" class=\"seg-tab is-active\" data-jump=\"support-creator\">${escapeHtml(t('support.pillSupport'))}</button>\n <button type=\"button\" class=\"seg-tab\" data-jump=\"support-sponsor\">${escapeHtml(t('support.pillSponsor'))}</button>\n <a class=\"seg-tab\" href=\"mailto:${SUPPORT_EMAIL}\">${escapeHtml(t('support.pillHelp'))}</a>\n </div>\n <div class=\"support-stack\">\n <section class=\"panel support-panel\" id=\"support-creator\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('support.creatorTitle'))}</strong></div>\n <div class=\"panel-pad\"><p class=\"support-prose\">${escapeHtml(t('support.creatorBody'))}</p></div>\n </section>\n <section class=\"panel support-panel\" id=\"support-sponsor\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('support.sponsorTitle'))}</strong></div>\n <div class=\"panel-pad\">\n <p class=\"support-prose\">${escapeHtml(t('support.sponsorBody'))}</p>\n <div class=\"support-actions\">\n <a class=\"btn\" href=\"${SUPPORT_SPONSORS}\" target=\"_blank\" rel=\"noopener noreferrer\">${escapeHtml(t('support.githubSponsors'))}</a>\n <a class=\"btn secondary\" href=\"${SUPPORT_LINKTREE}\" target=\"_blank\" rel=\"noopener noreferrer\">${escapeHtml(t('support.linktree'))}</a>\n </div>\n <div class=\"support-wallets\">\n <div class=\"support-wallets-h\">\n <strong>${escapeHtml(t('support.walletsTitle'))}</strong>\n <span class=\"muted\">${escapeHtml(t('support.walletsHint'))}</span>\n </div>\n <table class=\"data-table\">\n <thead><tr>\n <th>${escapeHtml(t('support.net'))}</th>\n <th>${escapeHtml(t('support.addr'))}</th>\n <th></th>\n </tr></thead>\n <tbody>${walletRows}</tbody>\n </table>\n </div>\n </div>\n </section>\n <section class=\"panel support-panel\" id=\"support-ysk\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('support.yskTitle'))}</strong></div>\n <div class=\"panel-pad\">\n <p class=\"support-prose\">${escapeHtml(t('support.yskBody'))}</p>\n <ul class=\"support-list\">\n <li>${escapeHtml(t('support.yskLi1'))}</li>\n <li>${escapeHtml(t('support.yskLi2'))}</li>\n <li>${escapeHtml(t('support.yskLi3'))}</li>\n <li>${escapeHtml(t('support.yskLi4'))}</li>\n </ul>\n <p class=\"muted\">${escapeHtml(t('support.yskPrice'))}</p>\n <a class=\"btn secondary sm\" href=\"${SUPPORT_SITE}\" target=\"_blank\" rel=\"noopener noreferrer\">${escapeHtml(t('support.site'))}</a>\n </div>\n </section>\n <section class=\"panel support-panel\" id=\"support-help\">\n <div class=\"panel-h\"><strong>${escapeHtml(t('support.helpTitle'))}</strong></div>\n <div class=\"panel-pad\">\n <p class=\"support-prose\">${escapeHtml(t('support.helpBody'))}</p>\n <a class=\"btn support-email-btn\" href=\"mailto:${SUPPORT_EMAIL}\">${SUPPORT_EMAIL}</a>\n <p class=\"support-docs\"><a href=\"${SUPPORT_DOCS}\" target=\"_blank\" rel=\"noopener noreferrer\">${escapeHtml(t('support.docs'))}</a></p>\n </div>\n </section>\n </div>\n `);\n bindShell();\n document.querySelectorAll('[data-jump]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const id = btn.getAttribute('data-jump');\n if (id) document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' });\n });\n });\n document.querySelectorAll('[data-copy]').forEach((btn) => {\n btn.addEventListener('click', async () => {\n const v = btn.getAttribute('data-copy') || '';\n const ok = await copyTextToClipboard(v);\n btn.textContent = ok ? t('chat.copied') : t('support.copy');\n setTimeout(() => {\n btn.textContent = t('support.copy');\n }, 1400);\n });\n });\n}\n\n/** Curated packs rendered in production Admin Catalog (fallback if API is empty). */\nconst CURATED_PACKS = [\n {\n id: 'Qwen/Qwen2.5-0.5B-Instruct-GGUF',\n modality: 'text',\n runtime: 'llamacpp',\n quants: ['Q4_K_M', 'Q5_K_M', 'Q8_0'],\n vramMb: 512,\n },\n {\n id: 'Qwen/Qwen2.5-7B-Instruct',\n modality: 'text',\n runtime: 'vllm',\n quants: [],\n vramMb: 16000,\n },\n {\n id: 'Tongyi-MAI/Z-Image-Turbo',\n label: 'Z-Image-Turbo',\n modality: 'image',\n runtime: 'diffusion',\n quants: [],\n vramMb: 8000,\n },\n {\n id: 'black-forest-labs/FLUX.2-klein-4B',\n label: 'FLUX.2 Klein 4B',\n modality: 'image',\n runtime: 'diffusion',\n quants: [],\n vramMb: 8000,\n },\n {\n id: 'Qwen/Qwen3-TTS',\n modality: 'tts',\n runtime: 'diffusion',\n quants: [],\n vramMb: 4000,\n },\n {\n id: 'Systran/faster-whisper-small',\n modality: 'stt',\n runtime: 'whisper',\n quants: [],\n vramMb: 1000,\n },\n {\n id: 'Lightricks/LTX-2.5',\n label: 'LTX-2.5',\n modality: 'video',\n runtime: 'diffusion',\n quants: [],\n vramMb: 12000,\n },\n {\n id: 'Wan-AI/Wan2.2',\n label: 'Wan 2.2',\n modality: 'video',\n runtime: 'diffusion',\n quants: [],\n vramMb: 20000,\n },\n];\n\nfunction catalogPackName(p) {\n return p.label || String(p.id || '').split('/').pop() || p.id || '';\n}\n\nfunction catalogLocalsForPack(p, local) {\n const id = String(p.id || '');\n return (local || []).filter(\n (m) => m.id === id || m.repoId === id || String(m.id || '').startsWith(`${id}:`),\n );\n}\n\nfunction catalogModalityLabel(m) {\n const key = `catalog.mod.${m}`;\n return hasT(key) ? t(key) : m || '—';\n}\n\nfunction catalogDefaultQuant(quants) {\n const list = quants || [];\n if (list.includes('Q4_K_M')) return 'Q4_K_M';\n return list[0] || '';\n}\n\nfunction fmtDownloads(n) {\n const v = Number(n) || 0;\n if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`;\n if (v >= 1_000) return `${(v / 1_000).toFixed(1)}k`;\n return String(v);\n}\n\nfunction fmtMb(n) {\n const v = Number(n) || 0;\n if (v <= 0) return '—';\n if (v >= 1024) return `${(v / 1024).toFixed(1)} GB`;\n return `${Math.round(v).toLocaleString()} MB`;\n}\n\nfunction assertPullRecorded(last) {\n const status = last?.status;\n const pathOnDisk = last?.entry?.path;\n if (status === 'done' && pathOnDisk) return;\n const reason = String(last?.reason || '');\n if (reason.includes('no GGUF')) throw new Error(t('catalog.pullNoGguf'));\n throw new Error(reason || t('catalog.pullFail'));\n}\n\nfunction fmtDuration(sec) {\n const n = Math.max(0, Math.round(Number(sec) || 0));\n if (n < 1) return t('catalog.dlEtaCalc');\n const zh = getLocale() === 'zh-Hant';\n const h = Math.floor(n / 3600);\n const m = Math.floor((n % 3600) / 60);\n const s = n % 60;\n if (h > 0) return zh ? `${h} 小時 ${m} 分` : `${h}h ${m}m`;\n if (m > 0) return zh ? `${m} 分 ${s} 秒` : `${m}m ${s}s`;\n return zh ? `${s} 秒` : `${s}s`;\n}\n\nfunction fmtSpeed(bps) {\n const v = Number(bps) || 0;\n if (v <= 0) return '—';\n return `${fmtMb(v / (1024 * 1024))}`;\n}\n\nfunction catalogJobSpeed(job) {\n const samples = job.samples || [];\n if (samples.length < 2) return 0;\n const a = samples[0];\n const b = samples[samples.length - 1];\n const dt = (b.t - a.t) / 1000;\n if (dt < 0.4) return 0;\n return Math.max(0, (b.bytes - a.bytes) / dt);\n}\n\nfunction catalogJobEta(job) {\n const speed = catalogJobSpeed(job);\n if (!speed || !job.total || job.bytes >= job.total) return null;\n return (job.total - job.bytes) / speed;\n}\n\nfunction catalogJobPct(job) {\n if (!job.total) return 0;\n return Math.min(100, Math.max(0, Math.round((job.bytes / job.total) * 100)));\n}\n\nfunction catalogQueueHas(id) {\n return (state.catalogQueue || []).some(\n (j) =>\n (j.id === id || j.spec === id || String(j.spec).startsWith(`${id}:`)) &&\n (j.status === 'queued' || j.status === 'downloading'),\n );\n}\n\nfunction catalogDlDockHtml() {\n const jobs = (state.catalogQueue || []).filter(\n (j) => j.status === 'queued' || j.status === 'downloading' || j.status === 'done',\n );\n if (!jobs.length) return '';\n const rows = jobs\n .map((job) => {\n const pct = catalogJobPct(job);\n const speed = catalogJobSpeed(job);\n const eta = catalogJobEta(job);\n const active = job.status === 'downloading';\n const barClass = active && job.total <= 0 ? ' is-indeterminate' : '';\n let detail = t('catalog.dlQueued');\n if (job.status === 'downloading') {\n const parts = [];\n if (job.total > 0) {\n parts.push(`${pct}%`);\n parts.push(\n `${fmtMb(job.bytes / (1024 * 1024))} / ${fmtMb(job.total / (1024 * 1024))}`,\n );\n }\n if (speed > 0) parts.push(tf('catalog.dlSpeed', { speed: fmtSpeed(speed) }));\n parts.push(\n eta != null ? tf('catalog.dlEta', { time: fmtDuration(eta) }) : t('catalog.dlEtaCalc'),\n );\n detail = parts.join(' · ');\n } else if (job.status === 'done') {\n detail = t('catalog.dlDone');\n } else if (job.status === 'error') {\n detail = job.error || t('catalog.dlError');\n } else {\n detail = t('catalog.dlWaiting');\n }\n const badge =\n job.status === 'downloading'\n ? t('catalog.dlActive')\n : job.status === 'queued'\n ? t('catalog.dlQueued')\n : job.status === 'done'\n ? t('catalog.dlDone')\n : t('catalog.dlError');\n return `\n <div class=\"catalog-dl-job catalog-dl-${escapeHtml(job.status)}\" data-dl-id=\"${escapeHtml(job.spec)}\">\n <div class=\"catalog-dl-job-head\">\n <div>\n <div class=\"cell-primary\">${escapeHtml(job.label || job.id)}</div>\n <div class=\"cell-sub mono\">${escapeHtml(job.spec)}</div>\n </div>\n <span class=\"badge ${job.status === 'error' ? 'warn' : job.status === 'done' ? 'success' : 'muted'}\">${escapeHtml(badge)}</span>\n </div>\n <div class=\"catalog-pull-progress${barClass}\">\n <div class=\"catalog-pull-bar\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"${pct}\">\n <span style=\"width:${job.total > 0 ? pct : 0}%\"></span>\n </div>\n <div class=\"catalog-pull-meta muted\">${escapeHtml(detail)}</div>\n </div>\n </div>`;\n })\n .join('');\n return `\n <section id=\"cat-dl-dock\" class=\"panel catalog-dl-dock\" aria-live=\"polite\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('catalog.dlQueue'))}</strong>\n <span class=\"muted\">${escapeHtml(String(jobs.length))}</span>\n </div>\n </div>\n <div class=\"catalog-dl-list\">${rows}</div>\n </section>`;\n}\n\nfunction paintCatalogQueue() {\n const host = document.getElementById('cat-dl-dock');\n const html = catalogDlDockHtml();\n if (!html) {\n if (host) host.remove();\n return;\n }\n if (host) {\n host.outerHTML = html;\n return;\n }\n const tabs = document.querySelector('.catalog-tabs-panel');\n if (tabs) tabs.insertAdjacentHTML('beforebegin', html);\n}\n\nfunction enqueueCatalogPull(spec, label) {\n const q = state.catalogQueue || [];\n if (q.some((j) => j.spec === spec && (j.status === 'queued' || j.status === 'downloading'))) {\n return;\n }\n q.push({\n id: spec.split(':')[0],\n spec,\n label: label || spec,\n status: 'queued',\n bytes: 0,\n total: 0,\n samples: [],\n error: '',\n });\n state.catalogQueue = q;\n paintCatalogQueue();\n pumpCatalogQueue().catch(onErr);\n}\n\nasync function pumpCatalogQueue() {\n if (state.catalogQueueRunning) return;\n const job = (state.catalogQueue || []).find((j) => j.status === 'queued');\n if (!job) return;\n state.catalogQueueRunning = true;\n job.status = 'downloading';\n job.samples = [{ t: Date.now(), bytes: 0 }];\n paintCatalogQueue();\n try {\n const res = await fetch(`${API}/catalog/pull`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(state.key ? { Authorization: `Bearer ${state.key}` } : {}),\n },\n body: JSON.stringify({ model: job.spec }),\n });\n const reader = res.body && res.body.getReader ? res.body.getReader() : null;\n let text = '';\n if (reader) {\n const dec = new TextDecoder();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n text += dec.decode(value, { stream: true });\n const lines = text.split('\\n').map((l) => l.trim()).filter(Boolean);\n const last = lines[lines.length - 1];\n if (!last) continue;\n try {\n const ev = JSON.parse(last);\n if (ev.status === 'downloading') {\n job.bytes = Number(ev.bytes) || 0;\n job.total = Number(ev.total) || 0;\n job.samples.push({ t: Date.now(), bytes: job.bytes });\n if (job.samples.length > 10) job.samples.shift();\n paintCatalogQueue();\n }\n } catch {\n /* partial line */\n }\n }\n } else {\n text = await res.text();\n }\n const lines = text.split('\\n').map((l) => l.trim()).filter(Boolean);\n const last = lines.length ? JSON.parse(lines[lines.length - 1]) : {};\n if (!res.ok) throw new Error(last.error?.message || last.reason || res.statusText);\n assertPullRecorded(last);\n job.status = 'done';\n job.bytes = job.total || job.bytes;\n paintCatalogQueue();\n setTimeout(() => {\n state.catalogQueue = (state.catalogQueue || []).filter((j) => j !== job);\n const busy = (state.catalogQueue || []).some(\n (j) => j.status === 'queued' || j.status === 'downloading',\n );\n if (state.page === 'catalog' && !busy) renderCatalog().catch(onErr);\n else paintCatalogQueue();\n }, 1800);\n } catch (err) {\n state.catalogQueue = (state.catalogQueue || []).filter((j) => j !== job);\n paintCatalogQueue();\n const msg = err instanceof Error ? err.message : String(err);\n if (!msg.includes('GGUF') && !msg.includes('GGUF 檔')) onErr(err);\n } finally {\n state.catalogQueueRunning = false;\n pumpCatalogQueue().catch(onErr);\n }\n}\n\nfunction catalogHubRowHtml(h, local) {\n const onDisk = catalogLocalsForPack({ id: h.id }, local);\n const isPulling = catalogQueueHas(h.id);\n const canPull =\n h.runtime === 'llamacpp' ||\n h.runtime === 'whisper' ||\n h.runtime === 'diffusion' ||\n h.runtime === 'tts';\n const pullBtn = canPull\n ? `<button type=\"button\" class=\"btn ${onDisk.length ? 'secondary' : ''} sm\" data-pull=\"${escapeHtml(h.id)}\" ${isPulling ? 'disabled' : ''}>${escapeHtml(isPulling ? t('catalog.pulling') : onDisk.length ? t('catalog.pullAgain') : t('catalog.pull'))}</button>`\n : `<span class=\"muted\">${escapeHtml(t('catalog.unsupported'))}</span>`;\n return `\n <tr>\n <td>\n <div class=\"cell-primary\">${escapeHtml(catalogPackName(h))}</div>\n <div class=\"cell-sub mono\">${escapeHtml(h.id)}</div>\n </td>\n <td><span class=\"badge muted\">${escapeHtml(catalogModalityLabel(h.modality))}</span></td>\n <td><span class=\"badge muted\">${escapeHtml(h.runtime || '—')}</span></td>\n <td class=\"catalog-vram-cell\">\n <div class=\"cell-primary\">${escapeHtml(fmtMb(h.sizeMb))}</div>\n <div class=\"cell-sub\">${escapeHtml(h.sizeLabel || t('catalog.sizeEst'))}</div>\n </td>\n <td class=\"catalog-vram-cell\">\n <div class=\"cell-primary\">${escapeHtml(fmtMb(h.vramMb))}</div>\n <div class=\"cell-sub\">${h.paramsB ? escapeHtml(`${h.paramsB}B`) : escapeHtml(t('catalog.sizeEst'))}</div>\n </td>\n <td>${escapeHtml(fmtDownloads(h.downloads))}</td>\n <td>${\n onDisk.length\n ? `<span class=\"badge success\">${escapeHtml(t('catalog.onDisk'))}</span>`\n : canPull\n ? `<span class=\"muted\">—</span>`\n : `<span class=\"badge warn\">${escapeHtml(t('catalog.unsupported'))}</span>`\n }</td>\n <td>\n <div class=\"row-actions\">\n ${pullBtn}\n </div>\n </td>\n </tr>`;\n}\n\nfunction bindCatalogPullButtons(root) {\n (root || document).querySelectorAll('[data-pull]').forEach((btn) => {\n if (btn.dataset.boundPull === '1') return;\n btn.dataset.boundPull = '1';\n btn.onclick = () => {\n const packId = btn.getAttribute('data-pull') || '';\n const sel = document.querySelector(`[data-quant-for=\"${CSS.escape(packId)}\"]`);\n const quant = sel && sel.value ? sel.value : '';\n const spec = quant ? `${packId}:${quant}` : packId;\n enqueueCatalogPull(spec, catalogPackName({ id: packId }));\n btn.disabled = true;\n };\n });\n}\n\nfunction catalogHubPagerHtml(shown, hasMore, loading) {\n return `\n <div class=\"data-pager\" id=\"cat-hub-pager\">\n <div class=\"data-pager-meta\">\n <span id=\"cat-hub-count\">${escapeHtml(tf('common.pagerTotal', { n: shown }))}</span>\n </div>\n <div class=\"data-pager-actions\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"cat-hub-more\" ${hasMore && !loading ? '' : 'disabled'}>${escapeHtml(loading ? t('catalog.hubLoading') : t('catalog.hubMore'))}</button>\n </div>\n </div>`;\n}\n\nasync function loadCatalogHub({ append = false } = {}) {\n if (state.catalogHubBusy) return;\n state.catalogHubBusy = true;\n const moreBtn = document.getElementById('cat-hub-more');\n if (moreBtn) {\n moreBtn.disabled = true;\n moreBtn.textContent = t('catalog.hubLoading');\n }\n const y = window.scrollY;\n try {\n const qs = new URLSearchParams();\n if (state.catalogHubQ) qs.set('q', state.catalogHubQ);\n if (state.catalogModality) qs.set('modality', state.catalogModality);\n if (append && state.catalogHubNext) qs.set('cursor', state.catalogHubNext);\n const data = await api(`/catalog/hub?${qs}`);\n const hits = (data.hits || []).filter((h) => h.supported !== false);\n state.catalogHubHits = append\n ? [...(state.catalogHubHits || []), ...hits]\n : hits;\n state.catalogHubNext = data.nextCursor || '';\n if (append) {\n const tbody = document.getElementById('cat-hub-tbody');\n if (tbody) {\n tbody.querySelector('.empty-row')?.remove();\n const local = state.catalogLocal || [];\n tbody.insertAdjacentHTML(\n 'beforeend',\n hits.map((h) => catalogHubRowHtml(h, local)).join(''),\n );\n bindCatalogPullButtons(tbody);\n }\n const count = document.getElementById('cat-hub-count');\n const shown = (state.catalogHubHits || []).length;\n if (count) count.textContent = tf('common.pagerTotal', { n: shown });\n const headMeta = document.querySelector('#catalog-tab-hub .panel-h-meta');\n if (headMeta) headMeta.textContent = tf('common.pagerTotal', { n: shown });\n if (moreBtn) {\n moreBtn.textContent = t('catalog.hubMore');\n moreBtn.disabled = !state.catalogHubNext;\n if (!state.catalogHubNext) moreBtn.remove();\n }\n window.scrollTo(0, y);\n return;\n }\n await renderCatalog();\n } catch (e) {\n if (!append) state.catalogHubHits = [];\n onErr(e);\n if (!append) await renderCatalog();\n } finally {\n state.catalogHubBusy = false;\n if (moreBtn && document.body.contains(moreBtn)) {\n moreBtn.disabled = !state.catalogHubNext;\n moreBtn.textContent = t('catalog.hubMore');\n }\n if (append) window.scrollTo(0, y);\n }\n}\n\nasync function renderCatalog() {\n let data = {};\n try {\n data = await api('/catalog');\n } catch (e) {\n onErr(e);\n }\n const packs = data.packs && data.packs.length ? data.packs : CURATED_PACKS;\n const local = data.local || [];\n state.catalogLocal = local;\n const loaded = data.loaded || [];\n if (data.popularSyncedAt) state.catalogPopularSyncedAt = data.popularSyncedAt;\n if (\n state.catalogHubHits == null &&\n Array.isArray(data.popular) &&\n data.popular.length\n ) {\n state.catalogHubHits = data.popular;\n }\n const loadedIds = new Set(loaded.map((m) => m.id));\n const usedMb = data.usedMb ?? 0;\n const budgetMb = data.budgetMb ?? 0;\n const vramPct = budgetMb\n ? Math.min(100, Math.round((usedMb / budgetMb) * 100))\n : 0;\n const tab =\n state.catalogTab === 'hub' || state.catalogTab === 'local'\n ? state.catalogTab\n : 'local';\n state.catalogTab = tab;\n const modality = state.catalogModality || '';\n const modalities = ['text', 'image', 'video', 'tts', 'stt'];\n const visiblePacks = modality\n ? packs.filter((p) => p.modality === modality)\n : packs;\n\n\n const packRows = visiblePacks\n .map((p) => {\n const onDisk = catalogLocalsForPack(p, local);\n const quants = p.quants || [];\n const defaultQ = catalogDefaultQuant(quants);\n const quantHtml = quants.length\n ? `<select class=\"catalog-quant-select\" data-quant-for=\"${escapeHtml(p.id)}\">${quants\n .map(\n (q) =>\n `<option value=\"${escapeHtml(q)}\" ${q === defaultQ ? 'selected' : ''}>${escapeHtml(q)}</option>`,\n )\n .join('')}</select>`\n : `<span class=\"muted\">${escapeHtml(t('catalog.noQuant'))}</span>`;\n const isPulling = catalogQueueHas(p.id);\n const pullLabel = isPulling\n ? t('catalog.pulling')\n : onDisk.length\n ? t('catalog.pullAgain')\n : t('catalog.pull');\n return `\n <tr>\n <td>\n <div class=\"cell-primary\">${escapeHtml(catalogPackName(p))}</div>\n <div class=\"cell-sub mono\" title=\"${escapeHtml(p.id)}\">${escapeHtml(p.id)}</div>\n </td>\n <td><span class=\"badge muted\">${escapeHtml(catalogModalityLabel(p.modality))}</span></td>\n <td><span class=\"badge muted\">${escapeHtml(p.runtime || '—')}</span></td>\n <td>${quantHtml}</td>\n <td class=\"catalog-vram-cell\">${p.vramMb ?? 0} MB</td>\n <td>${\n onDisk.length\n ? `<span class=\"badge success\">${escapeHtml(t('catalog.onDisk'))}</span>`\n : `<span class=\"muted\">—</span>`\n }</td>\n <td>\n <div class=\"row-actions\">\n <button type=\"button\" class=\"btn ${onDisk.length ? 'secondary' : ''} sm\" data-pull=\"${escapeHtml(p.id)}\" ${isPulling ? 'disabled' : ''}>${escapeHtml(pullLabel)}</button>\n </div>\n </td>\n </tr>`;\n })\n .join('');\n\n const packEmpty = `\n <tr class=\"empty-row\"><td colspan=\"7\">\n <div class=\"data-empty\">\n <div class=\"data-empty-icon\">∅</div>\n <strong>${escapeHtml(t('catalog.emptyPacks'))}</strong>\n </div>\n </td></tr>`;\n\n const localRows = local\n .map((m) => {\n const isLoaded = loadedIds.has(m.id);\n return `\n <tr>\n <td>\n <div class=\"cell-primary mono\">${escapeHtml(m.id)}</div>\n <div class=\"cell-sub\" title=\"${escapeHtml(m.path || '')}\">${escapeHtml(m.path || '—')}</div>\n </td>\n <td class=\"catalog-vram-cell\">${m.vramMb ?? 0} MB</td>\n <td>${\n isLoaded\n ? `<span class=\"badge success\">${escapeHtml(t('catalog.loaded'))}</span>`\n : `<span class=\"badge muted\">${escapeHtml(t('catalog.idle'))}</span>`\n }</td>\n <td>\n <div class=\"row-actions\">\n <button type=\"button\" class=\"btn sm\" data-load=\"${escapeHtml(m.id)}\" data-vram=\"${m.vramMb ?? 0}\" ${isLoaded ? 'disabled' : ''}>${escapeHtml(t('catalog.load'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" data-unload=\"${escapeHtml(m.id)}\" ${isLoaded ? '' : 'disabled'}>${escapeHtml(t('catalog.unload'))}</button>\n <button type=\"button\" class=\"btn danger sm\" data-rm=\"${escapeHtml(m.id)}\">${escapeHtml(t('catalog.delete'))}</button>\n </div>\n </td>\n </tr>`;\n })\n .join('');\n\n const localEmpty = `\n <tr class=\"empty-row\"><td colspan=\"4\">\n <div class=\"data-empty\">\n <div class=\"data-empty-icon\">∅</div>\n <strong>${escapeHtml(t('catalog.emptyLocal'))}</strong>\n <p class=\"muted\">${escapeHtml(t('catalog.emptyLocalHint'))}</p>\n </div>\n </td></tr>`;\n\n const loadedNames = loaded.map((m) => catalogPackName({ id: m.id })).join(', ');\n const kpiGrid = `\n <div class=\"grid catalog-kpi-grid media-kpi-grid\">\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('catalog.kpiLoaded'))}</div>\n <div class=\"value value-sm\">${loaded.length}</div>\n <div class=\"muted card-sub\">${escapeHtml(loadedNames || t('catalog.kpiLoadedNone'))}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('catalog.kpiVram'))}</div>\n <div class=\"value value-sm\">${usedMb}<span class=\"dash-kpi-den\">/${budgetMb}</span></div>\n <div class=\"usage-bar ${vramPct > 80 ? 'warn' : ''}\"><span style=\"width:${vramPct}%\"></span></div>\n <div class=\"muted card-sub\">${escapeHtml(tf('catalog.kpiVramSub', { used: usedMb, budget: budgetMb }))}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('catalog.kpiLocal'))}</div>\n <div class=\"value value-sm\">${local.length}</div>\n <div class=\"muted card-sub\">${escapeHtml(t('catalog.kpiLocalSub'))}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('catalog.tabHub'))}</div>\n <div class=\"value value-sm\">${(data.popular || []).length}</div>\n <div class=\"muted card-sub\">${escapeHtml(t('catalog.sync'))}</div>\n </div>\n </div>`;\n\n const modFilter = filterPanelHtml({\n title: t('catalog.filterModality'),\n hint: t('catalog.intro'),\n meta: tf('common.pagerTotal', { n: visiblePacks.length }),\n searchHtml: '',\n gridHtml: `\n <label>${escapeHtml(t('catalog.filterModality'))}\n <select id=\"cat-mod\">\n <option value=\"\">${escapeHtml(t('catalog.filterAll'))}</option>\n ${modalities\n .map(\n (m) =>\n `<option value=\"${escapeHtml(m)}\" ${modality === m ? 'selected' : ''}>${escapeHtml(catalogModalityLabel(m))}</option>`,\n )\n .join('')}\n </select>\n </label>`,\n });\n\n const packsTable = `\n <div class=\"panel data-table-panel\">\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr>\n <th>${escapeHtml(t('catalog.colName'))}</th>\n <th>${escapeHtml(t('catalog.colModality'))}</th>\n <th>${escapeHtml(t('catalog.colRuntime'))}</th>\n <th>${escapeHtml(t('catalog.colQuant'))}</th>\n <th>${escapeHtml(t('catalog.colVram'))}</th>\n <th>${escapeHtml(t('catalog.colStatus'))}</th>\n <th>${escapeHtml(t('common.actions'))}</th>\n </tr></thead>\n <tbody>${packRows || packEmpty}</tbody>\n </table>\n </div>\n </div>`;\n\n const localTable = `\n <div class=\"panel data-table-panel\">\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr>\n <th>${escapeHtml(t('catalog.colName'))}</th>\n <th>${escapeHtml(t('catalog.colVram'))}</th>\n <th>${escapeHtml(t('catalog.colStatus'))}</th>\n <th>${escapeHtml(t('common.actions'))}</th>\n </tr></thead>\n <tbody>${localRows || localEmpty}</tbody>\n </table>\n </div>\n </div>`;\n\n const hubHits = (Array.isArray(state.catalogHubHits) ? state.catalogHubHits : []).filter(\n (h) => h.supported !== false,\n );\n const hubRows = hubHits.map((h) => catalogHubRowHtml(h, local)).join('');\n const hubEmpty = `\n <tr class=\"empty-row\"><td colspan=\"8\">\n <div class=\"data-empty\">\n <div class=\"data-empty-icon\">∅</div>\n <strong>${escapeHtml(t('catalog.hubEmpty'))}</strong>\n </div>\n </td></tr>`;\n const hubModChips = [\n ['', t('catalog.filterAll')],\n ...modalities.map((m) => [m, catalogModalityLabel(m)]),\n ]\n .map(\n ([val, label]) =>\n `<button type=\"button\" class=\"catalog-mod-chip ${modality === val ? 'is-on' : ''}\" data-hub-mod=\"${escapeHtml(val)}\" aria-pressed=\"${modality === val}\">${escapeHtml(label)}</button>`,\n )\n .join('');\n const hubSearch = `\n <div class=\"catalog-hub-stack\">\n <div class=\"panel catalog-hub-card\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('catalog.hubBrowse'))}</strong>\n <span class=\"muted\">${escapeHtml(t('catalog.hubBrowseHint'))}</span>\n </div>\n ${hubHits.length ? `<span class=\"panel-h-meta muted\">${escapeHtml(tf('common.pagerTotal', { n: hubHits.length }))}</span>` : ''}\n </div>\n <div class=\"catalog-hub-row\">\n <input type=\"search\" id=\"cat-hub-q\" value=\"${escapeHtml(state.catalogHubQ || '')}\" placeholder=\"${escapeHtml(t('catalog.hubSearchPh'))}\" aria-label=\"${escapeHtml(t('catalog.hubSearch'))}\" />\n <button type=\"button\" class=\"btn sm\" id=\"cat-hub-go\">${escapeHtml(t('catalog.hubSearchBtn'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"cat-hub-reset\">${escapeHtml(t('common.reset'))}</button>\n </div>\n <div class=\"catalog-mod-chips\" role=\"group\" aria-label=\"${escapeHtml(t('catalog.filterModality'))}\">${hubModChips}</div>\n </div>\n <div class=\"panel catalog-hub-card catalog-hub-pull-card\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('catalog.pullSpec'))}</strong>\n <span class=\"muted\">${escapeHtml(t('catalog.pullSpecHint'))}</span>\n </div>\n </div>\n <div class=\"catalog-hub-row\">\n <input type=\"text\" id=\"cat-spec\" placeholder=\"${escapeHtml(t('catalog.pullSpecPh'))}\" autocomplete=\"off\" spellcheck=\"false\" aria-label=\"${escapeHtml(t('catalog.pullSpec'))}\" />\n <button type=\"button\" class=\"btn sm\" id=\"cat-spec-pull\">${escapeHtml(t('catalog.pullSpecBtn'))}</button>\n </div>\n </div>\n </div>`;\n const hubTable = `\n <div class=\"panel data-table-panel\">\n <div class=\"table-wrap\">\n <table class=\"data-table\">\n <thead><tr>\n <th>${escapeHtml(t('catalog.colName'))}</th>\n <th>${escapeHtml(t('catalog.colModality'))}</th>\n <th>${escapeHtml(t('catalog.colRuntime'))}</th>\n <th>${escapeHtml(t('catalog.colSize'))}</th>\n <th>${escapeHtml(t('catalog.colVram'))}</th>\n <th>${escapeHtml(t('catalog.downloads'))}</th>\n <th>${escapeHtml(t('catalog.colStatus'))}</th>\n <th>${escapeHtml(t('common.actions'))}</th>\n </tr></thead>\n <tbody id=\"cat-hub-tbody\">${hubRows || hubEmpty}</tbody>\n </table>\n </div>\n ${hubHits.length ? catalogHubPagerHtml(hubHits.length, Boolean(state.catalogHubNext), false) : ''}\n </div>`;\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('catalog.title'))}</h2>\n <div class=\"toolbar\">\n <button type=\"button\" class=\"btn secondary sm\" data-nav=\"runtimes\">${escapeHtml(t('nav.runtimes'))}</button>\n <button type=\"button\" class=\"btn sm\" id=\"cat-sync\">${escapeHtml(t('catalog.sync'))}</button>\n </div>\n </div>\n ${pageMetaHtml([\n t('catalog.intro'),\n t('catalog.syncHint'),\n state.catalogPopularSyncedAt\n ? tf('catalog.syncAt', { when: fmtTime(state.catalogPopularSyncedAt) })\n : '',\n ])}\n ${kpiGrid}\n ${catalogDlDockHtml()}\n <div class=\"usage-tabs-panel panel catalog-tabs-panel media-tabs-panel\">\n <div class=\"seg-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('catalog.title'))}\">\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'local' ? 'is-active' : ''}\" data-catalog-tab=\"local\" aria-selected=\"${tab === 'local'}\">\n ${escapeHtml(t('catalog.tabLocal'))}\n <span class=\"seg-tab-count\">${local.length}</span>\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'hub' ? 'is-active' : ''}\" data-catalog-tab=\"hub\" aria-selected=\"${tab === 'hub'}\">\n ${escapeHtml(t('catalog.tabHub'))}\n </button>\n </div>\n <div class=\"usage-tab-body\">\n <div class=\"usage-tab-pane catalog-tab-pane\" id=\"catalog-tab-local\" ${tab === 'local' ? '' : 'hidden'}>\n ${localTable}\n </div>\n <div class=\"usage-tab-pane catalog-tab-pane\" id=\"catalog-tab-hub\" ${tab === 'hub' ? '' : 'hidden'}>\n ${hubSearch}\n ${hubTable}\n </div>\n </div>\n </div>\n `);\n bindShell();\n document.querySelectorAll('[data-catalog-tab]').forEach((btn) => {\n btn.onclick = () => {\n const next = btn.getAttribute('data-catalog-tab') || 'local';\n state.catalogTab = next;\n document.querySelectorAll('.catalog-tab-pane').forEach((pane) => {\n pane.hidden = pane.id !== `catalog-tab-${next}`;\n });\n document.querySelectorAll('[data-catalog-tab]').forEach((tabBtn) => {\n const on = tabBtn.getAttribute('data-catalog-tab') === next;\n tabBtn.classList.toggle('is-active', on);\n tabBtn.setAttribute('aria-selected', String(on));\n });\n };\n });\n const modSel = document.getElementById('cat-mod');\n if (modSel) {\n modSel.onchange = () => {\n state.catalogModality = modSel.value;\n renderCatalog().catch(onErr);\n };\n }\n document\n .querySelector('#catalog-tab-packs [data-filter-apply]')\n ?.addEventListener('click', () => {\n state.catalogModality = document.getElementById('cat-mod')?.value || '';\n renderCatalog().catch(onErr);\n });\n document\n .querySelector('#catalog-tab-packs [data-filter-reset]')\n ?.addEventListener('click', () => {\n state.catalogModality = '';\n renderCatalog().catch(onErr);\n });\n const runHubSearch = () => {\n state.catalogHubQ = document.getElementById('cat-hub-q')?.value.trim() || '';\n state.catalogHubHits = null;\n loadCatalogHub().catch(onErr);\n };\n document.getElementById('cat-hub-go')?.addEventListener('click', runHubSearch);\n document.getElementById('cat-hub-reset')?.addEventListener('click', () => {\n state.catalogHubQ = '';\n state.catalogModality = '';\n state.catalogHubHits = null;\n loadCatalogHub().catch(onErr);\n });\n document.querySelectorAll('[data-hub-mod]').forEach((chip) => {\n chip.addEventListener('click', () => {\n state.catalogModality = chip.getAttribute('data-hub-mod') || '';\n state.catalogHubQ = document.getElementById('cat-hub-q')?.value.trim() || '';\n state.catalogHubHits = null;\n loadCatalogHub().catch(onErr);\n });\n });\n document.getElementById('cat-hub-q')?.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n runHubSearch();\n }\n });\n document.getElementById('cat-spec')?.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n document.getElementById('cat-spec-pull')?.click();\n }\n });\n document.getElementById('cat-hub-more')?.addEventListener('click', () => {\n loadCatalogHub({ append: true }).catch(onErr);\n });\n if (tab === 'hub' && state.catalogHubHits == null && !state.catalogHubBusy) {\n loadCatalogHub().catch(onErr);\n }\n document.getElementById('cat-sync')?.addEventListener('click', async () => {\n const btn = document.getElementById('cat-sync');\n if (!btn) return;\n btn.setAttribute('disabled', 'disabled');\n btn.textContent = t('catalog.syncing');\n try {\n const out = await api('/catalog/sync', {\n method: 'POST',\n body: JSON.stringify({}),\n });\n state.catalogHubHits = out.hits || [];\n state.catalogHubNext = '';\n state.catalogHubQ = '';\n state.catalogTab = 'hub';\n state.catalogPopularSyncedAt = out.syncedAt || '';\n await renderCatalog();\n } catch (e) {\n btn.removeAttribute('disabled');\n btn.textContent = t('catalog.sync');\n onErr(e);\n }\n });\n bindCatalogPullButtons(document);\n document.querySelectorAll('[data-load]').forEach((btn) => {\n btn.onclick = async () => {\n try {\n await api('/models/load', {\n method: 'POST',\n body: JSON.stringify({\n id: btn.getAttribute('data-load'),\n vramMb: Number(btn.getAttribute('data-vram') || 0),\n }),\n });\n await renderCatalog();\n } catch (e) {\n onErr(e);\n }\n };\n });\n document.querySelectorAll('[data-unload]').forEach((btn) => {\n btn.onclick = async () => {\n try {\n await api('/models/unload', {\n method: 'POST',\n body: JSON.stringify({ id: btn.getAttribute('data-unload') }),\n });\n await renderCatalog();\n } catch (e) {\n onErr(e);\n }\n };\n });\n document.querySelectorAll('[data-rm]').forEach((btn) => {\n btn.onclick = async () => {\n const id = btn.getAttribute('data-rm') || '';\n const yes = await uiConfirm({\n variant: 'danger',\n message: tf('catalog.deleteConfirm', { id }),\n confirmText: t('catalog.delete'),\n });\n if (!yes) return;\n try {\n await api('/catalog/rm', {\n method: 'POST',\n body: JSON.stringify({ id }),\n });\n await renderCatalog();\n } catch (e) {\n onErr(e);\n }\n };\n });\n document.getElementById('cat-spec-pull')?.addEventListener('click', () => {\n const spec = document.getElementById('cat-spec')?.value.trim();\n if (!spec) return;\n enqueueCatalogPull(spec, spec);\n });\n}\n\nfunction runtimeStatusBadge(status) {\n if (status === 'installed') {\n return `<span class=\"badge success\">${escapeHtml(t('runtimes.statusInstalled'))}</span>`;\n }\n if (status === 'configured') {\n return `<span class=\"badge success\">${escapeHtml(t('runtimes.statusConfigured'))}</span>`;\n }\n if (status === 'unsupported') {\n return `<span class=\"badge muted\">${escapeHtml(t('runtimes.statusUnsupported'))}</span>`;\n }\n return `<span class=\"badge warn\">${escapeHtml(t('runtimes.statusMissing'))}</span>`;\n}\n\nfunction runtimeSupportLabel(level) {\n if (level === 'full') return t('runtimes.supportFull');\n if (level === 'partial') return t('runtimes.supportPartial');\n return t('runtimes.supportNone');\n}\n\nfunction paintRuntimeInstallLog() {\n const job = state.runtimesInstall;\n const pre = document.getElementById('rt-install-log');\n if (pre && job) {\n pre.textContent = (job.lines || []).join('\\n');\n pre.scrollTop = pre.scrollHeight;\n }\n const running = job && job.status === 'running';\n document.querySelectorAll('[data-rt-install]').forEach((btn) => {\n const id = btn.getAttribute('data-rt-install');\n btn.disabled = Boolean(running);\n if (running && job.id === id && job.action !== 'uninstall') {\n btn.textContent = t('runtimes.installing');\n }\n });\n document.querySelectorAll('[data-rt-uninstall]').forEach((btn) => {\n const id = btn.getAttribute('data-rt-uninstall');\n btn.disabled = Boolean(running);\n if (running && job.id === id && job.action === 'uninstall') {\n btn.textContent = t('runtimes.uninstalling');\n }\n });\n}\n\nasync function startRuntimeInstall(id, action) {\n if (state.runtimesInstall?.status === 'running') return;\n const act = action === 'uninstall' ? 'uninstall' : 'install';\n state.runtimesInstall = { id, action: act, status: 'running', lines: [] };\n await renderRuntimes();\n try {\n const url =\n act === 'uninstall'\n ? `${API}/runtimes/uninstall`\n : `${API}/runtimes/install`;\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(state.key ? { Authorization: `Bearer ${state.key}` } : {}),\n },\n body: JSON.stringify({ id }),\n });\n const reader = res.body && res.body.getReader ? res.body.getReader() : null;\n if (!res.ok || !reader) {\n const text = await res.text();\n let msg = text;\n try {\n msg = JSON.parse(text)?.error?.message || text;\n } catch {\n /* keep */\n }\n state.runtimesInstall.status = 'error';\n state.runtimesInstall.lines.push(msg || res.statusText);\n paintRuntimeInstallLog();\n } else {\n const dec = new TextDecoder();\n let buf = '';\n const consume = (raw) => {\n if (!raw) return;\n try {\n const ev = JSON.parse(raw);\n if (ev.type === 'step' && Array.isArray(ev.argv)) {\n state.runtimesInstall.lines.push(`$ ${ev.argv.join(' ')}`);\n } else if (ev.type === 'log' && ev.line) {\n state.runtimesInstall.lines.push(ev.line);\n } else if (ev.type === 'error' && ev.message) {\n state.runtimesInstall.lines.push(ev.message);\n state.runtimesInstall.status = 'error';\n } else if (ev.type === 'done') {\n state.runtimesInstall.status = ev.code === 0 ? 'done' : 'error';\n const okKey =\n state.runtimesInstall.action === 'uninstall'\n ? 'runtimes.uninstallDone'\n : 'runtimes.installDone';\n const failKey =\n state.runtimesInstall.action === 'uninstall'\n ? 'runtimes.uninstallFail'\n : 'runtimes.installFail';\n state.runtimesInstall.lines.push(\n ev.code === 0 ? t(okKey) : t(failKey),\n );\n }\n if (state.runtimesInstall.lines.length > 200) {\n state.runtimesInstall.lines = state.runtimesInstall.lines.slice(-200);\n }\n paintRuntimeInstallLog();\n } catch {\n /* skip partial JSON */\n }\n };\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n buf += dec.decode();\n break;\n }\n buf += dec.decode(value, { stream: true });\n const parts = buf.split('\\n');\n buf = parts.pop() || '';\n for (const line of parts) consume(line.trim());\n }\n consume(buf.trim());\n }\n } catch (e) {\n state.runtimesInstall.status = 'error';\n state.runtimesInstall.lines.push(e.message || String(e));\n paintRuntimeInstallLog();\n }\n state.runtimesReport = null;\n await renderRuntimes();\n}\n\nasync function renderRuntimes() {\n if (!state.runtimesReport) {\n try {\n state.runtimesReport = await api('/runtimes');\n } catch (e) {\n onErr(e);\n state.runtimesReport = { host: { os: 'linux', osLabel: 'Linux', arch: '', platform: '—' }, items: [] };\n }\n }\n const report = state.runtimesReport;\n const hostOs = report.host?.os || 'linux';\n const osFilter = state.runtimesOs || 'host';\n const viewOs =\n osFilter === 'host' || osFilter === 'all' ? hostOs : osFilter;\n const mod = state.runtimesMod || '';\n const items = (report.items || []).filter((it) => {\n if (mod && !(it.modalities || []).includes(mod)) return false;\n if (osFilter === 'all') return true;\n const os = osFilter === 'host' ? hostOs : osFilter;\n return (it.support || {})[os] !== 'none';\n });\n const ready = (report.items || []).filter(\n (it) => it.status === 'installed' || it.status === 'configured',\n ).length;\n const missing = (report.items || []).filter((it) => it.status === 'missing').length;\n\n const osChips = [\n ['host', t('runtimes.filterHost')],\n ['all', t('runtimes.filterAll')],\n ['darwin', t('runtimes.osMac')],\n ['linux', t('runtimes.osLinux')],\n ['win32', t('runtimes.osWin')],\n ]\n .map(\n ([val, label]) =>\n `<button type=\"button\" class=\"catalog-mod-chip ${osFilter === val ? 'is-on' : ''}\" data-rt-os=\"${val}\">${escapeHtml(label)}</button>`,\n )\n .join('');\n const modChips = [\n ['', t('catalog.filterAll')],\n ['text', t('catalog.mod.text')],\n ['image', t('catalog.mod.image')],\n ['video', t('catalog.mod.video')],\n ['tts', t('catalog.mod.tts')],\n ['stt', t('catalog.mod.stt')],\n ]\n .map(\n ([val, label]) =>\n `<button type=\"button\" class=\"catalog-mod-chip ${mod === val ? 'is-on' : ''}\" data-rt-mod=\"${escapeHtml(val)}\">${escapeHtml(label)}</button>`,\n )\n .join('');\n\n const job = state.runtimesInstall;\n const cards = items\n .map((it) => {\n const cmd = (it.install && it.install[viewOs]) || '';\n const note = (it.notes && it.notes[viewOs]) || it.detail || '';\n const osCells = ['darwin', 'linux', 'win32']\n .map((os) => {\n const lv = (it.support || {})[os] || 'none';\n const cls = lv === 'full' ? 'success' : lv === 'partial' ? 'warn' : 'muted';\n const label =\n os === 'darwin' ? t('runtimes.osMac') : os === 'win32' ? t('runtimes.osWin') : t('runtimes.osLinux');\n return `<span class=\"badge ${cls}\" title=\"${escapeHtml(label)}\">${escapeHtml(label)} · ${escapeHtml(runtimeSupportLabel(lv))}</span>`;\n })\n .join('');\n const mods = (it.modalities || [])\n .map((m) => `<span class=\"badge muted\">${escapeHtml(hasT(`catalog.mod.${m}`) ? t(`catalog.mod.${m}`) : m)}</span>`)\n .join('');\n const canInstall = Boolean(it.installable) && viewOs === hostOs;\n const canUninstall =\n Boolean(it.uninstallable) &&\n viewOs === hostOs &&\n (it.status === 'installed' || it.status === 'configured');\n const thisJob = job && job.id === it.id;\n const running = job?.status === 'running';\n const installLabel =\n running && thisJob && job.action !== 'uninstall'\n ? t('runtimes.installing')\n : it.status === 'installed' || it.status === 'configured'\n ? t('runtimes.reinstall')\n : t('runtimes.install');\n const uninstallLabel =\n running && thisJob && job.action === 'uninstall'\n ? t('runtimes.uninstalling')\n : t('runtimes.uninstall');\n const logHtml =\n thisJob && (job.lines || []).length\n ? `<pre class=\"runtime-install-log\" id=\"rt-install-log\">${escapeHtml((job.lines || []).join('\\n'))}</pre>`\n : thisJob\n ? `<pre class=\"runtime-install-log\" id=\"rt-install-log\"></pre>`\n : '';\n return `\n <article class=\"panel runtime-card ${thisJob && running ? 'is-installing' : ''}\" data-runtime-id=\"${escapeHtml(it.id)}\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(it.name)}</strong>\n <span class=\"muted\">${escapeHtml(hasT(`runtimes.${it.id}`) ? t(`runtimes.${it.id}`) : '')}</span>\n </div>\n ${runtimeStatusBadge(it.status)}\n </div>\n <div class=\"panel-pad runtime-card-body\">\n <div class=\"runtime-card-mods\">${mods}</div>\n <div class=\"runtime-os-row\">${osCells}</div>\n ${\n it.path\n ? `<div class=\"cell-sub mono\">${escapeHtml(t('runtimes.path'))}: ${escapeHtml(it.path)}${it.version ? ` · ${escapeHtml(it.version)}` : ''}</div>`\n : `<div class=\"cell-sub muted\">${escapeHtml(note)}</div>`\n }\n <pre class=\"runtime-cmd\">${escapeHtml(cmd)}</pre>\n ${logHtml}\n <div class=\"runtime-card-actions\">\n ${\n canInstall\n ? `<button type=\"button\" class=\"btn sm\" data-rt-install=\"${escapeHtml(it.id)}\" ${running ? 'disabled' : ''}>${escapeHtml(installLabel)}</button>`\n : ''\n }\n ${\n canUninstall\n ? `<button type=\"button\" class=\"btn danger sm\" data-rt-uninstall=\"${escapeHtml(it.id)}\" data-rt-name=\"${escapeHtml(it.name)}\" ${running ? 'disabled' : ''}>${escapeHtml(uninstallLabel)}</button>`\n : ''\n }\n <button type=\"button\" class=\"btn secondary sm\" data-copy-cmd=\"${encodeURIComponent(cmd)}\">${escapeHtml(t('runtimes.copyCmd'))}</button>\n <a class=\"btn secondary sm\" href=\"${escapeHtml(it.docs)}\" target=\"_blank\" rel=\"noopener noreferrer\">${escapeHtml(t('runtimes.docs'))}</a>\n </div>\n </div>\n </article>`;\n })\n .join('');\n\n document.getElementById('app').innerHTML = shell(`\n <div class=\"topbar\">\n <h2>${escapeHtml(t('runtimes.title'))}</h2>\n <div class=\"toolbar\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"rt-refresh\">${escapeHtml(t('runtimes.refresh'))}</button>\n </div>\n </div>\n ${pageMetaHtml([t('runtimes.intro'), tf('runtimes.cmdFor', { os: t(viewOs === 'darwin' ? 'runtimes.osMac' : viewOs === 'win32' ? 'runtimes.osWin' : 'runtimes.osLinux') })])}\n <div class=\"grid catalog-kpi-grid media-kpi-grid\">\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('runtimes.kpiInstalled'))}</div>\n <div class=\"value value-sm\">${ready}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('runtimes.kpiMissing'))}</div>\n <div class=\"value value-sm\">${missing}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('runtimes.kpiHost'))}</div>\n <div class=\"value value-sm\">${escapeHtml(report.host?.osLabel || '—')}</div>\n <div class=\"muted card-sub\">${escapeHtml(report.host?.platform || '')}</div>\n </div>\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(t('runtimes.kpiArch'))}</div>\n <div class=\"value value-sm\">${escapeHtml(report.host?.arch || '—')}</div>\n </div>\n </div>\n <div class=\"panel catalog-hub-card\" style=\"margin-bottom:14px\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('runtimes.filterOs'))}</strong>\n </div>\n </div>\n <div class=\"catalog-mod-chips\" style=\"padding-top:12px\">${osChips}</div>\n <div class=\"catalog-mod-chips\">${modChips}</div>\n </div>\n <div class=\"runtime-grid\">\n ${cards || `<div class=\"data-empty\"><strong>${escapeHtml(t('runtimes.empty'))}</strong></div>`}\n </div>\n `);\n bindShell();\n document.querySelectorAll('[data-rt-os]').forEach((btn) => {\n btn.onclick = () => {\n state.runtimesOs = btn.getAttribute('data-rt-os') || 'host';\n renderRuntimes().catch(onErr);\n };\n });\n document.querySelectorAll('[data-rt-mod]').forEach((btn) => {\n btn.onclick = () => {\n state.runtimesMod = btn.getAttribute('data-rt-mod') || '';\n renderRuntimes().catch(onErr);\n };\n });\n document.getElementById('rt-refresh')?.addEventListener('click', () => {\n state.runtimesReport = null;\n renderRuntimes().catch(onErr);\n });\n document.querySelectorAll('[data-rt-install]').forEach((btn) => {\n btn.onclick = () => {\n const id = btn.getAttribute('data-rt-install');\n if (id) startRuntimeInstall(id, 'install').catch(onErr);\n };\n });\n document.querySelectorAll('[data-rt-uninstall]').forEach((btn) => {\n btn.onclick = async () => {\n const id = btn.getAttribute('data-rt-uninstall');\n const name = btn.getAttribute('data-rt-name') || id;\n if (!id) return;\n const ok = await openUiDialog({\n variant: 'danger',\n title: t('runtimes.uninstall'),\n message: tf('runtimes.uninstallConfirm', { name }),\n confirmText: t('runtimes.uninstall'),\n });\n if (ok) startRuntimeInstall(id, 'uninstall').catch(onErr);\n };\n });\n document.querySelectorAll('[data-copy-cmd]').forEach((btn) => {\n btn.onclick = async () => {\n let v = btn.getAttribute('data-copy-cmd') || '';\n try {\n v = decodeURIComponent(v);\n } catch {\n /* keep raw */\n }\n try {\n await navigator.clipboard.writeText(v);\n btn.textContent = t('loginCopied');\n setTimeout(() => {\n btn.textContent = t('runtimes.copyCmd');\n }, 1200);\n } catch {\n /* ignore */\n }\n };\n });\n}\n\nasync function render() {\n const app = document.getElementById('app');\n try {\n if (!state.key) {\n await renderLogin();\n return;\n }\n if (!state.me) await ensureMe();\n if (state.page === 'dashboard') await renderDashboard();\n else if (state.page === 'chat') await renderChatPlayground();\n else if (state.page === 'chats') await renderChats();\n else if (state.page === 'keys') await renderKeys();\n else if (state.page === 'documents') await renderDocuments();\n else if (state.page === 'media') await renderMedia();\n else if (state.page === 'catalog') await renderCatalog();\n else if (state.page === 'runtimes') await renderRuntimes();\n else if (state.page === 'audit') await renderAudit();\n else if (state.page === 'settings') await renderSettings();\n else if (state.page === 'apiFeatures') await renderApiFeatures();\n else if (state.page === 'usage') await renderUsage();\n else if (state.page === 'ddos') await renderDdos();\n else if (state.page === 'queue') await renderQueue();\n else if (state.page === 'pm2') await renderPm2();\n else if (state.page === 'system') await renderSystem();\n else if (state.page === 'support') await renderSupport();\n else await renderDashboard();\n } catch (e) {\n app.innerHTML = shell(`<div class=\"error-box\">${escapeHtml(e.message)}</div>`);\n bindShell();\n }\n}\n\n/** @type {ReturnType<typeof setInterval> | null} */\nlet queueTimer = null;\n\n/** Queue list filter + page tabs (mirrors media / usage) */\nconst queueFilter = {\n /** 'overview' | 'jobs' | 'policy' */\n tab: 'overview',\n status: '',\n sortBy: 'queuedAt',\n sortDir: 'desc',\n limit: 20,\n offset: 0,\n};\n\nfunction fmtQueueAge(ms) {\n if (!ms || ms < 0) return '—';\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60_000) return `${Math.round(ms / 1000)}s`;\n if (ms < 3_600_000) return `${Math.round(ms / 60_000)}m`;\n return `${(ms / 3_600_000).toFixed(1)}h`;\n}\n\n/** Fields compared for queue policy presets (operational pause/drain excluded). */\nconst QUEUE_PRESET_KEYS = [\n 'enabled',\n 'globalConcurrency',\n 'perKeyConcurrency',\n 'maxQueueDepth',\n 'maxQueueDepthPerKey',\n 'fairness',\n 'defaultPriority',\n 'playgroundPriority',\n 'leaseMs',\n 'maxWaitMs',\n];\n\n/** Built-in schemes — same UX pattern as DDoS center. */\nfunction queuePolicyPresets() {\n return {\n relaxed: {\n enabled: true,\n globalConcurrency: 6,\n perKeyConcurrency: 2,\n maxQueueDepth: 200,\n maxQueueDepthPerKey: 40,\n fairness: 'weighted_round_robin',\n defaultPriority: 100,\n playgroundPriority: 40,\n leaseMs: 60_000,\n maxWaitMs: 900_000,\n },\n balanced: {\n enabled: true,\n globalConcurrency: 4,\n perKeyConcurrency: 1,\n maxQueueDepth: 100,\n maxQueueDepthPerKey: 20,\n fairness: 'weighted_round_robin',\n defaultPriority: 100,\n playgroundPriority: 50,\n leaseMs: 45_000,\n maxWaitMs: 600_000,\n },\n strict: {\n enabled: true,\n globalConcurrency: 2,\n perKeyConcurrency: 1,\n maxQueueDepth: 40,\n maxQueueDepthPerKey: 8,\n fairness: 'fifo_global',\n defaultPriority: 100,\n playgroundPriority: 80,\n leaseMs: 30_000,\n maxWaitMs: 300_000,\n },\n };\n}\n\nfunction normalizeQueuePolicySlice(p) {\n if (!p) return {};\n const out = {};\n for (const k of QUEUE_PRESET_KEYS) {\n const v = p[k];\n if (typeof v === 'boolean') out[k] = v;\n else if (typeof v === 'number' && Number.isFinite(v)) out[k] = Math.round(v);\n else if (typeof v === 'string') out[k] = v;\n else if (v == null) out[k] = null;\n else out[k] = v;\n }\n return out;\n}\n\nfunction queuePoliciesEqual(a, b) {\n return (\n JSON.stringify(normalizeQueuePolicySlice(a)) ===\n JSON.stringify(normalizeQueuePolicySlice(b))\n );\n}\n\n/** @returns {'relaxed'|'balanced'|'strict'|'custom'} */\nfunction matchQueuePreset(policy) {\n if (!policy) return 'custom';\n const presets = queuePolicyPresets();\n for (const name of ['relaxed', 'balanced', 'strict']) {\n if (queuePoliciesEqual(policy, presets[name])) return name;\n }\n return 'custom';\n}\n\nfunction queuePresetLabel(name) {\n if (name === 'relaxed') return t('queue.presetRelaxed');\n if (name === 'balanced') return t('queue.presetBalanced');\n if (name === 'strict') return t('queue.presetStrict');\n return t('queue.presetCustom');\n}\n\nfunction queuePresetBadgeHtml(name, { unsaved = false } = {}) {\n const label = queuePresetLabel(name);\n const tone =\n name === 'relaxed'\n ? 'relaxed'\n : name === 'balanced'\n ? 'balanced'\n : name === 'strict'\n ? 'strict'\n : 'custom';\n const status = unsaved\n ? tf('queue.presetFormLabel', { name: label })\n : tf('queue.presetActiveLabel', { name: label });\n return `<span class=\"ddos-preset-badge is-${tone}\" id=\"queue-preset-badge\" title=\"${escapeHtml(status)}\">${escapeHtml(status)}</span>`;\n}\n\nfunction readQueuePolicyForm() {\n return {\n // Master switch lives in topbar (not a form checkbox)\n enabled: document.getElementById('q-master-enabled')\n ? isMasterToggleOn('q-master-enabled')\n : true,\n globalConcurrency: Math.max(\n 1,\n Math.min(64, Math.floor(numVal('qp-gconc', 4))),\n ),\n perKeyConcurrency: Math.max(\n 1,\n Math.min(16, Math.floor(numVal('qp-kconc', 1))),\n ),\n maxQueueDepth: Math.max(1, Math.floor(numVal('qp-depth', 100))),\n maxQueueDepthPerKey: Math.max(1, Math.floor(numVal('qp-depthk', 20))),\n fairness:\n document.getElementById('qp-fair')?.value === 'fifo_global'\n ? 'fifo_global'\n : 'weighted_round_robin',\n defaultPriority: Math.max(0, Math.min(1000, Math.floor(numVal('qp-pri', 100)))),\n playgroundPriority: Math.max(\n 0,\n Math.min(1000, Math.floor(numVal('qp-ppri', 50))),\n ),\n leaseMs: Math.max(5000, Math.floor(numVal('qp-lease', 45000))),\n maxWaitMs: Math.max(5000, Math.floor(numVal('qp-wait', 600000))),\n };\n}\n\nfunction applyQueueEnabledUi(on) {\n setMasterToggle(\n 'q-master-enabled',\n on,\n t('queue.masterOn'),\n t('queue.masterOff'),\n );\n setFeatureRootOff('queue-root', !on);\n setFeatureOffBanner('queue-disabled-banner', !on);\n // Status pill in runtime panel\n const pill = document.getElementById('qk-pill-enabled');\n if (pill) {\n pill.innerHTML = dashStatusPill(on, t('dash.on'), t('dash.off'));\n }\n}\n\nfunction applyQueuePresetToForm(values) {\n if (!values) return;\n const setNum = (id, v) => {\n const el = document.getElementById(id);\n if (el) el.value = String(v);\n };\n applyQueueEnabledUi(values.enabled !== false);\n setNum('qp-gconc', values.globalConcurrency);\n setNum('qp-kconc', values.perKeyConcurrency);\n setNum('qp-depth', values.maxQueueDepth);\n setNum('qp-depthk', values.maxQueueDepthPerKey);\n const fair = document.getElementById('qp-fair');\n if (fair) fair.value = values.fairness || 'weighted_round_robin';\n setNum('qp-pri', values.defaultPriority);\n setNum('qp-ppri', values.playgroundPriority);\n setNum('qp-lease', values.leaseMs);\n setNum('qp-wait', values.maxWaitMs);\n updateQueuePresetUI();\n}\n\nfunction updateQueuePresetUI() {\n if (!document.getElementById('queue-policy-panel')) return;\n let formPol;\n try {\n formPol = readQueuePolicyForm();\n } catch {\n return;\n }\n const formMatch = matchQueuePreset(formPol);\n const savedMatch = matchQueuePreset(state._queuePolicyCache || formPol);\n const unsaved = !queuePoliciesEqual(\n formPol,\n state._queuePolicyCache || formPol,\n );\n\n document.querySelectorAll('[data-queue-preset]').forEach((btn) => {\n const name = btn.dataset.queuePreset;\n if (name === 'custom') {\n const isCustom = formMatch === 'custom';\n btn.classList.toggle('is-active', isCustom);\n btn.setAttribute('aria-pressed', isCustom ? 'true' : 'false');\n btn.disabled = !isCustom;\n return;\n }\n const isForm = name === formMatch;\n const isSaved = name === savedMatch;\n btn.classList.toggle('is-active', isForm);\n btn.classList.toggle('is-saved', isSaved && !isForm);\n btn.setAttribute('aria-pressed', isForm ? 'true' : 'false');\n const base =\n name === 'relaxed'\n ? t('queue.presetRelaxed')\n : name === 'balanced'\n ? t('queue.presetBalanced')\n : t('queue.presetStrict');\n if (isForm && isSaved) {\n btn.innerHTML = `${escapeHtml(base)} <span class=\"preset-tag\">${escapeHtml(t('queue.presetTagActive'))}</span>`;\n } else if (isForm && unsaved) {\n btn.innerHTML = `${escapeHtml(base)} <span class=\"preset-tag preset-tag--draft\">${escapeHtml(t('queue.presetTagDraft'))}</span>`;\n } else if (isSaved) {\n btn.innerHTML = `${escapeHtml(base)} <span class=\"preset-tag preset-tag--saved\">${escapeHtml(t('queue.presetTagSaved'))}</span>`;\n } else {\n btn.textContent = base;\n }\n });\n\n const badgeHost = document.getElementById('queue-preset-badge');\n if (badgeHost) {\n badgeHost.outerHTML = queuePresetBadgeHtml(formMatch, {\n unsaved: unsaved && formMatch !== savedMatch,\n });\n }\n\n const hint = document.getElementById('queue-preset-hint');\n if (hint) {\n const hints = {\n relaxed: t('queue.presetRelaxedHint'),\n balanced: t('queue.presetBalancedHint'),\n strict: t('queue.presetStrictHint'),\n custom: t('queue.presetCustomHint'),\n };\n hint.textContent = hints[formMatch] || hints.custom;\n }\n}\n\nfunction bindQueuePresetControls() {\n document.querySelectorAll('[data-queue-preset]').forEach((btn) => {\n if (btn.dataset.queuePreset === 'custom') return;\n btn.onclick = () => {\n const name = btn.dataset.queuePreset;\n const preset = queuePolicyPresets()[name];\n if (!preset) return;\n applyQueuePresetToForm(preset);\n };\n });\n [\n 'qp-gconc',\n 'qp-kconc',\n 'qp-depth',\n 'qp-depthk',\n 'qp-fair',\n 'qp-pri',\n 'qp-ppri',\n 'qp-lease',\n 'qp-wait',\n ].forEach((id) => {\n const el = document.getElementById(id);\n if (!el) return;\n el.addEventListener('change', () => updateQueuePresetUI());\n el.addEventListener('input', () => updateQueuePresetUI());\n });\n updateQueuePresetUI();\n}\n\nfunction queueMainScrollEl() {\n return document.querySelector('.main');\n}\n\nfunction queueJobRowsHtml(jobs) {\n return jobs\n .map((j) => {\n const activeJob =\n j.status === 'queued' || j.status === 'leased' || j.status === 'running';\n const requeueable =\n j.status === 'failed' || j.status === 'dead' || j.status === 'cancelled';\n const waitMs =\n j.startedAt || j.finishedAt\n ? null\n : j.queuedAt\n ? Date.now() - new Date(j.queuedAt).getTime()\n : null;\n return `\n <tr data-q-row=\"${escapeHtml(j.id)}\">\n <td>\n <div class=\"cell-primary mono\" title=\"${escapeHtml(j.id || '')}\">${escapeHtml((j.id || '').slice(0, 10))}…</div>\n <div class=\"cell-sub mono\" title=\"${escapeHtml(j.requestId || '')}\">${escapeHtml((j.requestId || '').slice(0, 18))}${(j.requestId || '').length > 18 ? '…' : ''}</div>\n ${\n j.errorMessage\n ? `<div class=\"queue-job-err\" title=\"${escapeHtml(j.errorMessage)}\">${escapeHtml(String(j.errorMessage).slice(0, 80))}</div>`\n : ''\n }\n </td>\n <td>${badgeQueueSource(j.source)}</td>\n <td>\n ${badgeQueueStatus(j.status)}\n ${j.cancelRequested ? `<div class=\"cell-sub\">${escapeHtml(t('queue.cancelReq'))}</div>` : ''}\n </td>\n <td class=\"mono\" title=\"${escapeHtml(j.model || '')}\">${escapeHtml(j.model || '—')}</td>\n <td><span class=\"queue-pri\">${j.priority ?? '—'}</span></td>\n <td>\n <div class=\"cell-primary mono\" title=\"${escapeHtml(j.apiKeyId || '')}\">${escapeHtml((j.apiKeyId || '').slice(0, 8))}…</div>\n </td>\n <td class=\"mono\">${j.attempt ?? 0}<span class=\"muted\">/${j.maxAttempts ?? 1}</span></td>\n <td>\n <div class=\"cell-primary\">${fmtTime(j.queuedAt)}</div>\n ${\n waitMs != null && j.status === 'queued'\n ? `<div class=\"cell-sub\" data-q-wait>${escapeHtml(t('queue.wait'))}: ${fmtQueueAge(waitMs)}</div>`\n : j.startedAt\n ? `<div class=\"cell-sub\">${escapeHtml(t('queue.started'))}: ${fmtTime(j.startedAt)}</div>`\n : ''\n }\n </td>\n <td>\n <div class=\"row-actions\">\n ${\n activeJob\n ? `<button type=\"button\" class=\"btn danger sm\" data-q-cancel=\"${escapeHtml(j.id)}\">${escapeHtml(t('queue.cancel'))}</button>`\n : ''\n }\n ${\n j.status === 'queued'\n ? `<button type=\"button\" class=\"btn secondary sm\" data-q-pri=\"${escapeHtml(j.id)}\" data-pri=\"${j.priority}\">${escapeHtml(t('queue.priorityBtn'))}</button>`\n : ''\n }\n ${\n requeueable\n ? `<button type=\"button\" class=\"btn secondary sm\" data-q-requeue=\"${escapeHtml(j.id)}\">${escapeHtml(t('queue.requeue'))}</button>`\n : ''\n }\n </div>\n </td>\n </tr>`;\n })\n .join('');\n}\n\nfunction bindQueueRowActions() {\n document.querySelectorAll('[data-q-cancel]').forEach((b) => {\n b.onclick = async () => {\n if (\n !(await uiConfirm({\n title: t('queue.cancel'),\n message: t('queue.cancelConfirm'),\n variant: 'danger',\n confirmText: t('queue.cancel'),\n }))\n )\n return;\n await api(`/queue/jobs/${b.dataset.qCancel}/cancel`, {\n method: 'POST',\n body: '{}',\n });\n renderQueue().catch(onErr);\n };\n });\n document.querySelectorAll('[data-q-requeue]').forEach((b) => {\n b.onclick = async () => {\n await api(`/queue/jobs/${b.dataset.qRequeue}/requeue`, {\n method: 'POST',\n body: '{}',\n });\n renderQueue().catch(onErr);\n };\n });\n document.querySelectorAll('[data-q-pri]').forEach((b) => {\n b.onclick = async () => {\n const cur = Number(b.dataset.pri) || 100;\n const raw = window.prompt(t('queue.priorityPh'), String(cur));\n if (raw == null) return;\n const priority = Number(raw);\n if (!Number.isFinite(priority) || priority < 0 || priority > 1000) return;\n await api(`/queue/jobs/${b.dataset.qPri}/priority`, {\n method: 'POST',\n body: JSON.stringify({ priority }),\n });\n renderQueue().catch(onErr);\n };\n });\n}\n\nfunction queueModeLabel(pol) {\n if (!pol.enabled) return t('queue.modeOff');\n if (pol.paused) return t('queue.paused');\n if (pol.drainMode) return t('queue.drain');\n return t('queue.running');\n}\n\n/** Soft live-update: KPIs + job table only (keeps scroll / form focus). */\nfunction applyQueueSoftUpdate({ s, pol, jobs, total, by }) {\n const deadCount = s.dead ?? by.dead ?? 0;\n const leased = s.leased ?? by.leased ?? 0;\n const running = s.running ?? by.running ?? 0;\n const queued = s.queued ?? by.queued ?? 0;\n const depth = s.depth ?? queued + leased + running;\n const modeLabel = queueModeLabel(pol);\n const fairnessLabel =\n pol.fairness === 'fifo_global' ? t('queue.fifo') : t('queue.wrr');\n\n const setText = (id, text) => {\n const el = document.getElementById(id);\n if (el) el.textContent = text;\n };\n const setHtml = (id, html) => {\n const el = document.getElementById(id);\n if (el) el.innerHTML = html;\n };\n\n setText('qk-depth', String(depth));\n setText('qk-depth-sub', tf('queue.kpiDepthSub', { q: queued, l: leased }));\n setHtml(\n 'qk-running',\n `${running}<span class=\"dash-kpi-den\">/${pol.globalConcurrency ?? '—'}</span>`,\n );\n setText('qk-running-sub', tf('queue.kpiActiveSub', { n: s.workerActive ?? 0 }));\n setText('qk-queued', String(queued));\n setText('qk-dead', String(deadCount));\n setText(\n 'qk-oldest',\n s.oldestQueuedAgeMs ? fmtQueueAge(s.oldestQueuedAgeMs) : '—',\n );\n setText('qk-mode', modeLabel);\n setText('qk-mode-sub', fairnessLabel);\n\n const workerEl = document.getElementById('qk-worker-id');\n if (workerEl) {\n const wid = s.workerId || '—';\n workerEl.textContent = wid;\n workerEl.title = wid;\n }\n\n const setPill = (id, ok, okText, badText) => {\n const el = document.getElementById(id);\n if (!el) return;\n el.outerHTML = `<span id=\"${id}\">${dashStatusPill(ok, okText, badText)}</span>`;\n };\n setPill(\n 'qk-pill-enabled',\n pol.enabled !== false,\n t('dash.on'),\n t('dash.off'),\n );\n setPill(\n 'qk-pill-consumer',\n !pol.paused && pol.enabled !== false,\n t('queue.running'),\n pol.paused ? t('queue.paused') : t('queue.modeOff'),\n );\n setPill(\n 'qk-pill-admission',\n !pol.drainMode,\n t('queue.accepting'),\n t('queue.drain'),\n );\n setText('qk-fairness-val', fairnessLabel);\n setText(\n 'qk-conc-val',\n `${pol.perKeyConcurrency ?? 1} / ${pol.globalConcurrency ?? '—'}`,\n );\n\n // DLQ banner show/hide\n const dlqHost = document.getElementById('queue-dlq-slot');\n if (dlqHost) {\n if (deadCount > 0) {\n dlqHost.innerHTML = `\n <div class=\"queue-dlq-banner\" role=\"status\">\n <div class=\"queue-dlq-text\">\n <strong>${escapeHtml(t('queue.dlqTitle'))}</strong>\n <span class=\"queue-dlq-count\">${deadCount}</span>\n <span class=\"muted\">${escapeHtml(t('queue.dlqHint'))}</span>\n </div>\n <div class=\"toolbar\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"q-filter-dead\">${escapeHtml(t('queue.viewDlq'))}</button>\n <button type=\"button\" class=\"btn danger sm\" id=\"q-purge-dlq\">${escapeHtml(t('queue.purgeDead'))}</button>\n </div>\n </div>`;\n document.getElementById('q-filter-dead')?.addEventListener('click', () => {\n queueFilter.status = 'dead';\n queueFilter.offset = 0;\n queueFilter.tab = 'jobs';\n renderQueue().catch(onErr);\n });\n // #q-purge-dlq handled via #queue-root click delegation (doPurge)\n } else {\n dlqHost.innerHTML = '';\n }\n }\n\n // Tab badge counts (overview KPIs live on overview; jobs badge uses list total)\n const setCount = (id, n) => {\n const el = document.getElementById(id);\n if (el) el.textContent = String(n ?? 0);\n };\n setCount('q-tab-count-jobs', total);\n setCount('q-tab-count-dead', deadCount);\n\n const meta = document.getElementById('qk-jobs-meta');\n if (meta) meta.textContent = tf('queue.jobsMeta', { n: total });\n\n const tbody = document.querySelector('#queue-jobs-table tbody');\n if (tbody) {\n // Stable soft-refresh: skip DOM rewrite when row identity unchanged (avoids column jump)\n const sig = jobs\n .map(\n (j) =>\n `${j.id}|${j.status}|${j.priority}|${j.attempt}|${j.cancelRequested ? 1 : 0}|${j.errorMessage || ''}|${j.startedAt || ''}|${j.finishedAt || ''}`,\n )\n .join(';');\n const nextBody =\n queueJobRowsHtml(jobs) ||\n `<tr class=\"empty-row\"><td colspan=\"9\">\n <div class=\"data-empty\">\n <div class=\"data-empty-icon\">∅</div>\n <strong>${escapeHtml(t('queue.empty'))}</strong>\n </div>\n </td></tr>`;\n if (tbody.dataset.qsig !== sig) {\n const wrap = document.querySelector('#queue-jobs-table .table-wrap');\n const sx = wrap?.scrollLeft || 0;\n tbody.dataset.qsig = sig;\n tbody.innerHTML = nextBody;\n bindQueueRowActions();\n enhanceResponsiveTables(document.querySelector('#queue-jobs-table') || document);\n if (wrap) wrap.scrollLeft = sx;\n } else {\n // Only refresh live wait ages in-place (no full reflow)\n jobs.forEach((j) => {\n if (j.status !== 'queued' || !j.queuedAt) return;\n const waitMs = Date.now() - new Date(j.queuedAt).getTime();\n const id = String(j.id || '');\n let row = null;\n tbody.querySelectorAll('[data-q-row]').forEach((el) => {\n if (el.getAttribute('data-q-row') === id) row = el;\n });\n const waitEl = row?.querySelector('[data-q-wait]');\n if (waitEl) {\n waitEl.textContent = `${t('queue.wait')}: ${fmtQueueAge(waitMs)}`;\n }\n });\n }\n }\n\n // Pager meta only (avoid rebuilding selects and resetting focus)\n const pagerTotal = document.querySelector('#queue-pager .data-pager-meta span');\n if (pagerTotal) {\n const pages = Math.max(1, Math.ceil((total || 0) / queueFilter.limit) || 1);\n const page = Math.floor(queueFilter.offset / queueFilter.limit) + 1;\n const spans = document.querySelectorAll('#queue-pager .data-pager-meta > span');\n if (spans[0]) spans[0].textContent = tf('common.pagerTotal', { n: total || 0 });\n if (spans[1])\n spans[1].textContent = tf('common.pagerPage', { n: page, total: pages });\n const prev = document.getElementById('queue-prev');\n const next = document.getElementById('queue-next');\n if (prev) prev.disabled = queueFilter.offset <= 0;\n if (next) next.disabled = queueFilter.offset + queueFilter.limit >= total;\n }\n\n // Toolbar button labels (pause / drain may have changed externally)\n const pauseBtn = document.getElementById('q-pause');\n if (pauseBtn)\n pauseBtn.textContent = pol.paused ? t('queue.resume') : t('queue.pause');\n const drainBtn = document.getElementById('q-drain');\n if (drainBtn)\n drainBtn.textContent = pol.drainMode ? t('queue.undrain') : t('queue.drainBtn');\n\n // Master enable switch (don't fight user mid-click — only sync when not focused)\n const master = document.getElementById('q-master-enabled');\n if (master && document.activeElement !== master) {\n applyQueueEnabledUi(pol.enabled !== false);\n }\n}\n\nfunction ensureQueueAutoRefresh() {\n if (queueTimer) return;\n queueTimer = setInterval(() => {\n if (state.page !== 'queue') {\n clearInterval(queueTimer);\n queueTimer = null;\n return;\n }\n const el = document.activeElement;\n if (\n el &&\n el.closest &&\n el.closest('#queue-policy-panel') &&\n (el.tagName === 'INPUT' || el.tagName === 'SELECT' || el.tagName === 'TEXTAREA')\n ) {\n return;\n }\n // Soft refresh: no full shell rebuild → scroll stays put\n renderQueue({ soft: true }).catch(() => {});\n }, 4000);\n}\n\nasync function renderQueue(opts = {}) {\n const soft = Boolean(opts.soft) && document.getElementById('queue-root');\n\n if (!soft && queueTimer) {\n clearInterval(queueTimer);\n queueTimer = null;\n }\n\n // Preserve scroll across full re-renders (filter / save / manual refresh)\n const scrollEl = queueMainScrollEl();\n const savedScroll = !soft && scrollEl ? scrollEl.scrollTop : 0;\n\n const f = queueFilter;\n if (!f.sortBy) f.sortBy = 'queuedAt';\n if (!f.sortDir) f.sortDir = 'desc';\n const q = new URLSearchParams();\n q.set('limit', String(f.limit));\n q.set('offset', String(f.offset));\n if (f.status) q.set('status', f.status);\n appendSortParams(q, f);\n\n const [statsRes, jobsRes, policyRes] = await Promise.all([\n api('/queue/stats'),\n api(`/queue/jobs?${q}`),\n api('/queue/policy'),\n ]);\n // Page may have changed during fetch\n if (state.page !== 'queue') return;\n\n const s = statsRes.data || {};\n const pol = policyRes.data || s.policy || {};\n const jobs = jobsRes.data || [];\n const total = jobsRes.total ?? jobs.length;\n const by = s.byStatus || {};\n const deadCount = s.dead ?? by.dead ?? 0;\n const leased = s.leased ?? by.leased ?? 0;\n const running = s.running ?? by.running ?? 0;\n const queued = s.queued ?? by.queued ?? 0;\n const depth = s.depth ?? queued + leased + running;\n const modeLabel = queueModeLabel(pol);\n\n // Cache saved policy for preset matching (soft + full)\n state._queuePolicyCache = { ...pol };\n\n if (soft) {\n applyQueueSoftUpdate({ s, pol, jobs, total, by });\n ensureQueueAutoRefresh();\n return;\n }\n\n if (!queueFilter.tab) queueFilter.tab = 'overview';\n const tab =\n queueFilter.tab === 'jobs' || queueFilter.tab === 'policy'\n ? queueFilter.tab\n : 'overview';\n queueFilter.tab = tab;\n\n const bodyHtml = queueJobRowsHtml(jobs);\n\n const filter = filterPanelHtml({\n title: t('queue.filterTitle'),\n hint: t('queue.filterHint'),\n meta: tf('queue.jobsMeta', { n: total }),\n gridHtml: `\n <label>${escapeHtml(t('queue.filterStatus'))}\n <select id=\"qf-status\">\n <option value=\"\">${escapeHtml(t('queue.allStatuses'))}</option>\n <option value=\"queued\" ${f.status === 'queued' ? 'selected' : ''}>${escapeHtml(t('queue.filterQueued'))}</option>\n <option value=\"active\" ${f.status === 'active' ? 'selected' : ''}>${escapeHtml(t('queue.filterRunning'))}</option>\n <option value=\"dead\" ${f.status === 'dead' ? 'selected' : ''}>${escapeHtml(t('queue.filterDead'))}</option>\n <option value=\"failed\" ${f.status === 'failed' ? 'selected' : ''}>${escapeHtml(t('queue.filterFailed'))}</option>\n <option value=\"succeeded\" ${f.status === 'succeeded' ? 'selected' : ''}>${escapeHtml(t('queue.filterSucceeded'))}</option>\n <option value=\"cancelled\" ${f.status === 'cancelled' ? 'selected' : ''}>${escapeHtml(t('queue.filterCancelled'))}</option>\n </select>\n </label>`,\n });\n\n const table = dataTablePanelHtml({\n headHtml: `\n <th>${escapeHtml(t('queue.colJob'))}</th>\n <th>${escapeHtml(t('queue.colSource'))}</th>\n ${sortThHtml({ field: 'status', label: t('queue.colStatus'), filterRef: f })}\n ${sortThHtml({ field: 'model', label: t('queue.colModel'), filterRef: f })}\n ${sortThHtml({ field: 'priority', label: t('queue.colPri'), filterRef: f })}\n <th>${escapeHtml(t('queue.colKey'))}</th>\n ${sortThHtml({ field: 'attempt', label: t('queue.colTry'), filterRef: f })}\n ${sortThHtml({ field: 'queuedAt', label: t('queue.colTime'), filterRef: f })}\n <th>${escapeHtml(t('common.actions'))}</th>`,\n bodyHtml,\n colSpan: 9,\n emptyText: t('queue.empty'),\n pagerHtml: pagerHtml({\n total,\n limit: f.limit,\n offset: f.offset,\n idPrefix: 'queue',\n }),\n });\n\n const fairnessLabel =\n pol.fairness === 'fifo_global' ? t('queue.fifo') : t('queue.wrr');\n\n const queueOn = pol.enabled !== false;\n\n /** Standard page KPI card (.grid > .card) — same as Usage / DDoS */\n const kpiCard = (label, valueHtml, subText, valueId, subId) => `\n <div class=\"card\">\n <div class=\"label\">${escapeHtml(label)}</div>\n <div class=\"value value-sm\" id=\"${escapeHtml(valueId)}\">${valueHtml}</div>\n ${\n subText != null && subText !== ''\n ? `<div class=\"muted card-sub\"${subId ? ` id=\"${escapeHtml(subId)}\"` : ''}>${escapeHtml(String(subText))}</div>`\n : ''\n }\n </div>`;\n\n // Always-visible KPI strip (same .grid/.card pattern as Usage & DDoS)\n const kpiGrid = `\n <div class=\"grid queue-kpi-grid\" id=\"queue-kpi-grid\">\n ${kpiCard(\n t('queue.depth'),\n escapeHtml(String(depth)),\n tf('queue.kpiDepthSub', { q: queued, l: leased }),\n 'qk-depth',\n 'qk-depth-sub',\n )}\n ${kpiCard(\n t('queue.activeJobs'),\n `${running}<span class=\"dash-kpi-den\">/${pol.globalConcurrency ?? '—'}</span>`,\n tf('queue.kpiActiveSub', { n: s.workerActive ?? 0 }),\n 'qk-running',\n 'qk-running-sub',\n )}\n ${kpiCard(\n t('queue.queued'),\n escapeHtml(String(queued)),\n t('queue.kpiQueuedSub'),\n 'qk-queued',\n 'qk-queued-sub',\n )}\n ${kpiCard(\n t('queue.dead'),\n escapeHtml(String(deadCount)),\n t('queue.kpiDeadSub'),\n 'qk-dead',\n 'qk-dead-sub',\n )}\n ${kpiCard(\n t('queue.oldest'),\n escapeHtml(s.oldestQueuedAgeMs ? fmtQueueAge(s.oldestQueuedAgeMs) : '—'),\n t('queue.kpiOldestSub'),\n 'qk-oldest',\n 'qk-oldest-sub',\n )}\n ${kpiCard(\n t('queue.mode'),\n escapeHtml(modeLabel),\n fairnessLabel,\n 'qk-mode',\n 'qk-mode-sub',\n )}\n </div>`;\n\n const overviewPane = `\n <div class=\"panel data-table-panel queue-status-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('queue.statusPanel'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('queue.statusPanelHint'))}</span>\n </div>\n </div>\n <div class=\"panel-pad\">\n <div class=\"queue-status-row queue-status-row--6\">\n <div class=\"queue-status-item\">\n <span class=\"label\">${escapeHtml(t('queue.enabled'))}</span>\n <span id=\"qk-pill-enabled\">${dashStatusPill(pol.enabled !== false, t('dash.on'), t('dash.off'))}</span>\n </div>\n <div class=\"queue-status-item\">\n <span class=\"label\">${escapeHtml(t('queue.consumer'))}</span>\n <span id=\"qk-pill-consumer\">${dashStatusPill(!pol.paused && pol.enabled !== false, t('queue.running'), pol.paused ? t('queue.paused') : t('queue.modeOff'))}</span>\n </div>\n <div class=\"queue-status-item\">\n <span class=\"label\">${escapeHtml(t('queue.admission'))}</span>\n <span id=\"qk-pill-admission\">${dashStatusPill(!pol.drainMode, t('queue.accepting'), t('queue.drain'))}</span>\n </div>\n <div class=\"queue-status-item\">\n <span class=\"label\">${escapeHtml(t('queue.fairness'))}</span>\n <strong class=\"queue-status-val\" id=\"qk-fairness-val\">${escapeHtml(fairnessLabel)}</strong>\n </div>\n <div class=\"queue-status-item\">\n <span class=\"label\">${escapeHtml(t('queue.concurrency'))}</span>\n <strong class=\"queue-status-val mono\" id=\"qk-conc-val\">${pol.perKeyConcurrency ?? 1} / ${pol.globalConcurrency ?? '—'}</strong>\n </div>\n <div class=\"queue-status-item queue-status-item--worker\">\n <span class=\"label\">${escapeHtml(t('queue.workerInstance'))}</span>\n <code class=\"queue-worker-id\" id=\"qk-worker-id\" title=\"${escapeHtml(s.workerId || '')}\">${escapeHtml(s.workerId || '—')}</code>\n <span class=\"queue-worker-hint muted\">${escapeHtml(t('queue.workerInstanceHint'))}</span>\n </div>\n </div>\n </div>\n </div>\n\n <div id=\"queue-dlq-slot\">\n ${\n deadCount > 0\n ? `<div class=\"queue-dlq-banner\" role=\"status\">\n <div class=\"queue-dlq-text\">\n <strong>${escapeHtml(t('queue.dlqTitle'))}</strong>\n <span class=\"queue-dlq-count\">${deadCount}</span>\n <span class=\"muted\">${escapeHtml(t('queue.dlqHint'))}</span>\n </div>\n <div class=\"toolbar\">\n <button type=\"button\" class=\"btn secondary sm\" id=\"q-filter-dead\">${escapeHtml(t('queue.viewDlq'))}</button>\n <button type=\"button\" class=\"btn danger sm\" id=\"q-purge-dlq\">${escapeHtml(t('queue.purgeDead'))}</button>\n </div>\n </div>`\n : ''\n }\n </div>`;\n\n const jobsPane = `\n ${filter}\n <div id=\"queue-jobs-table\" class=\"queue-jobs-table-host\">${table}</div>`;\n\n const policyPane = `\n <div class=\"panel data-table-panel queue-policy-panel\" id=\"queue-policy-panel\">\n <div class=\"panel-h\">\n <div class=\"panel-h-text\">\n <strong>${escapeHtml(t('queue.policyTitle'))}</strong>\n <span class=\"muted panel-h-sub\">${escapeHtml(t('queue.policyHint'))}</span>\n </div>\n ${queuePresetBadgeHtml(matchQueuePreset(pol))}\n </div>\n <div class=\"panel-pad\">\n <div class=\"ddos-preset-block\">\n <div class=\"ddos-preset-block-h\">\n <strong>${escapeHtml(t('queue.presetTitle'))}</strong>\n <span class=\"muted\">${escapeHtml(t('queue.presetHint'))}</span>\n </div>\n <div class=\"ddos-presets\" role=\"group\" aria-label=\"${escapeHtml(t('queue.presetTitle'))}\">\n <button type=\"button\" class=\"ddos-preset-btn\" data-queue-preset=\"relaxed\" data-ddos-preset=\"relaxed\" aria-pressed=\"false\">${escapeHtml(t('queue.presetRelaxed'))}</button>\n <button type=\"button\" class=\"ddos-preset-btn\" data-queue-preset=\"balanced\" data-ddos-preset=\"balanced\" aria-pressed=\"false\">${escapeHtml(t('queue.presetBalanced'))}</button>\n <button type=\"button\" class=\"ddos-preset-btn\" data-queue-preset=\"strict\" data-ddos-preset=\"strict\" aria-pressed=\"false\">${escapeHtml(t('queue.presetStrict'))}</button>\n <button type=\"button\" class=\"ddos-preset-btn ddos-preset-btn--custom\" data-queue-preset=\"custom\" disabled aria-pressed=\"false\">${escapeHtml(t('queue.presetCustom'))}</button>\n </div>\n <p class=\"ddos-preset-hint\" id=\"queue-preset-hint\"></p>\n </div>\n <div class=\"form-grid\">\n <label>${escapeHtml(t('queue.globalConcurrency'))}\n <input type=\"number\" id=\"qp-gconc\" min=\"1\" max=\"64\" value=\"${Number(pol.globalConcurrency) || 2}\" />\n <span class=\"hint\">${escapeHtml(t('queue.hintGlobalConc'))}</span>\n </label>\n <label>${escapeHtml(t('queue.perKeyConcurrency'))}\n <input type=\"number\" id=\"qp-kconc\" min=\"1\" max=\"16\" value=\"${Number(pol.perKeyConcurrency) || 1}\" />\n <span class=\"hint\">${escapeHtml(t('queue.hintPerKeyConc'))}</span>\n </label>\n <label>${escapeHtml(t('queue.maxDepth'))}\n <input type=\"number\" id=\"qp-depth\" min=\"1\" value=\"${Number(pol.maxQueueDepth) || 100}\" />\n <span class=\"hint\">${escapeHtml(t('queue.hintMaxDepth'))}</span>\n </label>\n <label>${escapeHtml(t('queue.maxDepthKey'))}\n <input type=\"number\" id=\"qp-depthk\" min=\"1\" value=\"${Number(pol.maxQueueDepthPerKey) || 20}\" />\n <span class=\"hint\">${escapeHtml(t('queue.hintMaxDepthKey'))}</span>\n </label>\n <label>${escapeHtml(t('queue.fairness'))}\n <select id=\"qp-fair\">\n <option value=\"weighted_round_robin\" ${pol.fairness === 'weighted_round_robin' ? 'selected' : ''}>${escapeHtml(t('queue.wrr'))}</option>\n <option value=\"fifo_global\" ${pol.fairness === 'fifo_global' ? 'selected' : ''}>${escapeHtml(t('queue.fifo'))}</option>\n </select>\n <span class=\"hint\">${escapeHtml(t('queue.hintFairness'))}</span>\n </label>\n <label>${escapeHtml(t('queue.defaultPriority'))}\n <input type=\"number\" id=\"qp-pri\" min=\"0\" max=\"1000\" value=\"${Number(pol.defaultPriority) || 100}\" />\n </label>\n <label>${escapeHtml(t('queue.playgroundPriority'))}\n <input type=\"number\" id=\"qp-ppri\" min=\"0\" max=\"1000\" value=\"${Number(pol.playgroundPriority) || 50}\" />\n </label>\n <label>${escapeHtml(t('queue.leaseMs'))}\n <input type=\"number\" id=\"qp-lease\" min=\"5000\" step=\"1000\" value=\"${Number(pol.leaseMs) || 45000}\" />\n <span class=\"hint\">${escapeHtml(t('queue.hintLease'))}</span>\n </label>\n <label>${escapeHtml(t('queue.maxWaitMs'))}\n <input type=\"number\" id=\"qp-wait\" min=\"5000\" step=\"1000\" value=\"${Number(pol.maxWaitMs) || 600000}\" />\n <span class=\"hint\">${escapeHtml(t('queue.hintMaxWait'))}</span>\n </label>\n </div>\n <div class=\"toolbar settings-save-bar\">\n <button type=\"button\" class=\"btn sm\" id=\"qp-save\">${escapeHtml(t('queue.savePolicy'))}</button>\n </div>\n </div>\n </div>`;\n\n document.getElementById('app').innerHTML = shell(`\n <div id=\"queue-root\" class=\"${queueOn ? '' : 'is-feature-off'}\">\n <div class=\"topbar\">\n <h2>${escapeHtml(t('queue.title'))}</h2>\n <div class=\"toolbar\">\n ${masterToggleBtnHtml({\n id: 'q-master-enabled',\n on: queueOn,\n onLabel: t('queue.masterOn'),\n offLabel: t('queue.masterOff'),\n title: t('queue.masterHint'),\n })}\n <button type=\"button\" class=\"btn secondary sm\" id=\"q-pause\">${escapeHtml(pol.paused ? t('queue.resume') : t('queue.pause'))}</button>\n <button type=\"button\" class=\"btn secondary sm\" id=\"q-drain\">${escapeHtml(pol.drainMode ? t('queue.undrain') : t('queue.drainBtn'))}</button>\n <button type=\"button\" class=\"btn danger sm\" id=\"q-purge\">${escapeHtml(t('queue.purgeDead'))}</button>\n </div>\n </div>\n ${pageMetaHtml([t('queue.subtitle')])}\n <div class=\"feature-off-banner\" id=\"queue-disabled-banner\" ${queueOn ? 'hidden' : ''} role=\"status\">\n <strong>${escapeHtml(t('common.featureOff'))}</strong>\n <span>${escapeHtml(t('queue.disabledBanner'))}</span>\n </div>\n\n ${kpiGrid}\n\n <div class=\"usage-tabs-panel panel queue-tabs-panel\">\n <div class=\"seg-tabs\" role=\"tablist\" aria-label=\"${escapeHtml(t('queue.title'))}\">\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'overview' ? 'is-active' : ''}\" data-queue-tab=\"overview\" aria-selected=\"${tab === 'overview'}\">\n ${escapeHtml(t('queue.tabOverview'))}\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'jobs' ? 'is-active' : ''}\" data-queue-tab=\"jobs\" aria-selected=\"${tab === 'jobs'}\">\n ${escapeHtml(t('queue.tabJobs'))}\n <span class=\"seg-tab-count\" id=\"q-tab-count-jobs\">${total}</span>\n </button>\n <button type=\"button\" role=\"tab\" class=\"seg-tab ${tab === 'policy' ? 'is-active' : ''}\" data-queue-tab=\"policy\" aria-selected=\"${tab === 'policy'}\">\n ${escapeHtml(t('queue.tabPolicy'))}\n </button>\n </div>\n <div class=\"usage-tab-body\">\n <div class=\"usage-tab-pane queue-tab-pane-overview\" id=\"queue-tab-overview\" ${tab === 'overview' ? '' : 'hidden'}>\n ${overviewPane}\n </div>\n <div class=\"usage-tab-pane queue-tab-pane-jobs\" id=\"queue-tab-jobs\" ${tab === 'jobs' ? '' : 'hidden'}>\n ${jobsPane}\n </div>\n <div class=\"usage-tab-pane queue-tab-pane-policy\" id=\"queue-tab-policy\" ${tab === 'policy' ? '' : 'hidden'}>\n ${policyPane}\n </div>\n </div>\n </div>\n </div>\n `);\n bindShell();\n\n document.querySelectorAll('[data-queue-tab]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const next = btn.getAttribute('data-queue-tab') || 'overview';\n if (next !== 'overview' && next !== 'jobs' && next !== 'policy') return;\n if (queueFilter.tab === next) return;\n queueFilter.tab = next;\n if (next === 'jobs') {\n /* keep filters */\n } else {\n /* policy/overview: no offset change */\n }\n renderQueue().catch(onErr);\n });\n });\n\n // Restore scroll after full rebuild (filter / save / navigation)\n if (savedScroll > 0) {\n const main = queueMainScrollEl();\n if (main) {\n main.scrollTop = savedScroll;\n requestAnimationFrame(() => {\n main.scrollTop = savedScroll;\n });\n }\n }\n\n document.getElementById('q-master-enabled').onclick = async () => {\n const next = !isMasterToggleOn('q-master-enabled');\n applyQueueEnabledUi(next);\n try {\n const res = await api('/queue/policy', {\n method: 'PUT',\n body: JSON.stringify({ enabled: next }),\n });\n state._queuePolicyCache = {\n ...(state._queuePolicyCache || {}),\n ...(res.data || { enabled: next }),\n };\n updateQueuePresetUI();\n } catch (e) {\n applyQueueEnabledUi(!next);\n onErr(e);\n }\n };\n\n document.getElementById('q-pause').onclick = async () => {\n await api(pol.paused ? '/queue/resume' : '/queue/pause', {\n method: 'POST',\n body: '{}',\n });\n renderQueue().catch(onErr);\n };\n document.getElementById('q-drain').onclick = async () => {\n await api(pol.drainMode ? '/queue/undrain' : '/queue/drain', {\n method: 'POST',\n body: '{}',\n });\n renderQueue().catch(onErr);\n };\n let purgeBusy = false;\n const doPurge = async () => {\n if (purgeBusy) return;\n purgeBusy = true;\n try {\n const ok = await uiConfirm({\n title: t('queue.purgeTitle'),\n message: t('queue.purgeConfirm'),\n variant: 'danger',\n confirmText: t('queue.purgeConfirmBtn'),\n cancelText: t('common.cancel'),\n });\n if (!ok) return;\n const res = await api('/queue/purge-dead', {\n method: 'POST',\n body: '{}',\n });\n const n = Number(res?.data?.deleted ?? 0);\n await uiAlert({\n title: t('queue.purgeDoneTitle'),\n message: tf('queue.purgeDoneMsg', { n }),\n confirmText: t('common.ok'),\n });\n await renderQueue();\n } finally {\n purgeBusy = false;\n }\n };\n // Event delegation: soft-refresh rebuilds #q-purge-dlq; onclick rebinds each full render\n const queueRoot = document.getElementById('queue-root');\n if (queueRoot) {\n queueRoot.onclick = (e) => {\n const btn = e.target?.closest?.('#q-purge, #q-purge-dlq');\n if (!btn) return;\n e.preventDefault();\n doPurge().catch(onErr);\n };\n }\n document.getElementById('q-filter-dead')?.addEventListener('click', () => {\n queueFilter.status = 'dead';\n queueFilter.offset = 0;\n queueFilter.tab = 'jobs';\n renderQueue().catch(onErr);\n });\n\n document.querySelectorAll('[data-filter-apply]').forEach((btn) => {\n btn.onclick = () => {\n queueFilter.status = document.getElementById('qf-status')?.value || '';\n queueFilter.offset = 0;\n renderQueue().catch(onErr);\n };\n });\n document.querySelectorAll('[data-filter-reset]').forEach((btn) => {\n btn.onclick = () => {\n queueFilter.status = '';\n queueFilter.sortBy = 'queuedAt';\n queueFilter.sortDir = 'desc';\n queueFilter.offset = 0;\n renderQueue().catch(onErr);\n };\n });\n\n bindPager('queue', queueFilter, () => renderQueue().catch(onErr));\n bindSortHeaders(queueFilter, () => renderQueue().catch(onErr));\n\n document.getElementById('qp-save').onclick = async () => {\n const body = readQueuePolicyForm();\n await api('/queue/policy', { method: 'PUT', body: JSON.stringify(body) });\n state._queuePolicyCache = { ...(state._queuePolicyCache || {}), ...body };\n showError('');\n renderQueue().catch(onErr);\n };\n\n bindQueuePresetControls();\n bindQueueRowActions();\n ensureQueueAutoRefresh();\n}\n\n// Boot Admin SPA (must run after all function declarations)\n// Hash routing: refresh / share keeps page; Back/Forward works.\nstate.page = readInitialPage();\nif (!location.hash || location.hash === '#' || location.hash === '#/') {\n writePageHash(state.page);\n}\nwindow.addEventListener('hashchange', () => {\n const p = hashToPage(location.hash);\n if (!p) return;\n if (p === state.page) return;\n // popstate/hash from browser — do not push again\n applyPageChange(p, { writeHash: false });\n});\nwindow.addEventListener('popstate', () => {\n const p = hashToPage(location.hash);\n if (!p || p === state.page) return;\n applyPageChange(p, { writeHash: false });\n});\nrender();\n"],"names":["LANG_KEY","dict","detectLocale","saved","locale","getLocale","setLocale","next","t","path","parts","cur","p","q","hasT","tf","vars","s","k","v","langSwitchHtml","CHAT_ALLOWED_EXTENSIONS","CHAT_FILE_ACCEPT","API","KEY_STORAGE","ddosTimer","ddosPaused","formatApiError","data","statusText","err","code","details","feature","reason","rawMsg","key","fp","fingerprintFeature","fpEarly","msg","m","state","PAGE_FROM_HASH","pageToHash","page","hashToPage","hash","raw","writePageHash","h","readInitialPage","fromHash","api","options","headers","res","text","logout","e","parseApiResponse","clear","token","render","setPage","applyPageChange","opts","escapeHtml","uiDialogRoot","uiDialogResolve","closeUiDialog","result","resolve","onUiDialogKeydown","cancelable","openUiDialog","variant","showCancel","isPrompt","title","confirmText","cancelText","icon","root","okBtn","cancelBtn","input","finish","ok","val","uiAlert","uiConfirm","ensureMarkedConfigured","formatChatMarkdown","src","markedApi","purify","html","copyTextToClipboard","value","ta","fmtTime","iso","fmtBytes","n","fmtMs","ms","fmtPerMin","showError","box","badgeStatus","c","label","badgeQueueStatus","badgeQueueSource","badgeMode","mode","badgeRole","r","role","isImageMime","mediaPreviewKind","mime","filename","ext","isBrowserPreviewable","mediaPreviewObjectUrl","revokeMediaPreviewUrl","mediaLightboxStageHtml","kind","url","openMediaPreviewLightbox","meta","blob","subParts","subtitle","promptHtml","openAppModal","modal","stage","close","el","closeAppModal","a","max","clipped","poweredByFooter","pageTitle","closeNav","openNav","shell","content","nav","id","bindShell","b","logoutHandler","onErr","enhanceResponsiveTables","tableHeaderLabel","th","fromAttr","btn","table","labels","tr","td","i","kids","isActions","ensureMe","loadModels","refresh","loadKeys","pageMetaHtml","list","filterPanelHtml","hint","searchHtml","gridHtml","dataTablePanelHtml","headHtml","bodyHtml","colSpan","emptyText","pager","body","appendSortParams","params","filterRef","sortByKey","sortDirKey","by","dir","sortThHtml","field","active","aria","indicator","bindSortHeaders","reload","byKey","dirKey","pagerHtml","total","limit","offset","idPrefix","pages","canPrev","canNext","bindPager","footerHtml","size","onEsc","renderLogin","cmd","dashKpiCard","sub","tone","href","valueId","subId","toneCls","valueAttr","subAttr","inner","dashStatusPill","okText","badText","masterToggleBtnHtml","on","onLabel","offLabel","isMasterToggleOn","setMasterToggle","lab","setFeatureOffBanner","off","setFeatureRootOff","rootId","proxySourceShort","renderDashboard","d","tot","prot","rt","conc","safety","models","rate24","rateAll","genAt","queueKpiValue","queueKpiSub","queueTone","waitS","safeOn","safeKpiValue","safeKpiSub","recentTable","modelMax","modelBars","pct","ruleChip","queueDetailHtml","openChat","attachChips","docs","parseStoredPrompt","prompt","re","matches","blocks","hit","end","systemParts","bodyParts","renderChats","f","modelOpts","keyOpts","parsed","hasSys","previewBody","filter","applyFilter","attachHtml","preview","full","img","resolveDocumentImageSrc","systemHtml","openDocument","renderKeys","usageMap","u","row","reqs","util","wl","wlLabel","modelsLabel","showKeyForm","x","existing","isEdit","wlText","selectedModels","preset","cat","local","loaded","extraIds","modelBoxes","ipWhitelist","checked","extra","allowedModels","saveBtn","storageTypeLabel","type","downloadDocument","originalName","renderDocuments","storageHint","fetchDocumentBlobUrl","doc","revokeUrl","storageLine","closeAndRevoke","auditActionLabel","action","auditResourceLabel","resource","formatAuditMeta","metaJson","obj","renderAudit","actions","actionOpts","settingsPresets","readSettingsFormValues","presetMatchesForm","values","refreshSettingsPresetUi","card","applySettingsPresetToForm","tools","turns","timeout","applySettingsPreset","bar","renderSettings","catalog","guideCards","syncPresetUi","renderApiFeatures","groups","tab","flagLabel","flagHint","groupOnCount","keys","flagRowsHtml","totalKeys","g","totalOn","kpiGrid","tabButtons","tabPanes","name","renderMedia","jobParams","assetsRes","jobsRes","assets","assetsTotal","jobs","jobsTotal","agentKeys","genKeyOpts","modelList","defaultModel","genModelOpts","aspectOpts","fname","canPreview","pKind","assetsTable","jobRows","j","jobsTable","studioPane","fetchMediaBlob","mediaMode","mediaSource","paintSourceChip","chip","clearBtn","kindLabel","setMediaSource","setMediaMode","srcSec","nWrap","durWrap","voiceWrap","aspectWrap","promptWrap","submit","fmtSel","fmtWrap","o","fileEl","dropTitle","dropHint","zone","fileInput","acceptImageFile","file","acceptAudioFile","takeFiles","fileList","accept","openMediaSourceLibraryPicker","item","ev","dt","dragSig","mediaPage","dragDepth","apiKeyId","model","format","aspect","st","busyLabel","fd","voice","ids","keepTab","bytesRaw","audioOnly","imagesOnly","libTab","loadSeq","selected","listEl","qEl","addBtn","paintSelection","isImageName","isAudioMime","isAudioName","passMime","renderRows","items","it","inp","load","seq","searchTimer","renderUsage","uf","uq","limits","ps","qq","modelTotal","modelRows","keyTotal","keyRows","modelPager","keyPager","modelFilter","modelTable","keyFilter","keyTable","versionStatusMeta","status","channelLabel","channel","softwareLevelLabel","level","softwareStatusBadge","runtimeBadge","renderSystem","vs","soft","checks","softBody","softSummary","encReady","channelText","installText","softTable","softwarePane","packagePane","envPane","logEl","banSourceLabel","source","msToSec","msToMin","secToMs","sec","minToMs","min","numVal","fallback","boolVal","readDdosPolicyForm","trustedProxies","DDOS_PRESET_KEYS","normalizeDdosPolicySlice","out","ddosPoliciesEqual","matchDdosPreset","policy","presets","ddosPresetLabel","ddosPresetBadgeHtml","unsaved","updateDdosPresetUI","formPol","formMatch","savedMatch","isForm","isSaved","base","badgeHost","customBtn","applyDdosPolicyToForm","set","hid","updateDdosAutoBadge","ddosPolicyPanelHtml","check","step","presetBadge","ddosEventsRows","events","renderDdos","mainEl","savedScroll","df","connQ","banQ","evQ","fetches","results","conn","bl","evRes","policyRes","recent","bans","stats","whitelist","match","liveSlice","banSlice","liveRows","recentRows","banRows","topIps","eventRows","emptyLive","emptyRecent","emptyBan","emptyTop","sourceOpts","setText","bindDdosActions","pol","autoBanOn","policyPane","livePane","blacklistPane","eventsPane","main2","banIp","ip","onWl","w","ttl","policyPanel","runnerLabel","runner","formatPm2Message","scheduleAdminReload","seconds","buildPm2SwitchAlertMessage","keyFromApi","port","runnerBadge","envExtraToText","textToEnvExtra","line","tline","eq","readPm2ConfigForm","bool","instances","portRaw","portNum","renderPm2","app","cfg","holders","portBusy","logsText","logsMeta","lg","logFiles","logSizeLine","maxMb","keepKb","statusRaw","statusLabel","statusBadge","canStart","canControl","isWarnOnly","envExtraText","runnerPane","portPane","configPane","logsPane","doSwitch","payload","alertMsg","saveCfg","restart","portMsg","scheduledBody","chatMessages","chatAbort","chatPendingDocs","chatCompressing","chatRenderSkip","chatMdCache","chatUi","chatContext","CHAT_COMPRESS_MIN_MSGS","CHAT_RENDER_WINDOW","CHAT_RENDER_STEP","CHAT_CONTENT_COLLAPSE","chatSession","chatHistorySearchTimer","CHAT_MAX_DOCS","DOC_ID_RE","chatFileExt","isChatAllowedFilename","chatFormatsShort","resetChatContext","conversationDisplayTitle","messagesForSave","contextPayloadForSave","applyContextFromApi","chatMessageChars","msgs","chatCompressEligible","ready","buildApiMessages","systemBase","slice","system","summaryBlock","after","contextModeLabel","updateChatCompressButton","streaming","busy","paintContextBanner","syncContextControls","modeEl","nEl","optSum","paintChatSettingsBar","host","hasSummary","longThread","warn","openSummaryPopup","when","buildCompressTranscript","names","compressSystemPrompt","compressChatHistory","auth","playgroundAuthKey","captureChatUi","sendBtn","transcript","classifyPlaygroundKind","asKeyId","playgroundKeyId","realKeyId","playgroundRealApiKeyId","errText","json","summary","s2","saveConversation","setChatHistoryMobileOpen","open","closeChatHistoryMobile","loadConversationList","paintChatHistoryList","isRenaming","editValue","bodyInner","main","totalPages","pageLabel","prev","openTimer","clearOpen","openConversation","startInlineRename","deleteConversation","rid","bindTitleInput","finished","save","prevStored","sysEl","wrap","modelEl","keyEl","renderChatBubbles","renderChatPending","messages","resetChatThread","keepSystem","reasonEl","effortEl","resumeEl","forkEl","memEl","planEl","permEl","shellEl","sum","modeKey","idx","mdCacheKey","nearBottom","maxSkip","start","visible","hiddenCount","foldBar","visIdx","roleLabel","reasoning","bodyText","errCls","streamCls","useMd","ck","first","long","contentCls","moreBtn","spend","formatChatSpend","spendHtml","media","mediaHtml","toolsHtml","tc","copyBtn","hydrateChatMedia","prevH","box2","parseSseBuffer","buffer","rest","trimmed","cached","cacheBit","usd","applyStreamDelta","assistant","delta","changed","ge","args","tcs","uploadChatFile","onProgress","reject","asId","xhr","percent","setChatUploadProgress","fileName","fileIndex","fileTotal","indeterminate","pctEl","ind","addChatExistingDocs","added","skipped","pendingIds","openChatLibraryPicker","room","countEl","paintCount","allowed","already","disabled","addChatFiles","rawFiles","rejected","files","attachBtn","chatKeySelectOptions","meId","meLabel","PIPER_CHAT_ID","mod","playgroundModelLabel","tag","fetchAdminMediaBlob","nodes","pollAdminMediaJob","runPlaygroundMedia","pending","assetId","created","jobId","done","docId","allowedModelsForKeyId","keyId","filterIdsByAllowlist","allow","fillPlaygroundModelSelect","all","orderPlaygroundModels","apiModels","seen","add","renderChatPlayground","allModels","preferred","sel","ctxMode","ctxN","sendChatMessage","histToggle","histBackdrop","histClose","searchEl","bindChatPageFileDrop","overlay","composer","hasFiles","types","showOverlay","onDragEnter","onDragOver","onDragLeave","onDrop","winDragOver","winDrop","collectDocumentIdsForSend","push","mediaKind","includeReasoning","effort","docMeta","docIds","apiMessages","stopBtn","libBtn","reader","decoder","lastPaint","paint","force","now","SUPPORT_EMAIL","SUPPORT_SPONSORS","SUPPORT_LINKTREE","SUPPORT_SITE","SUPPORT_DOCS","renderSupport","walletRows","net","addr","CURATED_PACKS","catalogPackName","catalogLocalsForPack","catalogModalityLabel","catalogDefaultQuant","quants","fmtDownloads","fmtMb","assertPullRecorded","last","pathOnDisk","fmtDuration","zh","fmtSpeed","bps","catalogJobSpeed","job","samples","catalogJobEta","speed","catalogJobPct","catalogQueueHas","catalogDlDockHtml","rows","eta","barClass","detail","badge","paintCatalogQueue","tabs","enqueueCatalogPull","spec","pumpCatalogQueue","dec","lines","l","renderCatalog","catalogHubRowHtml","onDisk","isPulling","canPull","pullBtn","bindCatalogPullButtons","packId","quant","catalogHubPagerHtml","shown","hasMore","loading","loadCatalogHub","append","y","qs","hits","tbody","count","headMeta","packs","loadedIds","usedMb","budgetMb","vramPct","modality","modalities","visiblePacks","packRows","defaultQ","quantHtml","pullLabel","packEmpty","localRows","isLoaded","localEmpty","loadedNames","localTable","hubHits","hubRows","hubEmpty","hubModChips","hubSearch","hubTable","pane","tabBtn","modSel","runHubSearch","runtimeStatusBadge","runtimeSupportLabel","paintRuntimeInstallLog","pre","running","startRuntimeInstall","act","renderRuntimes","buf","consume","okKey","failKey","report","hostOs","osFilter","viewOs","os","missing","osChips","modChips","cards","note","osCells","lv","cls","mods","canInstall","canUninstall","thisJob","installLabel","uninstallLabel","logHtml","renderQueue","queueTimer","queueFilter","fmtQueueAge","QUEUE_PRESET_KEYS","queuePolicyPresets","normalizeQueuePolicySlice","queuePoliciesEqual","matchQueuePreset","queuePresetLabel","queuePresetBadgeHtml","readQueuePolicyForm","applyQueueEnabledUi","pill","applyQueuePresetToForm","setNum","fair","updateQueuePresetUI","isCustom","hints","bindQueuePresetControls","queueMainScrollEl","queueJobRowsHtml","activeJob","requeueable","waitMs","bindQueueRowActions","priority","queueModeLabel","applyQueueSoftUpdate","deadCount","leased","queued","depth","modeLabel","fairnessLabel","setHtml","workerEl","wid","setPill","dlqHost","setCount","sig","nextBody","sx","waitEl","spans","pauseBtn","drainBtn","master","ensureQueueAutoRefresh","scrollEl","statsRes","queueOn","kpiCard","valueHtml","subText","overviewPane","jobsPane","purgeBusy","doPurge","queueRoot"],"mappings":"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qB,0CACrB,WAAY,kDACZ,eAAgB,wCAChB,mBAAoB,6CACpB,gBAAiB,8BACjB,oBAAqB,sDACrB,2BAA4B,uCAC5B,wBAAyB,2BACzB,gBACE,+FACF,iBAAkB,gCAClB,QAAS,CACP,UACE,6EACF,SACE,4EACF,SACE,2EACF,MACE,+FACF,iBACE,6FACV,EACM,MAAO,CACL,wBACE,8GACF,gBACE,qEACF,qBACE,qEACF,oBACE,gGACF,oBACE,mDACF,iBAAkB,0DAC1B,CACA,CACA,EACE,UAAW,CACT,MAAO,WACP,SAAU,OACV,WAAY,QACZ,WAAY,SACZ,cAAe,SACf,SAAU,KACV,aAAc,aACd,aAAc,iBACd,eAAgB,uBAChB,aAAc,YACd,aAAc,+BACd,UAAW,KACX,YAAa,MACb,QAAS,aACT,QAAS,kBACT,OAAQ,KACR,MAAO,CACL,KAAM,OACN,UAAW,MACjB,EACI,IAAK,CACH,UAAW,MACX,KAAM,KACN,MAAO,OACP,KAAM,SACN,UAAW,KACX,MAAO,MACP,QAAS,KACT,SAAU,OACV,MAAO,OACP,SAAU,OACV,YAAa,SACb,MAAO,QACP,KAAM,UACN,MAAO,KACP,IAAK,MACL,OAAQ,OACR,QAAS,IACf,EACI,MAAO,CACL,MAAO,OACP,SAAU,oBACV,OAAQ,MACR,QAAS,MACT,MAAO,OACP,KAAM,KACN,QAAS,MACT,MAAO,OACP,OAAQ,MACR,OAAQ,MACR,WAAY,MACZ,KAAM,KACN,OAAQ,OACR,YAAa,aACb,OAAQ,aACR,eAAgB,YAChB,mBAAoB,2BACpB,aAAc,eACd,SAAU,MACV,UAAW,KACX,UAAW,OACX,MAAO,OACP,OAAQ,OACR,SAAU,KACV,QAAS,OACT,WAAY,OACZ,QAAS,OACT,KAAM,OACN,YAAa,KACb,QAAS,OACT,UAAW,KACX,SAAU,UACV,OAAQ,KACR,QAAS,OACT,UAAW,WACX,WAAY,UACZ,aACE,2CACF,gBAAiB,OACjB,eAAgB,OAChB,aAAc,eACd,cAAe,mCACf,MAAO,YACP,QAAS,OACT,SAAU,OACV,UAAW,OACX,WAAY,gBACZ,eACE,mCACF,kBAAmB,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"}