@xopcai/xopcbot 0.1.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 (535) hide show
  1. package/README.md +132 -0
  2. package/README.zh-CN.md +130 -0
  3. package/dist/__tests__/core.test.d.ts +1 -0
  4. package/dist/__tests__/core.test.js +72 -0
  5. package/dist/__tests__/core.test.js.map +1 -0
  6. package/dist/agent/fallback/__tests__/index.test.d.ts +1 -0
  7. package/dist/agent/fallback/__tests__/index.test.js +111 -0
  8. package/dist/agent/fallback/__tests__/index.test.js.map +1 -0
  9. package/dist/agent/fallback/candidates.d.ts +23 -0
  10. package/dist/agent/fallback/candidates.js +62 -0
  11. package/dist/agent/fallback/candidates.js.map +1 -0
  12. package/dist/agent/fallback/error.d.ts +22 -0
  13. package/dist/agent/fallback/error.js +27 -0
  14. package/dist/agent/fallback/error.js.map +1 -0
  15. package/dist/agent/fallback/index.d.ts +6 -0
  16. package/dist/agent/fallback/index.js +5 -0
  17. package/dist/agent/fallback/index.js.map +1 -0
  18. package/dist/agent/fallback/reason.d.ts +7 -0
  19. package/dist/agent/fallback/reason.js +78 -0
  20. package/dist/agent/fallback/reason.js.map +1 -0
  21. package/dist/agent/fallback/runner.d.ts +22 -0
  22. package/dist/agent/fallback/runner.js +34 -0
  23. package/dist/agent/fallback/runner.js.map +1 -0
  24. package/dist/agent/helpers.d.ts +38 -0
  25. package/dist/agent/helpers.js +122 -0
  26. package/dist/agent/helpers.js.map +1 -0
  27. package/dist/agent/index.d.ts +7 -0
  28. package/dist/agent/index.js +7 -0
  29. package/dist/agent/index.js.map +1 -0
  30. package/dist/agent/memory/compaction.d.ts +63 -0
  31. package/dist/agent/memory/compaction.js +233 -0
  32. package/dist/agent/memory/compaction.js.map +1 -0
  33. package/dist/agent/memory/window.d.ts +29 -0
  34. package/dist/agent/memory/window.js +64 -0
  35. package/dist/agent/memory/window.js.map +1 -0
  36. package/dist/agent/model-manager.d.ts +80 -0
  37. package/dist/agent/model-manager.js +213 -0
  38. package/dist/agent/model-manager.js.map +1 -0
  39. package/dist/agent/prompt/heartbeat.d.ts +97 -0
  40. package/dist/agent/prompt/heartbeat.js +313 -0
  41. package/dist/agent/prompt/heartbeat.js.map +1 -0
  42. package/dist/agent/prompt/index.d.ts +65 -0
  43. package/dist/agent/prompt/index.js +215 -0
  44. package/dist/agent/prompt/index.js.map +1 -0
  45. package/dist/agent/prompt/memory/index.d.ts +37 -0
  46. package/dist/agent/prompt/memory/index.js +241 -0
  47. package/dist/agent/prompt/memory/index.js.map +1 -0
  48. package/dist/agent/prompt/modes.d.ts +44 -0
  49. package/dist/agent/prompt/modes.js +167 -0
  50. package/dist/agent/prompt/modes.js.map +1 -0
  51. package/dist/agent/prompt/safety.d.ts +88 -0
  52. package/dist/agent/prompt/safety.js +290 -0
  53. package/dist/agent/prompt/safety.js.map +1 -0
  54. package/dist/agent/service.d.ts +91 -0
  55. package/dist/agent/service.js +641 -0
  56. package/dist/agent/service.js.map +1 -0
  57. package/dist/agent/session-tracker.d.ts +73 -0
  58. package/dist/agent/session-tracker.js +137 -0
  59. package/dist/agent/session-tracker.js.map +1 -0
  60. package/dist/agent/skills/__tests__/test-framework.test.d.ts +4 -0
  61. package/dist/agent/skills/__tests__/test-framework.test.js +343 -0
  62. package/dist/agent/skills/__tests__/test-framework.test.js.map +1 -0
  63. package/dist/agent/skills/config.d.ts +58 -0
  64. package/dist/agent/skills/config.js +212 -0
  65. package/dist/agent/skills/config.js.map +1 -0
  66. package/dist/agent/skills/index.d.ts +25 -0
  67. package/dist/agent/skills/index.js +349 -0
  68. package/dist/agent/skills/index.js.map +1 -0
  69. package/dist/agent/skills/installer.d.ts +38 -0
  70. package/dist/agent/skills/installer.js +352 -0
  71. package/dist/agent/skills/installer.js.map +1 -0
  72. package/dist/agent/skills/scanner.d.ts +32 -0
  73. package/dist/agent/skills/scanner.js +265 -0
  74. package/dist/agent/skills/scanner.js.map +1 -0
  75. package/dist/agent/skills/test-framework.d.ts +107 -0
  76. package/dist/agent/skills/test-framework.js +607 -0
  77. package/dist/agent/skills/test-framework.js.map +1 -0
  78. package/dist/agent/skills/types.d.ts +181 -0
  79. package/dist/agent/skills/types.js +7 -0
  80. package/dist/agent/skills/types.js.map +1 -0
  81. package/dist/agent/skills/watcher.d.ts +37 -0
  82. package/dist/agent/skills/watcher.js +124 -0
  83. package/dist/agent/skills/watcher.js.map +1 -0
  84. package/dist/agent/tools/communication.d.ts +18 -0
  85. package/dist/agent/tools/communication.js +56 -0
  86. package/dist/agent/tools/communication.js.map +1 -0
  87. package/dist/agent/tools/edit-diff.d.ts +21 -0
  88. package/dist/agent/tools/edit-diff.js +69 -0
  89. package/dist/agent/tools/edit-diff.js.map +1 -0
  90. package/dist/agent/tools/edit.d.ts +13 -0
  91. package/dist/agent/tools/edit.js +65 -0
  92. package/dist/agent/tools/edit.js.map +1 -0
  93. package/dist/agent/tools/find.d.ts +24 -0
  94. package/dist/agent/tools/find.js +99 -0
  95. package/dist/agent/tools/find.js.map +1 -0
  96. package/dist/agent/tools/grep.d.ts +33 -0
  97. package/dist/agent/tools/grep.js +183 -0
  98. package/dist/agent/tools/grep.js.map +1 -0
  99. package/dist/agent/tools/index.d.ts +13 -0
  100. package/dist/agent/tools/index.js +18 -0
  101. package/dist/agent/tools/index.js.map +1 -0
  102. package/dist/agent/tools/list-dir.d.ts +6 -0
  103. package/dist/agent/tools/list-dir.js +37 -0
  104. package/dist/agent/tools/list-dir.js.map +1 -0
  105. package/dist/agent/tools/memory-tool.d.ts +14 -0
  106. package/dist/agent/tools/memory-tool.js +81 -0
  107. package/dist/agent/tools/memory-tool.js.map +1 -0
  108. package/dist/agent/tools/path-utils.d.ts +4 -0
  109. package/dist/agent/tools/path-utils.js +13 -0
  110. package/dist/agent/tools/path-utils.js.map +1 -0
  111. package/dist/agent/tools/read.d.ts +7 -0
  112. package/dist/agent/tools/read.js +47 -0
  113. package/dist/agent/tools/read.js.map +1 -0
  114. package/dist/agent/tools/send-media.d.ts +18 -0
  115. package/dist/agent/tools/send-media.js +104 -0
  116. package/dist/agent/tools/send-media.js.map +1 -0
  117. package/dist/agent/tools/shell.d.ts +13 -0
  118. package/dist/agent/tools/shell.js +114 -0
  119. package/dist/agent/tools/shell.js.map +1 -0
  120. package/dist/agent/tools/truncate.d.ts +36 -0
  121. package/dist/agent/tools/truncate.js +98 -0
  122. package/dist/agent/tools/truncate.js.map +1 -0
  123. package/dist/agent/tools/web.d.ts +14 -0
  124. package/dist/agent/tools/web.js +109 -0
  125. package/dist/agent/tools/web.js.map +1 -0
  126. package/dist/agent/tools/write.d.ts +7 -0
  127. package/dist/agent/tools/write.js +35 -0
  128. package/dist/agent/tools/write.js.map +1 -0
  129. package/dist/agent/types.d.ts +8 -0
  130. package/dist/agent/types.js +2 -0
  131. package/dist/agent/types.js.map +1 -0
  132. package/dist/agent/typing.d.ts +9 -0
  133. package/dist/agent/typing.js +32 -0
  134. package/dist/agent/typing.js.map +1 -0
  135. package/dist/auth/index.d.ts +12 -0
  136. package/dist/auth/index.js +14 -0
  137. package/dist/auth/index.js.map +1 -0
  138. package/dist/auth/oauth/anthropic.d.ts +7 -0
  139. package/dist/auth/oauth/anthropic.js +89 -0
  140. package/dist/auth/oauth/anthropic.js.map +1 -0
  141. package/dist/auth/oauth/github-copilot.d.ts +8 -0
  142. package/dist/auth/oauth/github-copilot.js +35 -0
  143. package/dist/auth/oauth/github-copilot.js.map +1 -0
  144. package/dist/auth/oauth/google-antigravity.d.ts +7 -0
  145. package/dist/auth/oauth/google-antigravity.js +27 -0
  146. package/dist/auth/oauth/google-antigravity.js.map +1 -0
  147. package/dist/auth/oauth/google-gemini-cli.d.ts +7 -0
  148. package/dist/auth/oauth/google-gemini-cli.js +28 -0
  149. package/dist/auth/oauth/google-gemini-cli.js.map +1 -0
  150. package/dist/auth/oauth/index.d.ts +14 -0
  151. package/dist/auth/oauth/index.js +15 -0
  152. package/dist/auth/oauth/index.js.map +1 -0
  153. package/dist/auth/oauth/kimi.d.ts +8 -0
  154. package/dist/auth/oauth/kimi.js +104 -0
  155. package/dist/auth/oauth/kimi.js.map +1 -0
  156. package/dist/auth/oauth/minimax.d.ts +8 -0
  157. package/dist/auth/oauth/minimax.js +109 -0
  158. package/dist/auth/oauth/minimax.js.map +1 -0
  159. package/dist/auth/oauth/openai-codex.d.ts +7 -0
  160. package/dist/auth/oauth/openai-codex.js +33 -0
  161. package/dist/auth/oauth/openai-codex.js.map +1 -0
  162. package/dist/auth/oauth/pkce.d.ts +8 -0
  163. package/dist/auth/oauth/pkce.js +22 -0
  164. package/dist/auth/oauth/pkce.js.map +1 -0
  165. package/dist/auth/oauth/qwen.d.ts +7 -0
  166. package/dist/auth/oauth/qwen.js +114 -0
  167. package/dist/auth/oauth/qwen.js.map +1 -0
  168. package/dist/auth/oauth/types.d.ts +46 -0
  169. package/dist/auth/oauth/types.js +7 -0
  170. package/dist/auth/oauth/types.js.map +1 -0
  171. package/dist/auth/profiles/index.d.ts +16 -0
  172. package/dist/auth/profiles/index.js +17 -0
  173. package/dist/auth/profiles/index.js.map +1 -0
  174. package/dist/auth/profiles/oauth.d.ts +12 -0
  175. package/dist/auth/profiles/oauth.js +106 -0
  176. package/dist/auth/profiles/oauth.js.map +1 -0
  177. package/dist/auth/profiles/order.d.ts +19 -0
  178. package/dist/auth/profiles/order.js +63 -0
  179. package/dist/auth/profiles/order.js.map +1 -0
  180. package/dist/auth/profiles/profiles.d.ts +27 -0
  181. package/dist/auth/profiles/profiles.js +110 -0
  182. package/dist/auth/profiles/profiles.js.map +1 -0
  183. package/dist/auth/profiles/store.d.ts +17 -0
  184. package/dist/auth/profiles/store.js +234 -0
  185. package/dist/auth/profiles/store.js.map +1 -0
  186. package/dist/auth/profiles/types.d.ts +64 -0
  187. package/dist/auth/profiles/types.js +7 -0
  188. package/dist/auth/profiles/types.js.map +1 -0
  189. package/dist/auth/profiles/usage.d.ts +24 -0
  190. package/dist/auth/profiles/usage.js +99 -0
  191. package/dist/auth/profiles/usage.js.map +1 -0
  192. package/dist/auth/storage.d.ts +99 -0
  193. package/dist/auth/storage.js +315 -0
  194. package/dist/auth/storage.js.map +1 -0
  195. package/dist/bus/index.d.ts +3 -0
  196. package/dist/bus/index.js +2 -0
  197. package/dist/bus/index.js.map +1 -0
  198. package/dist/bus/queue.d.ts +20 -0
  199. package/dist/bus/queue.js +57 -0
  200. package/dist/bus/queue.js.map +1 -0
  201. package/dist/channels/__tests__/access-control.test.d.ts +4 -0
  202. package/dist/channels/__tests__/access-control.test.js +310 -0
  203. package/dist/channels/__tests__/access-control.test.js.map +1 -0
  204. package/dist/channels/__tests__/draft-stream.test.d.ts +4 -0
  205. package/dist/channels/__tests__/draft-stream.test.js +243 -0
  206. package/dist/channels/__tests__/draft-stream.test.js.map +1 -0
  207. package/dist/channels/__tests__/format.test.d.ts +4 -0
  208. package/dist/channels/__tests__/format.test.js +146 -0
  209. package/dist/channels/__tests__/format.test.js.map +1 -0
  210. package/dist/channels/__tests__/manager.test.d.ts +6 -0
  211. package/dist/channels/__tests__/manager.test.js +34 -0
  212. package/dist/channels/__tests__/manager.test.js.map +1 -0
  213. package/dist/channels/__tests__/typing-controller.test.d.ts +4 -0
  214. package/dist/channels/__tests__/typing-controller.test.js +109 -0
  215. package/dist/channels/__tests__/typing-controller.test.js.map +1 -0
  216. package/dist/channels/__tests__/update-offset-store.test.d.ts +7 -0
  217. package/dist/channels/__tests__/update-offset-store.test.js +35 -0
  218. package/dist/channels/__tests__/update-offset-store.test.js.map +1 -0
  219. package/dist/channels/access-control.d.ts +93 -0
  220. package/dist/channels/access-control.js +201 -0
  221. package/dist/channels/access-control.js.map +1 -0
  222. package/dist/channels/draft-stream.d.ts +55 -0
  223. package/dist/channels/draft-stream.js +211 -0
  224. package/dist/channels/draft-stream.js.map +1 -0
  225. package/dist/channels/format.d.ts +38 -0
  226. package/dist/channels/format.js +187 -0
  227. package/dist/channels/format.js.map +1 -0
  228. package/dist/channels/index.d.ts +22 -0
  229. package/dist/channels/index.js +23 -0
  230. package/dist/channels/index.js.map +1 -0
  231. package/dist/channels/manager.d.ts +30 -0
  232. package/dist/channels/manager.js +125 -0
  233. package/dist/channels/manager.js.map +1 -0
  234. package/dist/channels/telegram/__tests__/index.test.d.ts +4 -0
  235. package/dist/channels/telegram/__tests__/index.test.js +153 -0
  236. package/dist/channels/telegram/__tests__/index.test.js.map +1 -0
  237. package/dist/channels/telegram/__tests__/inline-keyboards.test.d.ts +4 -0
  238. package/dist/channels/telegram/__tests__/inline-keyboards.test.js +99 -0
  239. package/dist/channels/telegram/__tests__/inline-keyboards.test.js.map +1 -0
  240. package/dist/channels/telegram/client.d.ts +48 -0
  241. package/dist/channels/telegram/client.js +177 -0
  242. package/dist/channels/telegram/client.js.map +1 -0
  243. package/dist/channels/telegram/command-handler.d.ts +28 -0
  244. package/dist/channels/telegram/command-handler.js +209 -0
  245. package/dist/channels/telegram/command-handler.js.map +1 -0
  246. package/dist/channels/telegram/index.d.ts +8 -0
  247. package/dist/channels/telegram/index.js +9 -0
  248. package/dist/channels/telegram/index.js.map +1 -0
  249. package/dist/channels/telegram/inline-keyboards.d.ts +20 -0
  250. package/dist/channels/telegram/inline-keyboards.js +38 -0
  251. package/dist/channels/telegram/inline-keyboards.js.map +1 -0
  252. package/dist/channels/telegram/plugin.d.ts +33 -0
  253. package/dist/channels/telegram/plugin.js +640 -0
  254. package/dist/channels/telegram/plugin.js.map +1 -0
  255. package/dist/channels/telegram/webhook.d.ts +31 -0
  256. package/dist/channels/telegram/webhook.js +129 -0
  257. package/dist/channels/telegram/webhook.js.map +1 -0
  258. package/dist/channels/types.d.ts +186 -0
  259. package/dist/channels/types.js +7 -0
  260. package/dist/channels/types.js.map +1 -0
  261. package/dist/channels/typing-controller.d.ts +47 -0
  262. package/dist/channels/typing-controller.js +117 -0
  263. package/dist/channels/typing-controller.js.map +1 -0
  264. package/dist/channels/update-offset-store.d.ts +37 -0
  265. package/dist/channels/update-offset-store.js +165 -0
  266. package/dist/channels/update-offset-store.js.map +1 -0
  267. package/dist/channels/whatsapp/index.d.ts +4 -0
  268. package/dist/channels/whatsapp/index.js +5 -0
  269. package/dist/channels/whatsapp/index.js.map +1 -0
  270. package/dist/channels/whatsapp/plugin.d.ts +27 -0
  271. package/dist/channels/whatsapp/plugin.js +66 -0
  272. package/dist/channels/whatsapp/plugin.js.map +1 -0
  273. package/dist/cli/__tests__/registry.test.d.ts +1 -0
  274. package/dist/cli/__tests__/registry.test.js +366 -0
  275. package/dist/cli/__tests__/registry.test.js.map +1 -0
  276. package/dist/cli/commands/agent.d.ts +1 -0
  277. package/dist/cli/commands/agent.js +216 -0
  278. package/dist/cli/commands/agent.js.map +1 -0
  279. package/dist/cli/commands/auth.d.ts +6 -0
  280. package/dist/cli/commands/auth.js +440 -0
  281. package/dist/cli/commands/auth.js.map +1 -0
  282. package/dist/cli/commands/config.d.ts +1 -0
  283. package/dist/cli/commands/config.js +135 -0
  284. package/dist/cli/commands/config.js.map +1 -0
  285. package/dist/cli/commands/configure.d.ts +1 -0
  286. package/dist/cli/commands/configure.js +173 -0
  287. package/dist/cli/commands/configure.js.map +1 -0
  288. package/dist/cli/commands/cron.d.ts +1 -0
  289. package/dist/cli/commands/cron.js +81 -0
  290. package/dist/cli/commands/cron.js.map +1 -0
  291. package/dist/cli/commands/gateway.d.ts +1 -0
  292. package/dist/cli/commands/gateway.js +91 -0
  293. package/dist/cli/commands/gateway.js.map +1 -0
  294. package/dist/cli/commands/index.d.ts +0 -0
  295. package/dist/cli/commands/index.js +2 -0
  296. package/dist/cli/commands/index.js.map +1 -0
  297. package/dist/cli/commands/models.d.ts +1 -0
  298. package/dist/cli/commands/models.js +79 -0
  299. package/dist/cli/commands/models.js.map +1 -0
  300. package/dist/cli/commands/onboard.d.ts +1 -0
  301. package/dist/cli/commands/onboard.js +621 -0
  302. package/dist/cli/commands/onboard.js.map +1 -0
  303. package/dist/cli/commands/plugin.d.ts +1 -0
  304. package/dist/cli/commands/plugin.js +341 -0
  305. package/dist/cli/commands/plugin.js.map +1 -0
  306. package/dist/cli/commands/session.d.ts +1 -0
  307. package/dist/cli/commands/session.js +450 -0
  308. package/dist/cli/commands/session.js.map +1 -0
  309. package/dist/cli/commands/skills-test.d.ts +9 -0
  310. package/dist/cli/commands/skills-test.js +195 -0
  311. package/dist/cli/commands/skills-test.js.map +1 -0
  312. package/dist/cli/commands/skills.d.ts +9 -0
  313. package/dist/cli/commands/skills.js +385 -0
  314. package/dist/cli/commands/skills.js.map +1 -0
  315. package/dist/cli/index.d.ts +19 -0
  316. package/dist/cli/index.js +40 -0
  317. package/dist/cli/index.js.map +1 -0
  318. package/dist/cli/registry.d.ts +43 -0
  319. package/dist/cli/registry.js +82 -0
  320. package/dist/cli/registry.js.map +1 -0
  321. package/dist/cli/templates.d.ts +19 -0
  322. package/dist/cli/templates.js +191 -0
  323. package/dist/cli/templates.js.map +1 -0
  324. package/dist/cli/utils/colors.d.ts +13 -0
  325. package/dist/cli/utils/colors.js +16 -0
  326. package/dist/cli/utils/colors.js.map +1 -0
  327. package/dist/config/__tests__/diff.test.d.ts +1 -0
  328. package/dist/config/__tests__/diff.test.js +192 -0
  329. package/dist/config/__tests__/diff.test.js.map +1 -0
  330. package/dist/config/__tests__/loader.test.d.ts +1 -0
  331. package/dist/config/__tests__/loader.test.js +356 -0
  332. package/dist/config/__tests__/loader.test.js.map +1 -0
  333. package/dist/config/__tests__/paths.test.d.ts +1 -0
  334. package/dist/config/__tests__/paths.test.js +192 -0
  335. package/dist/config/__tests__/paths.test.js.map +1 -0
  336. package/dist/config/__tests__/reload.test.d.ts +1 -0
  337. package/dist/config/__tests__/reload.test.js +374 -0
  338. package/dist/config/__tests__/reload.test.js.map +1 -0
  339. package/dist/config/__tests__/rules.test.d.ts +1 -0
  340. package/dist/config/__tests__/rules.test.js +204 -0
  341. package/dist/config/__tests__/rules.test.js.map +1 -0
  342. package/dist/config/__tests__/schema.test.d.ts +1 -0
  343. package/dist/config/__tests__/schema.test.js +672 -0
  344. package/dist/config/__tests__/schema.test.js.map +1 -0
  345. package/dist/config/diff.d.ts +7 -0
  346. package/dist/config/diff.js +46 -0
  347. package/dist/config/diff.js.map +1 -0
  348. package/dist/config/index.d.ts +6 -0
  349. package/dist/config/index.js +7 -0
  350. package/dist/config/index.js.map +1 -0
  351. package/dist/config/loader.d.ts +5 -0
  352. package/dist/config/loader.js +81 -0
  353. package/dist/config/loader.js.map +1 -0
  354. package/dist/config/paths.d.ts +35 -0
  355. package/dist/config/paths.js +79 -0
  356. package/dist/config/paths.js.map +1 -0
  357. package/dist/config/reload.d.ts +78 -0
  358. package/dist/config/reload.js +190 -0
  359. package/dist/config/reload.js.map +1 -0
  360. package/dist/config/rules.d.ts +42 -0
  361. package/dist/config/rules.js +114 -0
  362. package/dist/config/rules.js.map +1 -0
  363. package/dist/config/schema.d.ts +1340 -0
  364. package/dist/config/schema.js +611 -0
  365. package/dist/config/schema.js.map +1 -0
  366. package/dist/cron/executor.d.ts +54 -0
  367. package/dist/cron/executor.js +364 -0
  368. package/dist/cron/executor.js.map +1 -0
  369. package/dist/cron/index.d.ts +5 -0
  370. package/dist/cron/index.js +6 -0
  371. package/dist/cron/index.js.map +1 -0
  372. package/dist/cron/persistence.d.ts +61 -0
  373. package/dist/cron/persistence.js +188 -0
  374. package/dist/cron/persistence.js.map +1 -0
  375. package/dist/cron/service.d.ts +94 -0
  376. package/dist/cron/service.js +382 -0
  377. package/dist/cron/service.js.map +1 -0
  378. package/dist/cron/types.d.ts +119 -0
  379. package/dist/cron/types.js +3 -0
  380. package/dist/cron/types.js.map +1 -0
  381. package/dist/cron/validation.d.ts +144 -0
  382. package/dist/cron/validation.js +113 -0
  383. package/dist/cron/validation.js.map +1 -0
  384. package/dist/errors/__tests__/index.test.d.ts +1 -0
  385. package/dist/errors/__tests__/index.test.js +301 -0
  386. package/dist/errors/__tests__/index.test.js.map +1 -0
  387. package/dist/errors/index.d.ts +114 -0
  388. package/dist/errors/index.js +278 -0
  389. package/dist/errors/index.js.map +1 -0
  390. package/dist/gateway/hono/app.d.ts +7 -0
  391. package/dist/gateway/hono/app.js +668 -0
  392. package/dist/gateway/hono/app.js.map +1 -0
  393. package/dist/gateway/hono/index.d.ts +2 -0
  394. package/dist/gateway/hono/index.js +3 -0
  395. package/dist/gateway/hono/index.js.map +1 -0
  396. package/dist/gateway/hono/middleware/auth.d.ts +18 -0
  397. package/dist/gateway/hono/middleware/auth.js +79 -0
  398. package/dist/gateway/hono/middleware/auth.js.map +1 -0
  399. package/dist/gateway/hono/middleware/logger.d.ts +1 -0
  400. package/dist/gateway/hono/middleware/logger.js +17 -0
  401. package/dist/gateway/hono/middleware/logger.js.map +1 -0
  402. package/dist/gateway/hono/sse.d.ts +55 -0
  403. package/dist/gateway/hono/sse.js +224 -0
  404. package/dist/gateway/hono/sse.js.map +1 -0
  405. package/dist/gateway/index.d.ts +4 -0
  406. package/dist/gateway/index.js +5 -0
  407. package/dist/gateway/index.js.map +1 -0
  408. package/dist/gateway/protocol.d.ts +28 -0
  409. package/dist/gateway/protocol.js +14 -0
  410. package/dist/gateway/protocol.js.map +1 -0
  411. package/dist/gateway/server.d.ts +19 -0
  412. package/dist/gateway/server.js +64 -0
  413. package/dist/gateway/server.js.map +1 -0
  414. package/dist/gateway/service.d.ts +265 -0
  415. package/dist/gateway/service.js +621 -0
  416. package/dist/gateway/service.js.map +1 -0
  417. package/dist/gateway/static/root/assets/main-CfIxL-cL.js +2105 -0
  418. package/dist/gateway/static/root/assets/main-CfIxL-cL.js.map +1 -0
  419. package/dist/gateway/static/root/assets/main-DndcTCgX.css +1 -0
  420. package/dist/gateway/static/root/index.html +116 -0
  421. package/dist/heartbeat/index.d.ts +1 -0
  422. package/dist/heartbeat/index.js +2 -0
  423. package/dist/heartbeat/index.js.map +1 -0
  424. package/dist/heartbeat/service.d.ts +19 -0
  425. package/dist/heartbeat/service.js +61 -0
  426. package/dist/heartbeat/service.js.map +1 -0
  427. package/dist/plugin-sdk/index.d.ts +21 -0
  428. package/dist/plugin-sdk/index.js +12 -0
  429. package/dist/plugin-sdk/index.js.map +1 -0
  430. package/dist/plugins/__tests__/api.test.d.ts +1 -0
  431. package/dist/plugins/__tests__/api.test.js +164 -0
  432. package/dist/plugins/__tests__/api.test.js.map +1 -0
  433. package/dist/plugins/__tests__/hooks.test.d.ts +1 -0
  434. package/dist/plugins/__tests__/hooks.test.js +159 -0
  435. package/dist/plugins/__tests__/hooks.test.js.map +1 -0
  436. package/dist/plugins/__tests__/loader.test.d.ts +1 -0
  437. package/dist/plugins/__tests__/loader.test.js +120 -0
  438. package/dist/plugins/__tests__/loader.test.js.map +1 -0
  439. package/dist/plugins/api.d.ts +41 -0
  440. package/dist/plugins/api.js +131 -0
  441. package/dist/plugins/api.js.map +1 -0
  442. package/dist/plugins/hooks.d.ts +153 -0
  443. package/dist/plugins/hooks.js +172 -0
  444. package/dist/plugins/hooks.js.map +1 -0
  445. package/dist/plugins/index.d.ts +11 -0
  446. package/dist/plugins/index.js +16 -0
  447. package/dist/plugins/index.js.map +1 -0
  448. package/dist/plugins/install.d.ts +59 -0
  449. package/dist/plugins/install.js +324 -0
  450. package/dist/plugins/install.js.map +1 -0
  451. package/dist/plugins/loader.d.ts +84 -0
  452. package/dist/plugins/loader.js +545 -0
  453. package/dist/plugins/loader.js.map +1 -0
  454. package/dist/plugins/types.d.ts +190 -0
  455. package/dist/plugins/types.js +7 -0
  456. package/dist/plugins/types.js.map +1 -0
  457. package/dist/providers/__tests__/registry.test.d.ts +1 -0
  458. package/dist/providers/__tests__/registry.test.js +110 -0
  459. package/dist/providers/__tests__/registry.test.js.map +1 -0
  460. package/dist/providers/api-strategies.d.ts +15 -0
  461. package/dist/providers/api-strategies.js +96 -0
  462. package/dist/providers/api-strategies.js.map +1 -0
  463. package/dist/providers/auto-discovery.d.ts +84 -0
  464. package/dist/providers/auto-discovery.js +236 -0
  465. package/dist/providers/auto-discovery.js.map +1 -0
  466. package/dist/providers/config.d.ts +25 -0
  467. package/dist/providers/config.js +42 -0
  468. package/dist/providers/config.js.map +1 -0
  469. package/dist/providers/index.d.ts +25 -0
  470. package/dist/providers/index.js +55 -0
  471. package/dist/providers/index.js.map +1 -0
  472. package/dist/providers/model-catalog.d.ts +205 -0
  473. package/dist/providers/model-catalog.js +1071 -0
  474. package/dist/providers/model-catalog.js.map +1 -0
  475. package/dist/providers/models-dev-data.d.ts +11 -0
  476. package/dist/providers/models-dev-data.js +1035 -0
  477. package/dist/providers/models-dev-data.js.map +1 -0
  478. package/dist/providers/models-dev.d.ts +30 -0
  479. package/dist/providers/models-dev.js +42 -0
  480. package/dist/providers/models-dev.js.map +1 -0
  481. package/dist/providers/pi-ai.d.ts +62 -0
  482. package/dist/providers/pi-ai.js +221 -0
  483. package/dist/providers/pi-ai.js.map +1 -0
  484. package/dist/providers/provider-catalog.d.ts +173 -0
  485. package/dist/providers/provider-catalog.js +834 -0
  486. package/dist/providers/provider-catalog.js.map +1 -0
  487. package/dist/providers/registry.d.ts +155 -0
  488. package/dist/providers/registry.js +524 -0
  489. package/dist/providers/registry.js.map +1 -0
  490. package/dist/providers/types.d.ts +95 -0
  491. package/dist/providers/types.js +7 -0
  492. package/dist/providers/types.js.map +1 -0
  493. package/dist/session/chat-manager.d.ts +49 -0
  494. package/dist/session/chat-manager.js +167 -0
  495. package/dist/session/chat-manager.js.map +1 -0
  496. package/dist/session/chat-types.d.ts +53 -0
  497. package/dist/session/chat-types.js +63 -0
  498. package/dist/session/chat-types.js.map +1 -0
  499. package/dist/session/index.d.ts +5 -0
  500. package/dist/session/index.js +5 -0
  501. package/dist/session/index.js.map +1 -0
  502. package/dist/session/manager.d.ts +103 -0
  503. package/dist/session/manager.js +200 -0
  504. package/dist/session/manager.js.map +1 -0
  505. package/dist/session/store.d.ts +114 -0
  506. package/dist/session/store.js +687 -0
  507. package/dist/session/store.js.map +1 -0
  508. package/dist/session/types.d.ts +88 -0
  509. package/dist/session/types.js +10 -0
  510. package/dist/session/types.js.map +1 -0
  511. package/dist/types/index.d.ts +177 -0
  512. package/dist/types/index.js +4 -0
  513. package/dist/types/index.js.map +1 -0
  514. package/dist/types/providers.d.ts +67 -0
  515. package/dist/types/providers.js +7 -0
  516. package/dist/types/providers.js.map +1 -0
  517. package/dist/utils/frontmatter.d.ts +17 -0
  518. package/dist/utils/frontmatter.js +104 -0
  519. package/dist/utils/frontmatter.js.map +1 -0
  520. package/dist/utils/helpers.d.ts +5 -0
  521. package/dist/utils/helpers.js +36 -0
  522. package/dist/utils/helpers.js.map +1 -0
  523. package/dist/utils/index.d.ts +2 -0
  524. package/dist/utils/index.js +3 -0
  525. package/dist/utils/index.js.map +1 -0
  526. package/dist/utils/log-store.d.ts +78 -0
  527. package/dist/utils/log-store.js +432 -0
  528. package/dist/utils/log-store.js.map +1 -0
  529. package/dist/utils/logger.d.ts +127 -0
  530. package/dist/utils/logger.js +481 -0
  531. package/dist/utils/logger.js.map +1 -0
  532. package/dist/utils/logger.types.d.ts +152 -0
  533. package/dist/utils/logger.types.js +30 -0
  534. package/dist/utils/logger.types.js.map +1 -0
  535. package/package.json +93 -0
@@ -0,0 +1,2105 @@
1
+ (function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))i(n);new MutationObserver(n=>{for(const r of n)if(r.type==="childList")for(const l of r.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&i(l)}).observe(document,{childList:!0,subtree:!0});function s(n){const r={};return n.integrity&&(r.integrity=n.integrity),n.referrerPolicy&&(r.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?r.credentials="include":n.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function i(n){if(n.ep)return;n.ep=!0;const r=s(n);fetch(n.href,r)}})();const ye=globalThis,De=ye.ShadowRoot&&(ye.ShadyCSS===void 0||ye.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,it=Symbol(),He=new WeakMap;let mt=class{constructor(t,s,i){if(this._$cssResult$=!0,i!==it)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=s}get styleSheet(){let t=this.o;const s=this.t;if(De&&t===void 0){const i=s!==void 0&&s.length===1;i&&(t=He.get(s)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&He.set(s,t))}return t}toString(){return this.cssText}};const _t=e=>new mt(typeof e=="string"?e:e+"",void 0,it),vt=(e,t)=>{if(De)e.adoptedStyleSheets=t.map(s=>s instanceof CSSStyleSheet?s:s.styleSheet);else for(const s of t){const i=document.createElement("style"),n=ye.litNonce;n!==void 0&&i.setAttribute("nonce",n),i.textContent=s.cssText,e.appendChild(i)}},Ne=De?e=>e:e=>e instanceof CSSStyleSheet?(t=>{let s="";for(const i of t.cssRules)s+=i.cssText;return _t(s)})(e):e;const{is:ft,defineProperty:yt,getOwnPropertyDescriptor:wt,getOwnPropertyNames:bt,getOwnPropertySymbols:$t,getPrototypeOf:xt}=Object,ke=globalThis,ze=ke.trustedTypes,St=ze?ze.emptyScript:"",kt=ke.reactiveElementPolyfillSupport,he=(e,t)=>e,we={toAttribute(e,t){switch(t){case Boolean:e=e?St:null;break;case Object:case Array:e=e==null?e:JSON.stringify(e)}return e},fromAttribute(e,t){let s=e;switch(t){case Boolean:s=e!==null;break;case Number:s=e===null?null:Number(e);break;case Object:case Array:try{s=JSON.parse(e)}catch{s=null}}return s}},Oe=(e,t)=>!ft(e,t),qe={attribute:!0,type:String,converter:we,reflect:!1,useDefault:!1,hasChanged:Oe};Symbol.metadata??=Symbol("metadata"),ke.litPropertyMetadata??=new WeakMap;let ee=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=qe){if(s.state&&(s.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=!0),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),n=this.getPropertyDescriptor(t,i,s);n!==void 0&&yt(this.prototype,t,n)}}static getPropertyDescriptor(t,s,i){const{get:n,set:r}=wt(this.prototype,t)??{get(){return this[s]},set(l){this[s]=l}};return{get:n,set(l){const h=n?.call(this);r?.call(this,l),this.requestUpdate(t,h,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??qe}static _$Ei(){if(this.hasOwnProperty(he("elementProperties")))return;const t=xt(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(he("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(he("properties"))){const s=this.properties,i=[...bt(s),...$t(s)];for(const n of i)this.createProperty(n,s[n])}const t=this[Symbol.metadata];if(t!==null){const s=litPropertyMetadata.get(t);if(s!==void 0)for(const[i,n]of s)this.elementProperties.set(i,n)}this._$Eh=new Map;for(const[s,i]of this.elementProperties){const n=this._$Eu(s,i);n!==void 0&&this._$Eh.set(n,s)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const s=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const n of i)s.unshift(Ne(n))}else t!==void 0&&s.push(Ne(t));return s}static _$Eu(t,s){const i=s.attribute;return i===!1?void 0:typeof i=="string"?i:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return vt(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,s,i){this._$AK(t,i)}_$ET(t,s){const i=this.constructor.elementProperties.get(t),n=this.constructor._$Eu(t,i);if(n!==void 0&&i.reflect===!0){const r=(i.converter?.toAttribute!==void 0?i.converter:we).toAttribute(s,i.type);this._$Em=t,r==null?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(t,s){const i=this.constructor,n=i._$Eh.get(t);if(n!==void 0&&this._$Em!==n){const r=i.getPropertyOptions(n),l=typeof r.converter=="function"?{fromAttribute:r.converter}:r.converter?.fromAttribute!==void 0?r.converter:we;this._$Em=n;const h=l.fromAttribute(s,r.type);this[n]=h??this._$Ej?.get(n)??h,this._$Em=null}}requestUpdate(t,s,i,n=!1,r){if(t!==void 0){const l=this.constructor;if(n===!1&&(r=this[t]),i??=l.getPropertyOptions(t),!((i.hasChanged??Oe)(r,s)||i.useDefault&&i.reflect&&r===this._$Ej?.get(t)&&!this.hasAttribute(l._$Eu(t,i))))return;this.C(t,s,i)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,s,{useDefault:i,reflect:n,wrapped:r},l){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,l??s??this[t]),r!==!0||l!==void 0)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),n===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(s){Promise.reject(s)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[n,r]of this._$Ep)this[n]=r;this._$Ep=void 0}const i=this.constructor.elementProperties;if(i.size>0)for(const[n,r]of i){const{wrapped:l}=r,h=this[n];l!==!0||this._$AL.has(n)||h===void 0||this.C(n,void 0,r,h)}}let t=!1;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach(i=>i.hostUpdate?.()),this.update(s)):this._$EM()}catch(i){throw t=!1,this._$EM(),i}t&&this._$AE(s)}willUpdate(t){}_$AE(t){this._$EO?.forEach(s=>s.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(s=>this._$ET(s,this[s])),this._$EM()}updated(t){}firstUpdated(t){}};ee.elementStyles=[],ee.shadowRootOptions={mode:"open"},ee[he("elementProperties")]=new Map,ee[he("finalized")]=new Map,kt?.({ReactiveElement:ee}),(ke.reactiveElementVersions??=[]).push("2.1.2");const Re=globalThis,Je=e=>e,be=Re.trustedTypes,Ge=be?be.createPolicy("lit-html",{createHTML:e=>e}):void 0,nt="$lit$",B=`lit$${Math.random().toFixed(9).slice(2)}$`,ot="?"+B,At=`<${ot}>`,J=document,pe=()=>J.createComment(""),ue=e=>e===null||typeof e!="object"&&typeof e!="function",Be=Array.isArray,Ct=e=>Be(e)||typeof e?.[Symbol.iterator]=="function",Te=`[
2
+ \f\r]`,re=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,We=/-->/g,Ve=/>/g,N=RegExp(`>|${Te}(?:([^\\s"'>=/]+)(${Te}*=${Te}*(?:[^
3
+ \f\r"'\`<>=]|("|')|))|$)`,"g"),Qe=/'/g,Xe=/"/g,rt=/^(?:script|style|textarea|title)$/i,Mt=e=>(t,...s)=>({_$litType$:e,strings:t,values:s}),o=Mt(1),G=Symbol.for("lit-noChange"),m=Symbol.for("lit-nothing"),Ze=new WeakMap,z=J.createTreeWalker(J,129);function at(e,t){if(!Be(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return Ge!==void 0?Ge.createHTML(t):t}const Tt=(e,t)=>{const s=e.length-1,i=[];let n,r=t===2?"<svg>":t===3?"<math>":"",l=re;for(let h=0;h<s;h++){const d=e[h];let g,S,f=-1,E=0;for(;E<d.length&&(l.lastIndex=E,S=l.exec(d),S!==null);)E=l.lastIndex,l===re?S[1]==="!--"?l=We:S[1]!==void 0?l=Ve:S[2]!==void 0?(rt.test(S[2])&&(n=RegExp("</"+S[2],"g")),l=N):S[3]!==void 0&&(l=N):l===N?S[0]===">"?(l=n??re,f=-1):S[1]===void 0?f=-2:(f=l.lastIndex-S[2].length,g=S[1],l=S[3]===void 0?N:S[3]==='"'?Xe:Qe):l===Xe||l===Qe?l=N:l===We||l===Ve?l=re:(l=N,n=void 0);const L=l===N&&e[h+1].startsWith("/>")?" ":"";r+=l===re?d+At:f>=0?(i.push(g),d.slice(0,f)+nt+d.slice(f)+B+L):d+B+(f===-2?h:L)}return[at(e,r+(e[s]||"<?>")+(t===2?"</svg>":t===3?"</math>":"")),i]};class ge{constructor({strings:t,_$litType$:s},i){let n;this.parts=[];let r=0,l=0;const h=t.length-1,d=this.parts,[g,S]=Tt(t,s);if(this.el=ge.createElement(g,i),z.currentNode=this.el.content,s===2||s===3){const f=this.el.content.firstChild;f.replaceWith(...f.childNodes)}for(;(n=z.nextNode())!==null&&d.length<h;){if(n.nodeType===1){if(n.hasAttributes())for(const f of n.getAttributeNames())if(f.endsWith(nt)){const E=S[l++],L=n.getAttribute(f).split(B),ve=/([.?@])?(.*)/.exec(E);d.push({type:1,index:r,name:ve[2],strings:L,ctor:ve[1]==="."?Pt:ve[1]==="?"?Ft:ve[1]==="@"?Lt:Ae}),n.removeAttribute(f)}else f.startsWith(B)&&(d.push({type:6,index:r}),n.removeAttribute(f));if(rt.test(n.tagName)){const f=n.textContent.split(B),E=f.length-1;if(E>0){n.textContent=be?be.emptyScript:"";for(let L=0;L<E;L++)n.append(f[L],pe()),z.nextNode(),d.push({type:2,index:++r});n.append(f[E],pe())}}}else if(n.nodeType===8)if(n.data===ot)d.push({type:2,index:r});else{let f=-1;for(;(f=n.data.indexOf(B,f+1))!==-1;)d.push({type:7,index:r}),f+=B.length-1}r++}}static createElement(t,s){const i=J.createElement("template");return i.innerHTML=t,i}}function se(e,t,s=e,i){if(t===G)return t;let n=i!==void 0?s._$Co?.[i]:s._$Cl;const r=ue(t)?void 0:t._$litDirective$;return n?.constructor!==r&&(n?._$AO?.(!1),r===void 0?n=void 0:(n=new r(e),n._$AT(e,s,i)),i!==void 0?(s._$Co??=[])[i]=n:s._$Cl=n),n!==void 0&&(t=se(e,n._$AS(e,t.values),n,i)),t}class Et{constructor(t,s){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=s}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:s},parts:i}=this._$AD,n=(t?.creationScope??J).importNode(s,!0);z.currentNode=n;let r=z.nextNode(),l=0,h=0,d=i[0];for(;d!==void 0;){if(l===d.index){let g;d.type===2?g=new _e(r,r.nextSibling,this,t):d.type===1?g=new d.ctor(r,d.name,d.strings,this,t):d.type===6&&(g=new It(r,this,t)),this._$AV.push(g),d=i[++h]}l!==d?.index&&(r=z.nextNode(),l++)}return z.currentNode=J,n}p(t){let s=0;for(const i of this._$AV)i!==void 0&&(i.strings!==void 0?(i._$AI(t,i,s),s+=i.strings.length-2):i._$AI(t[s])),s++}}class _e{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,s,i,n){this.type=2,this._$AH=m,this._$AN=void 0,this._$AA=t,this._$AB=s,this._$AM=i,this.options=n,this._$Cv=n?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const s=this._$AM;return s!==void 0&&t?.nodeType===11&&(t=s.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,s=this){t=se(this,t,s),ue(t)?t===m||t==null||t===""?(this._$AH!==m&&this._$AR(),this._$AH=m):t!==this._$AH&&t!==G&&this._(t):t._$litType$!==void 0?this.$(t):t.nodeType!==void 0?this.T(t):Ct(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==m&&ue(this._$AH)?this._$AA.nextSibling.data=t:this.T(J.createTextNode(t)),this._$AH=t}$(t){const{values:s,_$litType$:i}=t,n=typeof i=="number"?this._$AC(t):(i.el===void 0&&(i.el=ge.createElement(at(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(s);else{const r=new Et(n,this),l=r.u(this.options);r.p(s),this.T(l),this._$AH=r}}_$AC(t){let s=Ze.get(t.strings);return s===void 0&&Ze.set(t.strings,s=new ge(t)),s}k(t){Be(this._$AH)||(this._$AH=[],this._$AR());const s=this._$AH;let i,n=0;for(const r of t)n===s.length?s.push(i=new _e(this.O(pe()),this.O(pe()),this,this.options)):i=s[n],i._$AI(r),n++;n<s.length&&(this._$AR(i&&i._$AB.nextSibling,n),s.length=n)}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(!1,!0,s);t!==this._$AB;){const i=Je(t).nextSibling;Je(t).remove(),t=i}}setConnected(t){this._$AM===void 0&&(this._$Cv=t,this._$AP?.(t))}}class Ae{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,s,i,n,r){this.type=1,this._$AH=m,this._$AN=void 0,this.element=t,this.name=s,this._$AM=n,this.options=r,i.length>2||i[0]!==""||i[1]!==""?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=m}_$AI(t,s=this,i,n){const r=this.strings;let l=!1;if(r===void 0)t=se(this,t,s,0),l=!ue(t)||t!==this._$AH&&t!==G,l&&(this._$AH=t);else{const h=t;let d,g;for(t=r[0],d=0;d<r.length-1;d++)g=se(this,h[i+d],s,d),g===G&&(g=this._$AH[d]),l||=!ue(g)||g!==this._$AH[d],g===m?t=m:t!==m&&(t+=(g??"")+r[d+1]),this._$AH[d]=g}l&&!n&&this.j(t)}j(t){t===m?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}}class Pt extends Ae{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===m?void 0:t}}class Ft extends Ae{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==m)}}class Lt extends Ae{constructor(t,s,i,n,r){super(t,s,i,n,r),this.type=5}_$AI(t,s=this){if((t=se(this,t,s,0)??m)===G)return;const i=this._$AH,n=t===m&&i!==m||t.capture!==i.capture||t.once!==i.once||t.passive!==i.passive,r=t!==m&&(i===m||n);n&&this.element.removeEventListener(this.name,this,i),r&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}}class It{constructor(t,s,i){this.element=t,this.type=6,this._$AN=void 0,this._$AM=s,this.options=i}get _$AU(){return this._$AM._$AU}_$AI(t){se(this,t)}}const Dt=Re.litHtmlPolyfillSupport;Dt?.(ge,_e),(Re.litHtmlVersions??=[]).push("3.3.2");const Ot=(e,t,s)=>{const i=s?.renderBefore??t;let n=i._$litPart$;if(n===void 0){const r=s?.renderBefore??null;i._$litPart$=n=new _e(t.insertBefore(pe(),r),r,void 0,s??{})}return n._$AI(e),n};const Ke=globalThis;let y=class extends ee{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const s=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=Ot(s,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return G}};y._$litElement$=!0,y.finalized=!0,Ke.litElementHydrateSupport?.({LitElement:y});const Rt=Ke.litElementPolyfillSupport;Rt?.({LitElement:y});(Ke.litElementVersions??=[]).push("4.2.2");const k=e=>(t,s)=>{s!==void 0?s.addInitializer(()=>{customElements.define(e,t)}):customElements.define(e,t)};const Bt={attribute:!0,type:String,converter:we,reflect:!1,hasChanged:Oe},Kt=(e=Bt,t,s)=>{const{kind:i,metadata:n}=s;let r=globalThis.litPropertyMetadata.get(n);if(r===void 0&&globalThis.litPropertyMetadata.set(n,r=new Map),i==="setter"&&((e=Object.create(e)).wrapped=!0),r.set(s.name,e),i==="accessor"){const{name:l}=s;return{set(h){const d=t.get.call(this);t.set.call(this,h),this.requestUpdate(l,d,e,!0,h)},init(h){return h!==void 0&&this.C(l,void 0,e,h),h}}}if(i==="setter"){const{name:l}=s;return function(h){const d=this[l];t.call(this,h),this.requestUpdate(l,d,e,!0,h)}}throw Error("Unsupported decorator location: "+i)};function u(e){return(t,s)=>typeof s=="object"?Kt(e,t,s):((i,n,r)=>{const l=n.hasOwnProperty(r);return n.constructor.createProperty(r,i),l?Object.getOwnPropertyDescriptor(n,r):void 0})(e,t,s)}function c(e){return u({...e,state:!0,attribute:!1})}const jt=(e,t,s)=>(s.configurable=!0,s.enumerable=!0,Reflect.decorate&&typeof t!="object"&&Object.defineProperty(e,t,s),s);function ie(e,t){return(s,i,n)=>{const r=l=>l.renderRoot?.querySelector(e)??null;return jt(s,i,{get(){return r(this)}})}}const Ut=e=>e.strings===void 0;const lt={CHILD:2},ct=e=>(...t)=>({_$litDirective$:e,values:t});class ht{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,s,i){this._$Ct=t,this._$AM=s,this._$Ci=i}_$AS(t,s){return this.update(t,s)}update(t,s){return this.render(...s)}}const de=(e,t)=>{const s=e._$AN;if(s===void 0)return!1;for(const i of s)i._$AO?.(t,!1),de(i,t);return!0},$e=e=>{let t,s;do{if((t=e._$AM)===void 0)break;s=t._$AN,s.delete(e),e=t}while(s?.size===0)},dt=e=>{for(let t;t=e._$AM;e=t){let s=t._$AN;if(s===void 0)t._$AN=s=new Set;else if(s.has(e))break;s.add(e),zt(t)}};function Ht(e){this._$AN!==void 0?($e(this),this._$AM=e,dt(this)):this._$AM=e}function Nt(e,t=!1,s=0){const i=this._$AH,n=this._$AN;if(n!==void 0&&n.size!==0)if(t)if(Array.isArray(i))for(let r=s;r<i.length;r++)de(i[r],!1),$e(i[r]);else i!=null&&(de(i,!1),$e(i));else de(this,e)}const zt=e=>{e.type==lt.CHILD&&(e._$AP??=Nt,e._$AQ??=Ht)};class qt extends ht{constructor(){super(...arguments),this._$AN=void 0}_$AT(t,s,i){super._$AT(t,s,i),dt(this),this.isConnected=t._$AU}_$AO(t,s=!0){t!==this.isConnected&&(this.isConnected=t,t?this.reconnected?.():this.disconnected?.()),s&&(de(this,t),$e(this))}setValue(t){if(Ut(this._$Ct))this._$Ct._$AI(t,this);else{const s=[...this._$Ct._$AH];s[this._$Ci]=t,this._$Ct._$AI(s,this,0)}}disconnected(){}reconnected(){}}const Ye=()=>new Jt;class Jt{}const Ee=new WeakMap,et=ct(class extends qt{render(e){return m}update(e,[t]){const s=t!==this.G;return s&&this.G!==void 0&&this.rt(void 0),(s||this.lt!==this.ct)&&(this.G=t,this.ht=e.options?.host,this.rt(this.ct=e.element)),m}rt(e){if(this.isConnected||(e=void 0),typeof this.G=="function"){const t=this.ht??globalThis;let s=Ee.get(t);s===void 0&&(s=new WeakMap,Ee.set(t,s)),s.get(this.G)!==void 0&&this.G.call(this.ht,void 0),s.set(this.G,e),e!==void 0&&this.G.call(this.ht,e)}else this.G.value=e}get lt(){return typeof this.G=="function"?Ee.get(this.ht??globalThis)?.get(this.G):this.G?.value}disconnected(){this.lt===this.ct&&this.rt(void 0)}reconnected(){this.rt(this.ct)}});class Pe extends ht{constructor(t){if(super(t),this.it=m,t.type!==lt.CHILD)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===m||t==null)return this._t=void 0,this.it=t;if(t===G)return t;if(typeof t!="string")throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.it)return this._t;this.it=t;const s=[t];return s.raw=s,this._t={_$litType$:this.constructor.resultType,strings:s,values:[]}}}Pe.directiveName="unsafeHTML",Pe.resultType=1;const ae=ct(Pe);const Ce={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"};const Gt=["svg",Ce,[["path",{d:"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"}]]];const Wt=["svg",Ce,[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"}],["path",{d:"m21.854 2.147-10.94 10.939"}]]];const Vt=["svg",Ce,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]];const Qt=["svg",Ce,[["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]]],Xt={title:"XOPCBOT Gateway",brand:"XOPCBOT"},Zt={chat:"Chat",sessions:"Sessions",cron:"Cron Jobs",logs:"Logs",settings:"Settings",management:"Management"},Yt={title:"XopcBot",newSession:"New Chat",welcomeTitle:"Welcome to xopcbot",welcomeDescription:"Send a message to get started",emptyState:"No messages yet",emptyStateDescription:"Start a conversation by typing a message below",you:"You",assistant:"Assistant",tool:"Tool",thinking:"thinking...",typeMessage:"Type a message...",attachFile:"Attach file",sendMessage:"Send message",abort:"Abort",retry:"Retry",reasoning:"Reasoning",thinkingLevelNone:"None",thinkingLevel1:"Level 1",thinkingLevel2:"Level 2",thinkingLevel3:"Level 3",thinkingLevel4:"Level 4",connecting:"Connecting...",disconnected:"Disconnected",connectionError:"Connection error",reconnecting:"Reconnecting...",online:"Online",offline:"Offline"},es={title:"Settings",save:"Save",cancel:"Cancel",close:"Close",loading:"Loading settings...",unsaved:"{{count}} unsaved",saveChanges:"Save Changes",saving:"Saving...",noSection:"No section selected",enableFeature:"Enable this feature",required:"{{field}} is required",invalidFormat:"Invalid format",unsavedChanges:"Unsaved changes",sections:{agent:"Agent",providers:"Providers",channels:"Channels",gateway:"Gateway"},descriptions:{agent:"Configure your agent settings",providers:"Configure your provider API keys",channels:"Configure messaging channels",gateway:"Configure gateway settings"},fields:{model:"Model",workspace:"Workspace",maxTokens:"Max Tokens",temperature:"Temperature",maxToolIterations:"Max Tool Iterations",openaiApiKey:"OpenAI API Key",anthropicApiKey:"Anthropic API Key",googleApiKey:"Google API Key",qwenApiKey:"Qwen API Key",kimiApiKey:"Kimi API Key",minimaxApiKey:"MiniMax API Key",deepseekApiKey:"DeepSeek API Key",grokApiKey:"Grok API Key",openrouterApiKey:"OpenRouter API Key",telegramEnabled:"Telegram",telegramToken:"Telegram Token",telegramApiRoot:"API Root (Optional)",telegramAllowFrom:"Allow From (Optional)",telegramDebug:"Debug Mode",whatsappEnabled:"WhatsApp",whatsappBridgeUrl:"Bridge URL",whatsappAllowFrom:"Allow From (Optional)",heartbeatEnabled:"Heartbeat",heartbeatIntervalMs:"Heartbeat Interval (ms)"},descriptionsFields:{model:"Default AI model to use",workspace:"Working directory for agent files",maxTokens:"Maximum tokens in response",temperature:"Randomness in responses (0-2)",maxToolIterations:"Maximum tool calls per message",openaiApiKey:"API key for OpenAI models",anthropicApiKey:"API key for Claude models",googleApiKey:"API key for Gemini models",qwenApiKey:"API key for Qwen models",kimiApiKey:"API key for Kimi models",minimaxApiKey:"API key for MiniMax models",deepseekApiKey:"API key for DeepSeek models",grokApiKey:"API key for Grok models",openrouterApiKey:"API key for OpenRouter models",telegramEnabled:"Enable Telegram bot",telegramToken:"Bot API token from @BotFather",telegramApiRoot:"Custom Telegram API root URL",telegramAllowFrom:"Allowed user IDs, comma separated",telegramDebug:"Enable debug logging for Telegram",whatsappEnabled:"Enable WhatsApp bridge",whatsappBridgeUrl:"WhatsApp bridge WebSocket URL",whatsappAllowFrom:"Allowed phone numbers, comma separated",heartbeatEnabled:"Enable heartbeat monitoring",heartbeatIntervalMs:"Heartbeat check interval in milliseconds"},placeholders:{workspace:"~/.xopcbot/workspace",openaiApiKey:"sk-...",anthropicApiKey:"sk-ant-...",googleApiKey:"AIzaSy...",qwenApiKey:"sk-...",kimiApiKey:"sk-kimi-...",minimaxApiKey:"sk-cp-...",deepseekApiKey:"sk-...",openrouterApiKey:"sk-or-...",telegramToken:"1234567890:ABCdefGHIjklMNOpqrsTUVwxyz",telegramApiRoot:"https://api.telegram.org",telegramAllowFrom:"123456789, 987654321",whatsappBridgeUrl:"ws://localhost:3001",whatsappAllowFrom:"+1234567890, +0987654321"},connection:{title:"Connection",gatewayUrl:"Gateway URL",gatewayUrlDesc:"WebSocket URL for the gateway server",authToken:"Auth Token",authTokenDesc:"Optional authentication token"},appearance:{title:"Appearance",theme:"Theme",themeDesc:"Choose your preferred color scheme",themeSystem:"System",themeLight:"Light",themeDark:"Dark"},chat:{title:"Chat",enableAttachments:"Enable Attachments",enableAttachmentsDesc:"Allow file attachments in chat",showModelSelector:"Show Model Selector",showModelSelectorDesc:"Display model selection dropdown",showThinkingSelector:"Show Thinking Selector",showThinkingSelectorDesc:"Display thinking level selection"}},ts={noSession:"No session available",noAgent:"No agent set",noModel:"No model set",requestTimeout:"Request timeout",sendFailed:"Failed to send message",invalidFileType:"Invalid file type",fileTooLarge:"File too large (max {{size}})",readFileFailed:"Failed to read file"},ss={dropHere:"Drop files here",dragDrop:"Drag and drop files here",image:"Image",document:"Document",pdf:"PDF",word:"Word",excel:"Excel",powerpoint:"PowerPoint",text:"Text",code:"Code",archive:"Archive",unknown:"Unknown"},is={settings:"Open settings"},ns={title:"Configuration",save:"Save Configuration",noResult:"No result",artifacts:"Artifacts",showArtifacts:"Show artifacts"},os={title:"Logs",refresh:"Refresh",clear:"Clear",totalLogs:"Total Logs",pause:"Pause",autoRefresh:"Auto Refresh",level:"Level",search:"Search",searchPlaceholder:"Search logs...",time:"Time",message:"Message",module:"Module",noLogs:"No logs found",noLogsDescription:"Try adjusting your filters or check back later.",details:"Log Details"},rs={title:"Sessions",newSession:"New Session",searchPlaceholder:"Search sessions...",totalSessions:"Total Sessions",activeSessions:"Active Sessions",pinnedSessions:"Pinned Sessions",archivedSessions:"Archived Sessions",noSessions:"No sessions",delete:"Delete",archive:"Archive",pin:"Pin",unpin:"Unpin",confirmDelete:"Are you sure you want to delete this session?"},as={title:"Cron Jobs",addJob:"Add Cron Job",editJob:"Edit Job",name:"Name (optional)",namePlaceholder:"My scheduled task",schedule:"Schedule (cron expression) *",scheduleHint:"e.g., */5 * * * * (every 5 minutes), 0 9 * * * (daily at 9am)",message:"Message *",messagePlaceholder:"What should the assistant do?",create:"Create Job",runNow:"Run Now",delete:"Delete",edit:"Edit",enable:"Enable",disable:"Disable",enabled:"Enabled",disabled:"Disabled",running:"Running",lastRun:"Last Run",nextRun:"Next Run",status:"Status",history:"History",actions:"Actions",noJobs:"No cron jobs",confirmDelete:"Are you sure you want to delete this cron job?",confirmRun:"Run this cron job now?",success:"Success",failed:"Failed",scheduleLabel:"Schedule",messageLabel:"Message",confirm:"Confirm",cancel:"Cancel",total:"Total",schedulePresets:{custom:"-- Custom (enter below) --",everyMinute:"Every minute",every5Minutes:"Every 5 minutes (default)",every10Minutes:"Every 10 minutes",every15Minutes:"Every 15 minutes",every30Minutes:"Every 30 minutes",everyHour:"Every hour",every2Hours:"Every 2 hours",every4Hours:"Every 4 hours",every6Hours:"Every 6 hours",every12Hours:"Every 12 hours",everyDayMidnight:"Every day at midnight",everyDay9AM:"Every day at 9:00 AM",everyDay9PM:"Every day at 9:00 PM"},scheduleHintPreset:"Select a preset or enter custom cron expression",mode:"Mode",modeDirect:"Send message directly to the channel without AI processing",modeAgent:"Use AI agent to process the message, then send the response",modeDirectOption:"Direct (send message directly)",modeAgentOption:"AI Agent (process with AI then send)",model:"Model",noConfiguredModels:"No configured models",save:"Save",failedToLoadJobs:"Failed to load jobs",scheduleRequired:"Schedule and message are required",chatIdRequired:"Chat ID is required",failedToJob:"Failed to {{mode}} job",failedToToggleJob:"Failed to toggle job",actionFailed:"Action failed",enterManuallyOrSelect:"Enter manually or select from recent chats",noRecentChats:"No recent chats found. Enter chat ID manually (e.g., 123456789 for Telegram)",timeLabels:{lessThanMinute:"Less than a minute",minutes:"{{count}} min",hours:"{{count}} hours",overdue:"Overdue"},lastActiveLabels:{justNow:"just now",minutesAgo:"{{count}}m ago",hoursAgo:"{{count}}h ago",daysAgo:"{{count}}d ago"}},ls={save:"Save",cancel:"Cancel",confirm:"Confirm",close:"Close",loading:"Loading...",error:"Error",success:"Success",noData:"No data"},cs={app:Xt,nav:Zt,chat:Yt,settings:es,errors:ts,fileUpload:ss,shortcuts:is,config:ns,logs:os,sessions:rs,cron:as,common:ls},hs={title:"XOPCBOT 网关",brand:"XOPCBOT"},ds={chat:"对话",sessions:"会话",cron:"定时任务",logs:"日志",settings:"设置",management:"管理"},ps={title:"XopcBot",newSession:"新建对话",welcomeTitle:"欢迎使用 xopcbot",welcomeDescription:"发送消息开始对话",emptyState:"暂无消息",emptyStateDescription:"在下方输入消息开始对话",you:"你",assistant:"助手",tool:"工具",thinking:"思考中...",typeMessage:"输入消息...",attachFile:"附加文件",sendMessage:"发送消息",abort:"中止",retry:"重试",reasoning:"推理",thinkingLevelNone:"无",thinkingLevel1:"级别 1",thinkingLevel2:"级别 2",thinkingLevel3:"级别 3",thinkingLevel4:"级别 4",connecting:"连接中...",disconnected:"已断开",connectionError:"连接错误",reconnecting:"重新连接中...",online:"在线",offline:"离线"},us={title:"设置",save:"保存",cancel:"取消",close:"关闭",loading:"加载设置中...",unsaved:"{{count}} 个未保存",saveChanges:"保存更改",saving:"保存中...",noSection:"未选择部分",enableFeature:"启用此功能",required:"{{field}} 为必填项",invalidFormat:"格式无效",unsavedChanges:"未保存的更改",sections:{agent:"代理",providers:"提供商",channels:"渠道",gateway:"网关"},descriptions:{agent:"配置代理设置",providers:"配置提供商 API 密钥",channels:"配置消息渠道",gateway:"配置网关设置"},fields:{model:"模型",workspace:"工作区",maxTokens:"最大 Token 数",temperature:"温度",maxToolIterations:"最大工具调用次数",openaiApiKey:"OpenAI API 密钥",anthropicApiKey:"Anthropic API 密钥",googleApiKey:"Google API 密钥",qwenApiKey:"Qwen API 密钥",kimiApiKey:"Kimi API 密钥",minimaxApiKey:"MiniMax API 密钥",deepseekApiKey:"DeepSeek API 密钥",grokApiKey:"Grok API 密钥",openrouterApiKey:"OpenRouter API 密钥",telegramEnabled:"Telegram",telegramToken:"Telegram 令牌",telegramApiRoot:"API 根地址(可选)",telegramAllowFrom:"允许来源(可选)",telegramDebug:"调试模式",whatsappEnabled:"WhatsApp",whatsappBridgeUrl:"桥接地址",whatsappAllowFrom:"允许来源(可选)",heartbeatEnabled:"心跳",heartbeatIntervalMs:"心跳间隔(毫秒)"},descriptionsFields:{model:"默认使用的 AI 模型",workspace:"代理文件的工作目录",maxTokens:"响应中的最大 token 数",temperature:"响应随机性(0-2)",maxToolIterations:"每条消息的最大工具调用次数",openaiApiKey:"OpenAI 模型的 API 密钥",anthropicApiKey:"Claude 模型的 API 密钥",googleApiKey:"Gemini 模型的 API 密钥",qwenApiKey:"Qwen 模型的 API 密钥",kimiApiKey:"Kimi 模型的 API 密钥",minimaxApiKey:"MiniMax 模型的 API 密钥",deepseekApiKey:"DeepSeek 模型的 API 密钥",grokApiKey:"Grok 模型的 API 密钥",openrouterApiKey:"OpenRouter 模型的 API 密钥",telegramEnabled:"启用 Telegram 机器人",telegramToken:"@BotFather 获取的机器人 API 令牌",telegramApiRoot:"自定义 Telegram API 根地址",telegramAllowFrom:"允许的用户 ID,逗号分隔",telegramDebug:"启用 Telegram 调试日志",whatsappEnabled:"启用 WhatsApp 桥接",whatsappBridgeUrl:"WhatsApp 桥接 WebSocket 地址",whatsappAllowFrom:"允许的电话号码,逗号分隔",heartbeatEnabled:"启用心跳监控",heartbeatIntervalMs:"心跳检查间隔(毫秒)"},placeholders:{workspace:"~/.xopcbot/workspace",openaiApiKey:"sk-...",anthropicApiKey:"sk-ant-...",googleApiKey:"AIzaSy...",qwenApiKey:"sk-...",kimiApiKey:"sk-kimi-...",minimaxApiKey:"sk-cp-...",deepseekApiKey:"sk-...",openrouterApiKey:"sk-or-...",telegramToken:"1234567890:ABCdefGHIjklMNOpqrsTUVwxyz",telegramApiRoot:"https://api.telegram.org",telegramAllowFrom:"123456789, 987654321",whatsappBridgeUrl:"ws://localhost:3001",whatsappAllowFrom:"+1234567890, +0987654321"},connection:{title:"连接",gatewayUrl:"网关地址",gatewayUrlDesc:"网关服务器的 WebSocket 地址",authToken:"认证令牌",authTokenDesc:"可选的认证令牌"},appearance:{title:"外观",theme:"主题",themeDesc:"选择你喜欢的配色方案",themeSystem:"跟随系统",themeLight:"浅色",themeDark:"深色"},chat:{title:"对话",enableAttachments:"启用附件",enableAttachmentsDesc:"允许在对话中附加文件",showModelSelector:"显示模型选择器",showModelSelectorDesc:"显示模型选择下拉框",showThinkingSelector:"显示思考选择器",showThinkingSelectorDesc:"显示思考级别选择"}},gs={noSession:"无可用会话",noAgent:"未设置代理",noModel:"未设置模型",requestTimeout:"请求超时",sendFailed:"发送消息失败",invalidFileType:"无效的文件类型",fileTooLarge:"文件过大(最大 {{size}})",readFileFailed:"读取文件失败"},ms={dropHere:"拖放文件到此处",dragDrop:"拖放文件到此处",image:"图片",document:"文档",pdf:"PDF",word:"Word",excel:"Excel",powerpoint:"PowerPoint",text:"文本",code:"代码",archive:"压缩包",unknown:"未知"},_s={settings:"打开设置"},vs={title:"配置",save:"保存配置",noResult:"无结果",artifacts:"产物",showArtifacts:"显示产物"},fs={title:"日志",refresh:"刷新",clear:"清空",totalLogs:"总日志数",pause:"暂停",autoRefresh:"自动刷新",level:"级别",search:"搜索",searchPlaceholder:"搜索日志...",time:"时间",message:"消息",module:"模块",noLogs:"暂无日志",noLogsDescription:"尝试调整筛选条件或稍后再查看。",details:"日志详情"},ys={title:"会话",newSession:"新建会话",searchPlaceholder:"搜索会话...",totalSessions:"总会话数",activeSessions:"活跃会话",pinnedSessions:"固定会话",archivedSessions:"归档会话",noSessions:"暂无会话",delete:"删除",archive:"归档",pin:"固定",unpin:"取消固定",confirmDelete:"确定要删除此会话吗?"},ws={title:"定时任务",addJob:"添加定时任务",editJob:"编辑任务",name:"名称(可选)",namePlaceholder:"我的定时任务",schedule:"计划表达式 *",scheduleHint:"例如:*/5 * * * *(每5分钟),0 9 * * *(每天9点)",message:"消息 *",messagePlaceholder:"助手应该做什么?",create:"创建任务",runNow:"立即执行",delete:"删除",edit:"编辑",enable:"启用",disable:"禁用",enabled:"已启用",disabled:"已禁用",running:"运行中",lastRun:"上次执行",nextRun:"下次执行",status:"状态",history:"历史记录",actions:"操作",noJobs:"暂无定时任务",confirmDelete:"确定要删除此定时任务吗?",confirmRun:"立即执行此定时任务?",success:"成功",failed:"失败",scheduleLabel:"计划",messageLabel:"消息",confirm:"确认",cancel:"取消",total:"总计",schedulePresets:{custom:"-- 自定义(在下方输入) --",everyMinute:"每分钟",every5Minutes:"每 5 分钟(默认)",every10Minutes:"每 10 分钟",every15Minutes:"每 15 分钟",every30Minutes:"每 30 分钟",everyHour:"每小时",every2Hours:"每 2 小时",every4Hours:"每 4 小时",every6Hours:"每 6 小时",every12Hours:"每 12 小时",everyDayMidnight:"每天午夜",everyDay9AM:"每天早上 9 点",everyDay9PM:"每天晚上 9 点"},scheduleHintPreset:"选择预设或输入自定义 cron 表达式",mode:"模式",modeDirect:"直接发送消息到渠道,不经过 AI 处理",modeAgent:"使用 AI 代理处理消息,然后发送回复",modeDirectOption:"直接发送(直接发送到渠道)",modeAgentOption:"AI 代理(经过 AI 处理后发送)",model:"模型",noConfiguredModels:"未配置模型",save:"保存",failedToLoadJobs:"加载任务失败",scheduleRequired:"计划表达式和消息为必填项",chatIdRequired:"Chat ID 为必填项",failedToJob:"{{mode}} 任务失败",failedToToggleJob:"切换任务状态失败",actionFailed:"操作失败",enterManuallyOrSelect:"手动输入或从最近聊天中选择",noRecentChats:"未找到最近聊天。请手动输入 chat ID(例如:Telegram 为 123456789)",timeLabels:{lessThanMinute:"不到 1 分钟",minutes:"{{count}} 分钟",hours:"{{count}} 小时",overdue:"已过期"},lastActiveLabels:{justNow:"刚刚",minutesAgo:"{{count}} 分钟前",hoursAgo:"{{count}} 小时前",daysAgo:"{{count}} 天前"}},bs={save:"保存",cancel:"取消",confirm:"确认",close:"关闭",loading:"加载中...",error:"错误",success:"成功",noData:"暂无数据"},$s={app:hs,nav:ds,chat:ps,settings:us,errors:gs,fileUpload:ms,shortcuts:_s,config:vs,logs:fs,sessions:ys,cron:ws,common:bs},pt={en:cs,zh:$s},K=new Map;K.set("en",pt.en);K.set("zh",pt.zh);let q="en";function a(e,t){const s=K.get(q);if(!s)return e;const i=e.split(".");let n=s;for(const r of i)if(n&&typeof n=="object"&&r in n)n=n[r];else{const l=K.get("en");if(l&&q!=="en"){let h=l;for(const d of i)if(h&&typeof h=="object"&&d in h)h=h[d];else return e;n=h}else return e}return typeof n!="string"?e:t?n.replace(/\{\{(\w+)\}\}/g,(r,l)=>{const h=t[l];return h!==void 0?String(h):`{{${l}}}`}):n}async function xs(e){if(K.has(e)){q=e;return}try{const t=await fetch(`/src/i18n/${e}.json`);if(!t.ok)throw new Error(`Failed to load ${e} translations`);const s=await t.json();K.set(e,s),q=e,window.dispatchEvent(new CustomEvent("languagechange",{detail:{language:e}}))}catch(t){console.error(`Failed to load ${e} translations:`,t),e!=="en"&&K.has("en")&&(q="en")}}function tt(e){K.has(e)?(q=e,window.dispatchEvent(new CustomEvent("languagechange",{detail:{language:e}}))):xs(e)}function Ss(e="en"){q=e}const ks={"Type a message...":"chat.typeMessage","Attach file":"chat.attachFile","Send message":"chat.sendMessage",Abort:"chat.abort","No session available":"errors.noSession","No agent set":"errors.noAgent",Configuration:"config.title",Cancel:"settings.cancel",Save:"settings.save","No result":"config.noResult",Artifacts:"config.artifacts","Show artifacts":"config.showArtifacts"};function te(e){const t=ks[e];return a(t||e)}var As=Object.defineProperty,Cs=Object.getOwnPropertyDescriptor,T=(e,t,s,i)=>{for(var n=i>1?void 0:i?Cs(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&As(t,s,n),n};function le(e,t=""){if(!e||!Array.isArray(e))return"";const[s,i,n]=e,r=Object.entries(i||{}).map(([d,g])=>`${d}="${g}"`).join(" "),l=Array.isArray(n)?n.map(d=>{if(Array.isArray(d)){const[g,S]=d,f=Object.entries(S||{}).map(([E,L])=>`${E}="${L}"`).join(" ");return`<${g} ${f} />`}return""}).join(""):"";return`<svg ${t?`${r} class="${t}"`:r}>${l}</svg>`}let M=class extends y{constructor(){super(...arguments),this.value="",this.attachments=[],this.isStreaming=!1,this.showAttachmentButton=!0,this.showModelSelector=!0,this._isComposing=!1,this._isDragging=!1,this._processingFiles=!1,this._isSending=!1,this.textareaRef=Ye(),this.fileInputRef=Ye(),this.maxFileSize=20*1024*1024,this.acceptedTypes="image/*,application/pdf,.docx,.pptx,.xlsx,.xls,.txt,.md,.json,.xml,.html,.css,.js,.ts,.jsx,.tsx,.yml,.yaml,.zip",this._handleDocumentDragOver=e=>{e.dataTransfer?.types.includes("Files")&&(e.preventDefault(),this._isDragging=!0)},this._handleDocumentDragLeave=e=>{e.relatedTarget===null&&(this._isDragging=!1)},this._handleDocumentDrop=async e=>{e.preventDefault(),this._isDragging=!1;const t=e.dataTransfer?.files;t&&t.length>0&&await this._processFiles(Array.from(t))},this._handleInput=e=>{const t=e.target;this.value=t.value,this._adjustTextareaHeight()},this._handleKeydown=e=>{e.key==="Enter"&&!e.shiftKey&&!this._isComposing&&(e.preventDefault(),this._send())},this._handlePaste=async e=>{const t=e.clipboardData?.items;if(!t)return;const s=[];for(const i of Array.from(t))if(i.type.startsWith("image/")){const n=i.getAsFile();n&&s.push(n)}s.length>0&&(e.preventDefault(),await this._processFiles(s))},this._handleFileInputChange=async e=>{const t=e.target,s=t.files;s&&(await this._processFiles(Array.from(s)),t.value="")}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),document.addEventListener("dragover",this._handleDocumentDragOver),document.addEventListener("drop",this._handleDocumentDrop),document.addEventListener("dragleave",this._handleDocumentDragLeave),document.addEventListener("click",this._handleOutsideClick)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("dragover",this._handleDocumentDragOver),document.removeEventListener("drop",this._handleDocumentDrop),document.removeEventListener("dragleave",this._handleDocumentDragLeave),document.removeEventListener("click",this._handleOutsideClick)}render(){return o`
4
+ <div class="editor-container">
5
+ ${this.attachments.length>0?this._renderAttachments():""}
6
+
7
+ <div class="input-row ${this._isDragging?"dragging":""}">
8
+ ${this.showAttachmentButton?this._renderAttachmentButton():""}
9
+
10
+ <textarea
11
+ ${et(this.textareaRef)}
12
+ class="text-input"
13
+ placeholder=${te("Type a message...")}
14
+ .value=${this.value}
15
+ @input=${this._handleInput}
16
+ @keydown=${this._handleKeydown}
17
+ @compositionstart=${()=>this._isComposing=!0}
18
+ @compositionend=${()=>this._isComposing=!1}
19
+ @paste=${this._handlePaste}
20
+ rows="1"
21
+ ></textarea>
22
+
23
+ <div class="input-actions">
24
+ ${this._renderSendButton()}
25
+ </div>
26
+ </div>
27
+
28
+ ${this._isDragging?this._renderDropOverlay():""}
29
+ </div>
30
+ `}_renderAttachments(){return o`
31
+ <div class="attachments-row">
32
+ ${this.attachments.map((e,t)=>o`
33
+ <div class="attachment-chip">
34
+ <div class="attachment-preview">
35
+ ${e.mimeType.startsWith("image/")?o`
36
+ <img src="${e.content}" alt="${e.name}" />
37
+ `:o`
38
+ ${ae(le(FileText,"w-4 h-4"))}
39
+ `}
40
+ </div>
41
+ <span class="attachment-name">${e.name}</span>
42
+ <button type="button" class="attachment-remove" @click=${()=>this._removeAttachment(t)}>
43
+ ${ae(le(Qt,"w-3 h-3"))}
44
+ </button>
45
+ </div>
46
+ `)}
47
+ </div>
48
+ `}_renderAttachmentButton(){return o`
49
+ <button type="button" class="attach-btn" @click=${()=>this._triggerFileSelect("all")} title=${te("Attach file")}>
50
+ ${ae(le(Gt,"w-4 h-4"))}
51
+ </button>
52
+
53
+ <input
54
+ ${et(this.fileInputRef)}
55
+ type="file"
56
+ multiple
57
+ accept=${this.acceptedTypes}
58
+ class="hidden"
59
+ @change=${this._handleFileInputChange}
60
+ />
61
+ `}_renderSendButton(){const e=this.value.trim()||this.attachments.length>0;return this.isStreaming?o`
62
+ <button type="button" class="stop-btn" @click=${()=>this.onAbort?.()} title=${te("Abort")}>
63
+ ${ae(le(Vt,"w-4 h-4"))}
64
+ </button>
65
+ `:o`
66
+ <button
67
+ type="button"
68
+ class="send-btn ${e?"active":""}"
69
+ ?disabled=${!e}
70
+ @click=${this._send}
71
+ title=${te("Send message")}
72
+ >
73
+ ${ae(le(Wt,"w-4 h-4"))}
74
+ </button>
75
+ `}_renderDropOverlay(){return o`
76
+ <div class="drop-overlay">
77
+ <span>Drop files here to attach</span>
78
+ </div>
79
+ `}_triggerFileSelect(e){let t=this.fileInputRef.value;if(t||(t=this.querySelector('input[type="file"]')),!t){console.warn("File input not found");return}e==="image"?t.accept="image/*":e==="document"?t.accept=".pdf,.docx,.pptx,.xlsx,.xls,.txt,.md,.json,.xml,.html,.css,.js,.ts,.jsx,.tsx,.yml,.yaml,.zip":t.accept=this.acceptedTypes,t.click()}_adjustTextareaHeight(){const e=this.textareaRef.value;e&&(e.style.height="auto",e.style.height=Math.min(e.scrollHeight,200)+"px")}_send(){if(this._isSending||this.isStreaming||!this.value.trim()&&this.attachments.length===0)return;this._isSending=!0;const e=[...this.attachments];this.onSend?.(this.value,e),this.value="",this.attachments=[],requestAnimationFrame(()=>{this._adjustTextareaHeight(),setTimeout(()=>{this._isSending=!1},500)})}async _processFiles(e){this._processingFiles=!0;try{for(const t of e){if(t.size>this.maxFileSize){console.warn(`File ${t.name} exceeds max size of ${this.maxFileSize} bytes`);continue}const s=await this._loadAttachment(t);this.attachments=[...this.attachments,s]}}finally{this._processingFiles=!1}}async _loadAttachment(e){const t=await this._readFileAsBase64(e),s=e.type.startsWith("image/");return{id:crypto.randomUUID(),name:e.name,type:s?"image":"document",mimeType:e.type,size:e.size,content:t}}_readFileAsBase64(e){return new Promise((t,s)=>{const i=new FileReader;i.onload=()=>t(i.result),i.onerror=()=>s(i.error),i.readAsDataURL(e)})}_removeAttachment(e){this.attachments=this.attachments.filter((t,s)=>s!==e)}_formatFileSize(e){const t=["B","KB","MB","GB"];let s=0,i=e;for(;i>=1024&&s<t.length-1;)i/=1024,s++;return`${i.toFixed(1)} ${t[s]}`}};T([ie("textarea")],M.prototype,"textarea",2);T([u({type:String})],M.prototype,"value",2);T([u({type:Array})],M.prototype,"attachments",2);T([u({type:Boolean})],M.prototype,"isStreaming",2);T([u({type:Boolean})],M.prototype,"showAttachmentButton",2);T([u({type:Boolean})],M.prototype,"showModelSelector",2);T([u({attribute:!1})],M.prototype,"currentModel",2);T([u({attribute:!1})],M.prototype,"onSend",2);T([u({attribute:!1})],M.prototype,"onAbort",2);T([u({attribute:!1})],M.prototype,"onModelSelect",2);T([c()],M.prototype,"_isComposing",2);T([c()],M.prototype,"_isDragging",2);T([c()],M.prototype,"_processingFiles",2);T([c()],M.prototype,"_isSending",2);M=T([k("message-editor")],M);function p(e){return Fe[e]||Fe.helpCircle}const Fe={messageSquare:o`
80
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
81
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
82
+ </svg>
83
+ `,settings:o`
84
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
85
+ <circle cx="12" cy="12" r="3"></circle>
86
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
87
+ </svg>
88
+ `,menu:o`
89
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
90
+ <line x1="3" y1="12" x2="21" y2="12"></line>
91
+ <line x1="3" y1="6" x2="21" y2="6"></line>
92
+ <line x1="3" y1="18" x2="21" y2="18"></line>
93
+ </svg>
94
+ `,chevronDown:o`
95
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
96
+ <polyline points="6 9 12 15 18 9"></polyline>
97
+ </svg>
98
+ `,sun:o`
99
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
100
+ <circle cx="12" cy="12" r="5"></circle>
101
+ <line x1="12" y1="1" x2="12" y2="3"></line>
102
+ <line x1="12" y1="21" x2="12" y2="23"></line>
103
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
104
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
105
+ <line x1="1" y1="12" x2="3" y2="12"></line>
106
+ <line x1="21" y1="12" x2="23" y2="12"></line>
107
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
108
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
109
+ </svg>
110
+ `,moon:o`
111
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
112
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
113
+ </svg>
114
+ `,monitor:o`
115
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
116
+ <rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
117
+ <line x1="8" y1="21" x2="16" y2="21"></line>
118
+ <line x1="12" y1="17" x2="12" y2="21"></line>
119
+ </svg>
120
+ `,send:o`
121
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
122
+ <line x1="22" y1="2" x2="11" y2="13"></line>
123
+ <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
124
+ </svg>
125
+ `,paperclip:o`
126
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
127
+ <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
128
+ </svg>
129
+ `,x:o`
130
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
131
+ <line x1="18" y1="6" x2="6" y2="18"></line>
132
+ <line x1="6" y1="6" x2="18" y2="18"></line>
133
+ </svg>
134
+ `,fileText:o`
135
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
136
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
137
+ <polyline points="14 2 14 8 20 8"></polyline>
138
+ <line x1="16" y1="13" x2="8" y2="13"></line>
139
+ <line x1="16" y1="17" x2="8" y2="17"></line>
140
+ <polyline points="10 9 9 9 8 9"></polyline>
141
+ </svg>
142
+ `,image:o`
143
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
144
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
145
+ <circle cx="8.5" cy="8.5" r="1.5"></circle>
146
+ <polyline points="21 15 16 10 5 21"></polyline>
147
+ </svg>
148
+ `,file:o`
149
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
150
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
151
+ <polyline points="14 2 14 8 20 8"></polyline>
152
+ </svg>
153
+ `,plug:o`
154
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
155
+ <path d="M12 22v-5"></path>
156
+ <path d="M15 8V2"></path>
157
+ <path d="M9 8V2"></path>
158
+ <path d="M15 8a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3v-5a3 3 0 0 1 3-3h6z"></path>
159
+ </svg>
160
+ `,palette:o`
161
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
162
+ <circle cx="13.5" cy="6.5" r=".5"></circle>
163
+ <circle cx="17.5" cy="10.5" r=".5"></circle>
164
+ <circle cx="8.5" cy="7.5" r=".5"></circle>
165
+ <circle cx="6.5" cy="12.5" r=".5"></circle>
166
+ <path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.01 17.461 2 12 2z"></path>
167
+ </svg>
168
+ `,alertCircle:o`
169
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
170
+ <circle cx="12" cy="12" r="10"></circle>
171
+ <line x1="12" y1="8" x2="12" y2="12"></line>
172
+ <line x1="12" y1="16" x2="12.01" y2="16"></line>
173
+ </svg>
174
+ `,check:o`
175
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
176
+ <polyline points="20 6 9 17 4 12"></polyline>
177
+ </svg>
178
+ `,chevronRight:o`
179
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
180
+ <polyline points="9 18 15 12 9 6"></polyline>
181
+ </svg>
182
+ `,arrowLeft:o`
183
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
184
+ <line x1="19" y1="12" x2="5" y2="12"></line>
185
+ <polyline points="12 19 5 12 12 5"></polyline>
186
+ </svg>
187
+ `,bot:o`
188
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
189
+ <rect x="3" y="11" width="18" height="10" rx="2"></rect>
190
+ <circle cx="12" cy="5" r="2"></circle>
191
+ <path d="M12 7v4"></path>
192
+ <line x1="8" y1="16" x2="8" y2="16.01"></line>
193
+ <line x1="16" y1="16" x2="16" y2="16.01"></line>
194
+ </svg>
195
+ `,helpCircle:o`
196
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
197
+ <circle cx="12" cy="12" r="10"></circle>
198
+ <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path>
199
+ <line x1="12" y1="17" x2="12.01" y2="17"></line>
200
+ </svg>
201
+ `,rotateCcw:o`
202
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
203
+ <polyline points="1 4 1 10 7 10"></polyline>
204
+ <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path>
205
+ </svg>
206
+ `,square:o`
207
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
208
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
209
+ </svg>
210
+ `,moreHorizontal:o`
211
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
212
+ <circle cx="12" cy="12" r="1"></circle>
213
+ <circle cx="19" cy="12" r="1"></circle>
214
+ <circle cx="5" cy="12" r="1"></circle>
215
+ </svg>
216
+ `,copy:o`
217
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
218
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
219
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
220
+ </svg>
221
+ `,download:o`
222
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
223
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
224
+ <polyline points="7 10 12 15 17 10"></polyline>
225
+ <line x1="12" y1="15" x2="12" y2="3"></line>
226
+ </svg>
227
+ `,folderOpen:o`
228
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
229
+ <path d="M6 17h12a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3.5"></path>
230
+ <path d="M2 17V5a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v1"></path>
231
+ </svg>
232
+ `,phone:o`
233
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
234
+ <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
235
+ </svg>
236
+ `,globe:o`
237
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
238
+ <circle cx="12" cy="12" r="10"></circle>
239
+ <line x1="2" y1="12" x2="22" y2="12"></line>
240
+ <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
241
+ </svg>
242
+ `,terminal:o`
243
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
244
+ <polyline points="4 17 10 11 4 5"></polyline>
245
+ <line x1="12" y1="19" x2="20" y2="19"></line>
246
+ </svg>
247
+ `,zap:o`
248
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
249
+ <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
250
+ </svg>
251
+ `,pin:o`
252
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
253
+ <line x1="12" y1="17" x2="12" y2="22"></line>
254
+ <path d="M5 17h14v-3a2 2 0 0 0-2-2h-3.5"></path>
255
+ <path d="M5 12V7a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v5"></path>
256
+ <circle cx="12" cy="7" r="1"></circle>
257
+ </svg>
258
+ `,pinOff:o`
259
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
260
+ <line x1="2" y1="2" x2="22" y2="22"></line>
261
+ <line x1="12" y1="17" x2="12" y2="22"></line>
262
+ <path d="M5 17h14v-3a2 2 0 0 0-2-2h-3.5"></path>
263
+ <path d="M5 12V7a2 2 0 0 1 2-2h1"></path>
264
+ </svg>
265
+ `,archive:o`
266
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
267
+ <polyline points="21 8 21 21 3 21 3 8"></polyline>
268
+ <rect x="1" y="3" width="22" height="5"></rect>
269
+ <line x1="10" y1="12" x2="14" y2="12"></line>
270
+ </svg>
271
+ `,archiveRestore:o`
272
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
273
+ <polyline points="21 8 21 21 3 21 3 8"></polyline>
274
+ <rect x="1" y="3" width="22" height="5"></rect>
275
+ <polyline points="10 12 14 12 14 8"></polyline>
276
+ </svg>
277
+ `,trash:o`
278
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
279
+ <polyline points="3 6 5 6 21 6"></polyline>
280
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
281
+ </svg>
282
+ `,grid:o`
283
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
284
+ <rect x="3" y="3" width="7" height="7"></rect>
285
+ <rect x="14" y="3" width="7" height="7"></rect>
286
+ <rect x="14" y="14" width="7" height="7"></rect>
287
+ <rect x="3" y="14" width="7" height="7"></rect>
288
+ </svg>
289
+ `,list:o`
290
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
291
+ <line x1="8" y1="6" x2="21" y2="6"></line>
292
+ <line x1="8" y1="12" x2="21" y2="12"></line>
293
+ <line x1="8" y1="18" x2="21" y2="18"></line>
294
+ <line x1="3" y1="6" x2="3.01" y2="6"></line>
295
+ <line x1="3" y1="12" x2="3.01" y2="12"></line>
296
+ <line x1="3" y1="18" x2="3.01" y2="18"></line>
297
+ </svg>
298
+ `,layers:o`
299
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
300
+ <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
301
+ <polyline points="2 17 12 22 22 17"></polyline>
302
+ <polyline points="2 12 12 17 22 12"></polyline>
303
+ </svg>
304
+ `,circle:o`
305
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
306
+ <circle cx="12" cy="12" r="10"></circle>
307
+ </svg>
308
+ `,search:o`
309
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
310
+ <circle cx="11" cy="11" r="8"></circle>
311
+ <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
312
+ </svg>
313
+ `,chevronUp:o`
314
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
315
+ <polyline points="18 15 12 9 6 15"></polyline>
316
+ </svg>
317
+ `,alertTriangle:o`
318
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
319
+ <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
320
+ <line x1="12" y1="9" x2="12" y2="13"></line>
321
+ <line x1="12" y1="17" x2="12.01" y2="17"></line>
322
+ </svg>
323
+ `,info:o`
324
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
325
+ <circle cx="12" cy="12" r="10"></circle>
326
+ <line x1="12" y1="16" x2="12" y2="12"></line>
327
+ <line x1="12" y1="8" x2="12.01" y2="8"></line>
328
+ </svg>
329
+ `,folder:o`
330
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
331
+ <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
332
+ </svg>
333
+ `,clock:o`
334
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
335
+ <circle cx="12" cy="12" r="10"></circle>
336
+ <polyline points="12 6 12 12 16 14"></polyline>
337
+ </svg>
338
+ `,plus:o`
339
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
340
+ <line x1="12" y1="5" x2="12" y2="19"></line>
341
+ <line x1="5" y1="12" x2="19" y2="12"></line>
342
+ </svg>
343
+ `,refresh:o`
344
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
345
+ <polyline points="23 4 23 10 17 10"></polyline>
346
+ <polyline points="1 20 1 14 7 14"></polyline>
347
+ <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
348
+ </svg>
349
+ `,play:o`
350
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
351
+ <polygon points="5 3 19 12 5 21 5 3"></polygon>
352
+ </svg>
353
+ `,edit:o`
354
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
355
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
356
+ <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
357
+ </svg>
358
+ `,pause:o`
359
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
360
+ <rect x="6" y="4" width="4" height="16"></rect>
361
+ <rect x="14" y="4" width="4" height="16"></rect>
362
+ </svg>
363
+ `,refreshCw:o`
364
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
365
+ <polyline points="23 4 23 10 17 10"></polyline>
366
+ <polyline points="1 20 1 14 7 14"></polyline>
367
+ <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
368
+ </svg>
369
+ `,checkCircle:o`
370
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
371
+ <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
372
+ <polyline points="22 4 12 14.01 9 11.01"></polyline>
373
+ </svg>
374
+ `,xCircle:o`
375
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
376
+ <circle cx="12" cy="12" r="10"></circle>
377
+ <line x1="15" y1="9" x2="9" y2="15"></line>
378
+ <line x1="9" y1="9" x2="15" y2="15"></line>
379
+ </svg>
380
+ `,loader:o`
381
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
382
+ <line x1="12" y1="2" x2="12" y2="6"></line>
383
+ <line x1="12" y1="18" x2="12" y2="22"></line>
384
+ <line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line>
385
+ <line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line>
386
+ <line x1="2" y1="12" x2="6" y2="12"></line>
387
+ <line x1="18" y1="12" x2="22" y2="12"></line>
388
+ <line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line>
389
+ <line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line>
390
+ </svg>
391
+ `,slash:o`
392
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
393
+ <circle cx="12" cy="12" r="10"></circle>
394
+ <line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line>
395
+ </svg>
396
+ `};function Ms(e){return e.includes("pdf")?o`
397
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="2">
398
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
399
+ <polyline points="14,2 14,8 20,8"/>
400
+ </svg>
401
+ `:e.includes("word")||e.includes("document")?o`
402
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2">
403
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
404
+ <polyline points="14,2 14,8 20,8"/>
405
+ </svg>
406
+ `:e.includes("sheet")||e.includes("excel")?o`
407
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#16a34a" stroke-width="2">
408
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
409
+ <polyline points="14,2 14,8 20,8"/>
410
+ </svg>
411
+ `:e.includes("presentation")||e.includes("powerpoint")?o`
412
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2">
413
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
414
+ <polyline points="14,2 14,8 20,8"/>
415
+ </svg>
416
+ `:Fe.file}var Ts=Object.defineProperty,Es=Object.getOwnPropertyDescriptor,ut=(e,t,s,i)=>{for(var n=i>1?void 0:i?Es(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ts(t,s,n),n};let Le=class extends y{constructor(){super(...arguments),this.attachments=[]}createRenderRoot(){return this}render(){if(!this.attachments?.length)return null;const e=this.attachments.filter(s=>s.type==="image"||s.mimeType?.startsWith("image/")),t=this.attachments.filter(s=>s.type!=="image"&&!s.mimeType?.startsWith("image/"));return o`
417
+ <div class="flex flex-col gap-2 mt-2">
418
+ ${e.length>0?this._renderImageGallery(e):""}
419
+ ${t.length>0?this._renderDocumentList(t):""}
420
+ </div>
421
+ `}_renderImageGallery(e){const t=e.length;let s="single";return t===2?s="double":t===3?s="triple":t>=4&&(s="quad"),o`
422
+ <div class="image-gallery ${s}">
423
+ ${e.map(i=>o`
424
+ <img
425
+ src="${i.data||i.content}"
426
+ alt="${i.name||a("fileUpload.image")}"
427
+ @click=${()=>this._handleImageClick(i)}
428
+ />
429
+ `)}
430
+ </div>
431
+ `}_renderDocumentList(e){return o`
432
+ <div class="flex flex-col gap-2">
433
+ ${e.map(t=>this._renderDocumentPreview(t))}
434
+ </div>
435
+ `}_renderDocumentPreview(e){const t=e.name||a("fileUpload.document"),s=e.size?this._formatFileSize(e.size):"";return o`
436
+ <div class="document-preview" @click=${()=>this._handleDocumentClick(e)}>
437
+ <div class="icon">${Ms(e.mimeType||"")}</div>
438
+ <div class="info">
439
+ <div class="name">${t}</div>
440
+ <div class="meta">${s||e.mimeType||a("fileUpload.unknown")}</div>
441
+ </div>
442
+ </div>
443
+ `}_formatFileSize(e){const t=["B","KB","MB","GB"];let s=0,i=e;for(;i>=1024&&s<t.length-1;)i/=1024,s++;return`${i.toFixed(1)} ${t[s]}`}_handleImageClick(e){this.dispatchEvent(new CustomEvent("image-click",{detail:e,bubbles:!0,composed:!0}))}_handleDocumentClick(e){this.dispatchEvent(new CustomEvent("document-click",{detail:e,bubbles:!0,composed:!0}))}};ut([u({attribute:!1})],Le.prototype,"attachments",2);Le=ut([k("attachment-renderer")],Le);var Ps=Object.defineProperty,Fs=Object.getOwnPropertyDescriptor,gt=(e,t,s,i)=>{for(var n=i>1?void 0:i?Fs(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ps(t,s,n),n};let Ie=class extends y{createRenderRoot(){return this}render(){if(!this.usage)return null;const e=[];return this.usage.totalTokens!==void 0?e.push(`${this.usage.totalTokens} tokens`):this.usage.inputTokens!==void 0&&this.usage.outputTokens!==void 0&&e.push(`${this.usage.inputTokens+this.usage.outputTokens} tokens`),this.usage.cost!==void 0&&this.usage.cost>0&&e.push(`$${this.usage.cost.toFixed(4)}`),e.length===0?null:o`
444
+ <span class="usage-badge">
445
+ ${e.join(" · ")}
446
+ </span>
447
+ `}};gt([u({attribute:!1})],Ie.prototype,"usage",2);Ie=gt([k("usage-badge")],Ie);var Ls=Object.defineProperty,Is=Object.getOwnPropertyDescriptor,je=(e,t,s,i)=>{for(var n=i>1?void 0:i?Is(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ls(t,s,n),n};let xe=class extends y{constructor(){super(...arguments),this.isStreaming=!1}createRenderRoot(){return this}render(){const e=this.message.role==="user"||this.message.role==="user-with-attachments",t=this.message.role==="assistant";this.message.role==="tool"||this.message.role;const s=a(e?"chat.you":t?"chat.assistant":"chat.tool"),i=s.charAt(0);return o`
448
+ <div class="message-item ${e?"flex-row-reverse":""}">
449
+ <div class="avatar ${e?"user":t?"assistant":"tool"}">
450
+ ${i}
451
+ </div>
452
+
453
+ <div class="flex flex-col gap-1 max-w-[85%]">
454
+ <div class="flex items-center gap-2 text-xs text-muted">
455
+ <span class="font-medium">${s}</span>
456
+ <span>·</span>
457
+ <span>${this._formatTime(this.message.timestamp)}</span>
458
+ ${this.isStreaming?o`<span class="text-primary animate-pulse">${a("chat.thinking")}</span>`:""}
459
+ </div>
460
+
461
+ <div class="message-bubble ${e?"bg-primary-light":"bg-secondary"}">
462
+ ${this._renderContent(this.message.content)}
463
+ ${this.message.attachments?.length?o`
464
+ <attachment-renderer .attachments=${this.message.attachments}></attachment-renderer>
465
+ `:""}
466
+ </div>
467
+
468
+ ${t&&this.message.usage?o`
469
+ <usage-badge .usage=${this.message.usage}></usage-badge>
470
+ `:""}
471
+ </div>
472
+ </div>
473
+ `}_renderContent(e){return!e||e.length===0?this.isStreaming?o`<span class="streaming-cursor"></span>`:null:o`
474
+ <div class="markdown-content">
475
+ ${e.map(t=>this._renderContentBlock(t))}
476
+ ${this.isStreaming?o`<span class="streaming-cursor"></span>`:""}
477
+ </div>
478
+ `}_renderContentBlock(e){switch(e.type){case"text":if(e.text)return o`<p class="whitespace-pre-wrap">${e.text}</p>`;break;case"image":if(e.source?.data)return o`<img src="${e.source.data}" class="rounded-lg max-w-full" />`;break;case"tool_use":case"tool_result":return this._renderToolCall(e);default:if(e.text)return o`<p class="whitespace-pre-wrap">${e.text}</p>`}return null}_renderToolCall(e){const t=e.is_error||e.error,s=e.name||e.function?.name||"Tool",i=e.input||e.function?.arguments;return o`
479
+ <div class="tool-call ${t?"tool-call--error":""}">
480
+ <div class="tool-call-header">
481
+ <span>🔧 ${s}</span>
482
+ ${t?o`<span class="text-red-500 text-xs">Error</span>`:""}
483
+ </div>
484
+ ${i?o`
485
+ <pre class="tool-call-content">${JSON.stringify(i,null,2)}</pre>
486
+ `:""}
487
+ ${e.content?o`
488
+ <div class="tool-call-result">${JSON.stringify(e.content)}</div>
489
+ `:""}
490
+ </div>
491
+ `}_formatTime(e){return e?new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):""}};je([u({attribute:!1})],xe.prototype,"message",2);je([u({type:Boolean})],xe.prototype,"isStreaming",2);xe=je([k("message-bubble")],xe);var Ds=Object.defineProperty,Os=Object.getOwnPropertyDescriptor,Me=(e,t,s,i)=>{for(var n=i>1?void 0:i?Os(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ds(t,s,n),n};let me=class extends y{constructor(){super(...arguments),this.messages=[],this.isStreaming=!1,this.useVirtualScroll=!1}createRenderRoot(){return this}render(){return!this.messages||this.messages.length===0?this._renderEmptyState():o`
492
+ <div class="flex flex-col gap-4 pb-4">
493
+ ${this.messages.map((e,t)=>o`
494
+ <message-bubble
495
+ .message=${e}
496
+ .isStreaming=${this.isStreaming&&t===this.messages.length-1}
497
+ ></message-bubble>
498
+ `)}
499
+ </div>
500
+ `}_renderEmptyState(){return o`
501
+ <div class="empty-state">
502
+ <div class="icon">💬</div>
503
+ <div class="title">${a("chat.emptyState")}</div>
504
+ <div class="description">${a("chat.emptyStateDescription")}</div>
505
+ </div>
506
+ `}scrollToBottom(){const e=this.closest(".overflow-y-auto");e&&(e.scrollTop=e.scrollHeight)}isNearBottom(e=100){const t=this.closest(".overflow-y-auto");if(!t)return!0;const{scrollTop:s,scrollHeight:i,clientHeight:n}=t;return i-s-n<e}};Me([u({attribute:!1})],me.prototype,"messages",2);Me([u({type:Boolean})],me.prototype,"isStreaming",2);Me([u({type:Boolean})],me.prototype,"useVirtualScroll",2);me=Me([k("message-list")],me);var Rs=Object.defineProperty,Bs=Object.getOwnPropertyDescriptor,ne=(e,t,s,i)=>{for(var n=i>1?void 0:i?Bs(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Rs(t,s,n),n};let W=class extends y{constructor(){super(...arguments),this.tools=new Map,this.pendingToolCalls=new Set,this.isStreaming=!1,this._currentMessage=null,this._isComplete=!1}createRenderRoot(){return this}setMessage(e,t){this._currentMessage=e,this._isComplete=t}render(){return this._currentMessage?o`
507
+ <div class="flex gap-3 message-item">
508
+ <div class="avatar assistant">
509
+ AI
510
+ </div>
511
+
512
+ <div class="flex flex-col gap-1 max-w-[85%]">
513
+ <div class="flex items-center gap-2 text-xs text-muted">
514
+ <span class="font-medium">Assistant</span>
515
+ <span>·</span>
516
+ <span class="text-accent animate-pulse">thinking...</span>
517
+ </div>
518
+
519
+ <div class="rounded-xl p-3 bg-secondary">
520
+ ${this.renderStreamingContent()}
521
+ </div>
522
+ </div>
523
+ </div>
524
+ `:null}renderStreamingContent(){const e=this._currentMessage?.content||[];return o`
525
+ <div class="markdown-content">
526
+ ${e.map(t=>t.type==="text"?o`<p class="whitespace-pre-wrap">${this._escapeHtml(t.text||"")}<span class="streaming-cursor"></span></p>`:t.type==="tool_use"?this.renderToolUse(t):"")}
527
+ ${this.isStreaming&&(!e.length||e[e.length-1]?.type!=="text")?o`<span class="streaming-cursor"></span>`:""}
528
+ </div>
529
+ `}renderToolUse(e){const t=e.name||e.function?.name,s=e.input||e.function?.arguments||{},i=typeof s=="string"?s:JSON.stringify(s,null,2);return o`
530
+ <div class="tool-call">
531
+ <div class="name">
532
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
533
+ <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>
534
+ </svg>
535
+ <span>${t}</span>
536
+ </div>
537
+ <pre class="input">${i}</pre>
538
+ </div>
539
+ `}_escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}};ne([u({attribute:!1})],W.prototype,"tools",2);ne([u({attribute:!1})],W.prototype,"pendingToolCalls",2);ne([u({type:Boolean})],W.prototype,"isStreaming",2);ne([c()],W.prototype,"_currentMessage",2);ne([c()],W.prototype,"_isComplete",2);W=ne([k("streaming-message-container")],W);var Ks=Object.defineProperty,js=Object.getOwnPropertyDescriptor,x=(e,t,s,i)=>{for(var n=i>1?void 0:i?js(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ks(t,s,n),n};function Y(e,t){return`${e.replace(/\/+$/,"")}${t}`}function ce(e){const t={"Content-Type":"application/json"};return e&&(t.Authorization=`Bearer ${e}`),t}let w=class extends y{constructor(){super(...arguments),this.enableAttachments=!0,this.enableModelSelector=!0,this._connectionState="disconnected",this._error=null,this._messages=[],this._isStreaming=!1,this._streamingContent="",this._streamingMessage=null,this._reconnectCount=0,this._isAtBottom=!0,this._currentSessionKey=null,this._sessions=[],this._hasMoreMessages=!0,this._isLoadingMore=!1,this._shouldReconnect=!0,this._isSending=!1,this._lastLoadedSessionKey=null,this._handleScroll=()=>{if(!this._chatMessages)return;const{scrollTop:e,scrollHeight:t,clientHeight:s}=this._chatMessages,i=t-e-s<50;i!==this._isAtBottom&&(this._isAtBottom=i),e<100&&!this._isAtBottom&&this._hasMoreMessages&&!this._isLoadingMore&&this._loadMoreMessages()},this._handleSend=(e,t)=>{const s=t?.map(i=>({type:i.type||"file",mimeType:i.mimeType,data:i.content,name:i.name,size:i.size}));this.sendMessage(e,s)}}get _maxReconnectAttempts(){return this.config?.maxReconnectAttempts??10}get _autoReconnect(){return this.config?.autoReconnect??!0}createRenderRoot(){return this}async connectedCallback(){super.connectedCallback(),this.classList.add("chat-container"),await Ss("en")}firstUpdated(){this._chatMessages&&this._chatMessages.addEventListener("scroll",this._handleScroll),this._handleRouteChange()}updated(e){super.updated(e),e.has("config")&&this.config&&this._connectionState==="disconnected"&&this.connect(),e.has("route")&&this.route&&this._handleRouteChange()}async _handleRouteChange(){const e=this.route;if(!e)return;let t=null;switch(e.type){case"recent":this._lastLoadedSessionKey=null,await this._loadSessions();return;case"session":t=e.sessionKey;break;case"new":await this._createNewSession();return}t&&t!==this._lastLoadedSessionKey&&(await this._loadSession(t,0),this._lastLoadedSessionKey=t)}async _loadSession(e,t=0){if(this.config)try{const s=Y(this.config.url,`/api/sessions/${encodeURIComponent(e)}?offset=${t}&limit=50`),i=ce(this.config.token),n=await fetch(s,{headers:i});if(!n.ok)throw new Error(`HTTP ${n.status}`);const l=(await n.json()).session;this._currentSessionKey=e;const h=l.messages||[],d=h.filter(g=>g.role==="user"||g.role==="assistant").map(g=>({role:g.role,content:typeof g.content=="string"?[{type:"text",text:g.content}]:g.content||[],attachments:g.attachments,timestamp:g.timestamp?new Date(g.timestamp).getTime():Date.now()}));t>0?this._messages=[...d,...this._messages]:this._messages=d,this._hasMoreMessages=h.length>=50,t===0&&this._scrollToBottom(!1),this.requestUpdate()}catch(s){console.error("[GatewayChat] Failed to load session:",s)}}async _loadMoreMessages(){if(!this._currentSessionKey||this._isLoadingMore||!this._hasMoreMessages)return;this._isLoadingMore=!0;const e=this._messages.length;try{await this._loadSession(this._currentSessionKey,e)}finally{this._isLoadingMore=!1}}disconnectedCallback(){super.disconnectedCallback(),this._shouldReconnect=!1,this.disconnect(),this._chatMessages&&this._chatMessages.removeEventListener("scroll",this._handleScroll)}_scrollToBottom(e=!0){this.updateComplete.then(()=>{this._chatMessages&&this._chatMessages.scrollTo({top:this._chatMessages.scrollHeight,behavior:e?"smooth":"auto"})})}connect(){if(!(!this.config||this._connectionState==="connecting")){this._connectionState="connecting",this._error=null,this.requestUpdate();try{const e=Y(this.config.url,"/api/events"),t=new URL(e);this.config.token&&t.searchParams.set("token",this.config.token),this._eventSource=new EventSource(t.toString()),this._eventSource.onopen=()=>{this._connectionState="connected",this._error=null,this._reconnectCount=0,this.requestUpdate(),this._lastLoadedSessionKey||this._loadSessions()},this._eventSource.addEventListener("connected",()=>{this._connectionState="connected",this._error=null,this.requestUpdate()}),this._eventSource.addEventListener("config.reload",s=>{try{const i=JSON.parse(s.data);this.dispatchEvent(new CustomEvent("config-reload",{detail:i}))}catch{}}),this._eventSource.addEventListener("channels.status",s=>{try{const i=JSON.parse(s.data);this.dispatchEvent(new CustomEvent("channels-status",{detail:i}))}catch{}}),this._eventSource.addEventListener("message.sent",s=>{try{const i=JSON.parse(s.data);this.dispatchEvent(new CustomEvent("message-sent",{detail:i}))}catch{}}),this._eventSource.onerror=()=>{this._eventSource?.readyState===EventSource.CLOSED?(this._connectionState="disconnected",this._handlePermanentDisconnect()):this._connectionState="reconnecting",this.requestUpdate()}}catch(e){console.error("[GatewayChat] Failed to create EventSource:",e),this._connectionState="error",this._error=a("errors.connectionError"),this.requestUpdate()}}}_handlePermanentDisconnect(){this._isStreaming&&(this._isStreaming=!1,this._isSending=!1,this._streamingContent="",this._streamingMessage=null),this._shouldReconnect&&this._autoReconnect&&(this._reconnectCount++,this._reconnectCount>this._maxReconnectAttempts&&(this._error=a("errors.connectionError"),this._connectionState="error"))}disconnect(){this._shouldReconnect=!1,this._eventSource?.close(),this._eventSource=void 0,this._agentAbort?.abort(),this._agentAbort=void 0,this._connectionState="disconnected"}reconnect(){this._shouldReconnect=!0,this._reconnectCount=0,this.disconnect(),setTimeout(()=>this.connect(),100)}async _loadSessions(){if(this.config)try{const e=Y(this.config.url,"/api/sessions?limit=20"),t=ce(this.config.token),s=await fetch(e,{headers:t});if(!s.ok)throw new Error(`HTTP ${s.status}`);const r=((await s.json()).items||[]).filter(h=>h.key.startsWith("gateway:")).sort((h,d)=>new Date(d.updatedAt).getTime()-new Date(h.updatedAt).getTime());this._sessions=r;const l=r.filter(h=>h.messageCount>0);if(l.length>0){const h=l[0].key;await this._loadSession(h,0),this._lastLoadedSessionKey=h,this._updateUrlWithSession(h)}else if(r.length>0){const h=r[0];this._currentSessionKey=h.key,this._messages=[],this._lastLoadedSessionKey=h.key,this._updateUrlWithSession(h.key)}else await this._createNewSession()}catch(e){console.error("[GatewayChat] Failed to load sessions:",e)}}_updateUrlWithSession(e){const t=`#/chat/${encodeURIComponent(e)}`;location.hash!==t&&history.replaceState(null,"",t)}async _createNewSession(){if(!this.config)return;const e=this._sessions.find(t=>t.messageCount===0);if(e){this._currentSessionKey=e.key,this._messages=[],this._lastLoadedSessionKey=e.key,this._updateUrlWithSession(e.key);return}try{const t=Y(this.config.url,"/api/sessions"),s={...ce(this.config.token),"Content-Type":"application/json"},i=await fetch(t,{method:"POST",headers:s,body:JSON.stringify({channel:"gateway"})});if(!i.ok)throw new Error(`HTTP ${i.status}`);const r=(await i.json()).session;this._currentSessionKey=r.key,this._messages=[],this._sessions=[{key:r.key,name:r.name,updatedAt:r.updatedAt},...this._sessions],this._currentSessionKey=r.key,this._lastLoadedSessionKey=r.key,this._updateUrlWithSession(r.key),this._scrollToBottom(),this.requestUpdate()}catch(t){console.error("[GatewayChat] Failed to create new session:",t)}}async sendMessage(e,t){if(!(this._isSending||this._isStreaming)&&!(!e.trim()&&!t?.length)&&this.config){this._isSending=!0,this._messages=[...this._messages,{role:"user",content:e?[{type:"text",text:e}]:[],attachments:t,timestamp:Date.now()}],this._scrollToBottom(),this.requestUpdate();try{this._agentAbort=new AbortController;const s=Y(this.config.url,"/api/agent"),i={...ce(this.config.token),Accept:"text/event-stream"},n=this._currentSessionKey?this._currentSessionKey.replace("gateway:",""):"default",r=await fetch(s,{method:"POST",headers:i,body:JSON.stringify({message:e,channel:"gateway",chatId:n,attachments:t}),signal:this._agentAbort.signal});if(!r.ok){const h=await r.json().catch(()=>({}));throw new Error(h.error?.message||`HTTP ${r.status}`)}if((r.headers.get("Content-Type")||"").includes("text/event-stream")&&r.body)await this._consumeSSEStream(r.body);else{const h=await r.json();h.ok&&h.payload?.content&&(this._updateStreamingMessage(h.payload.content),this._finalizeMessage())}}catch(s){if(s.name==="AbortError")return;this._error=s instanceof Error?s.message:a("errors.sendFailed"),this._isStreaming=!1,this._isSending=!1,this._streamingMessage=null,this.requestUpdate()}finally{this._agentAbort=void 0,this._isSending=!1}}}async _consumeSSEStream(e){const t=e.pipeThrough(new TextDecoderStream).getReader();let s="",i="",n="";try{for(;;){const{done:r,value:l}=await t.read();if(r)break;for(s+=l;s.includes(`
540
+ `);){const h=s.indexOf(`
541
+ `),d=s.slice(0,h);s=s.slice(h+1),d.startsWith("event:")?i=d.slice(6).trim():d.startsWith("data:")?n+=(n?`
542
+ `:"")+d.slice(5).trim():d===""&&n&&(this._handleSSEEvent(i||"message",n),i="",n="")}}if(s.trim()||n){if(s.trim()){const r=s.split(`
543
+ `);for(const l of r)l.startsWith("event:")?i=l.slice(6).trim():l.startsWith("data:")?n+=(n?`
544
+ `:"")+l.slice(5).trim():l===""&&n&&(this._handleSSEEvent(i||"message",n),i="",n="")}n&&this._handleSSEEvent(i||"message",n)}}finally{t.releaseLock()}}_handleSSEEvent(e,t){try{const s=JSON.parse(t);switch(e){case"status":this._isStreaming=!0,this.requestUpdate();break;case"token":s.content&&this._updateStreamingMessage(s.content);break;case"error":this._error=s.content||s.error?.message||a("errors.sendFailed"),this._isStreaming=!1,this._isSending=!1,this._streamingMessage=null,this.requestUpdate();break;case"result":this._finalizeMessage();break;default:s.content&&this._updateStreamingMessage(s.content);break}}catch{}}_updateStreamingMessage(e){if(this._streamingMessage){const t=this._streamingMessage.content.find(s=>s.type==="text");t?t.text=(t.text||"")+e:this._streamingMessage.content.push({type:"text",text:e})}else this._streamingMessage={role:"assistant",content:[{type:"text",text:e}],timestamp:Date.now()};this._isStreaming=!0,this._streamingContent=e,this.requestUpdate(),this._isAtBottom&&this._scrollToBottom()}_finalizeMessage(){this._streamingMessage&&(this._messages=[...this._messages,this._streamingMessage],this._streamingMessage=null),this._isStreaming=!1,this._streamingContent="",this._isSending=!1,this._isAtBottom&&this._scrollToBottom(),this.requestUpdate()}async request(e,t,s){if(!this.config)throw new Error("Not configured");const i=Y(this.config.url,t),n=await fetch(i,{method:e,headers:ce(this.config.token),body:s?JSON.stringify(s):void 0});if(!n.ok){const r=await n.json().catch(()=>({error:{message:`HTTP ${n.status}`}}));throw new Error(r.error?.message||`HTTP ${n.status}`)}return n.json()}abort(){this._agentAbort?.abort(),this._agentAbort=void 0,this._isStreaming=!1,this._isSending=!1,this._streamingContent="",this._streamingMessage=null,this.requestUpdate()}get connectionState(){return this._connectionState}get messages(){return this._messages}clearMessages(){this._messages=[],this.requestUpdate()}render(){return o`
545
+ ${this._renderStatus()}
546
+ ${this._renderHeader()}
547
+
548
+ <div class="chat-messages">
549
+ <div class="chat-messages-inner">
550
+ ${this._renderMessages()}
551
+ </div>
552
+ </div>
553
+
554
+ <!-- Scroll to bottom button - placed outside overflow container -->
555
+ ${this._isAtBottom?"":o`
556
+ <button
557
+ class="scroll-to-bottom-btn"
558
+ style="position: fixed; bottom: 100px; right: 24px; width: 48px; height: 48px; border-radius: 50%; background: #3b82f6; color: white; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 100;"
559
+ @click=${this._scrollToBottom}
560
+ title="Scroll to bottom"
561
+ >
562
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
563
+ </button>
564
+ `}
565
+
566
+ <div class="chat-input-container">
567
+ <div class="chat-input-inner">
568
+ ${this._renderInput()}
569
+ </div>
570
+ </div>
571
+ `}_renderHeader(){return o`
572
+ <div class="chat-header">
573
+ <div class="chat-header-title">
574
+ <span class="font-semibold">${a("chat.title")||"XopcBot"}</span>
575
+ ${this._currentSessionKey?o`
576
+ <span class="text-xs text-muted ml-2">${this._sessions.find(e=>e.key===this._currentSessionKey)?.name||this._currentSessionKey}</span>
577
+ `:""}
578
+ </div>
579
+ <button class="new-session-btn" @click=${()=>this._createNewSession()}>
580
+ ${this._renderIcon("plus")}
581
+ <span>${a("chat.newSession")||"New Chat"}</span>
582
+ </button>
583
+ </div>
584
+ `}_renderStatus(){return this._connectionState==="error"&&this._error?o`
585
+ <div class="status-bar error">
586
+ ${this._renderIcon("alertCircle")}
587
+ <span>${this._error}</span>
588
+ <button class="underline ml-auto" @click=${()=>this.reconnect()}>${a("chat.retry")}</button>
589
+ </div>
590
+ `:this._connectionState==="reconnecting"?o`
591
+ <div class="status-bar warning">
592
+ <div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
593
+ <span>${a("chat.reconnecting")}</span>
594
+ </div>
595
+ `:this._connectionState==="connecting"?o`
596
+ <div class="status-bar warning">
597
+ <div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
598
+ <span>${a("chat.connecting")}</span>
599
+ </div>
600
+ `:null}_renderIcon(e){return{alertCircle:o`
601
+ <svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
602
+ <circle cx="12" cy="12" r="10"/>
603
+ <line x1="12" y1="8" x2="12" y2="12"/>
604
+ <line x1="12" y1="16" x2="12.01" y2="16"/>
605
+ </svg>
606
+ `,chevronDown:o`
607
+ <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
608
+ <polyline points="6 9 12 15 18 9"/>
609
+ </svg>
610
+ `,plus:o`
611
+ <svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
612
+ <line x1="12" y1="5" x2="12" y2="19"/>
613
+ <line x1="5" y1="12" x2="19" y2="12"/>
614
+ </svg>
615
+ `}[e]||""}_renderScrollToBottomButton(){return o`
616
+ <button
617
+ class="scroll-to-bottom-btn"
618
+ style="background: red !important; width: 60px; height: 60px; font-size: 24px;"
619
+ @click=${this._scrollToBottom}
620
+ title="Scroll to bottom"
621
+ >
622
+ 👇
623
+ </button>
624
+ `}_renderMessages(){return!this._messages.length&&!this._isStreaming?o`
625
+ <div class="empty-state" style="padding-top: 30vh;">
626
+ <div class="icon">🤖</div>
627
+ <div class="title">${a("chat.welcomeTitle")}</div>
628
+ <div class="description">${a("chat.welcomeDescription")}</div>
629
+ </div>
630
+ `:o`
631
+ <div class="flex flex-col gap-4">
632
+ ${this._messages.map(e=>this._renderMessage(e))}
633
+ ${this._isStreaming&&this._streamingMessage?this._renderStreamingMessage():""}
634
+ </div>
635
+ `}_renderMessage(e){const t=e.role==="user";return!e.content?.some(i=>i.text)&&!e.attachments?.length?null:o`
636
+ <div class="message-item ${t?"flex-row-reverse":""}">
637
+ <div class="avatar ${t?"user":"assistant"}">
638
+ ${t?a("chat.you").charAt(0):"X"}
639
+ </div>
640
+
641
+ <div class="flex flex-col gap-1 max-w-[calc(100%-3rem)]">
642
+ <div class="flex items-center gap-2 text-xs text-muted ${t?"flex-row-reverse":""}">
643
+ <span class="font-medium">${a(t?"chat.you":"chat.assistant")}</span>
644
+ <span>·</span>
645
+ <span>${this._formatTime(e.timestamp)}</span>
646
+ </div>
647
+
648
+ <div class="message-bubble ${t?"user":"assistant"}">
649
+ ${this._renderMessageContent(e.content)}
650
+ ${e.attachments?.length?this._renderAttachments(e.attachments):""}
651
+ </div>
652
+ </div>
653
+ </div>
654
+ `}_renderStreamingMessage(){const e=this._streamingMessage?.content||[];return o`
655
+ <div class="message-item">
656
+ <div class="avatar assistant">X</div>
657
+ <div class="flex flex-col gap-1 max-w-[calc(100%-3rem)]">
658
+ <div class="flex items-center gap-2 text-xs text-muted">
659
+ <span class="font-medium">${a("chat.assistant")}</span>
660
+ <span>·</span>
661
+ <span class="text-primary animate-pulse">${a("chat.thinking")}</span>
662
+ </div>
663
+ <div class="message-bubble assistant">
664
+ <div class="markdown-content">
665
+ ${e.map(t=>t.type==="text"&&t.text?o`<p class="whitespace-pre-wrap">${t.text}<span class="streaming-cursor"></span></p>`:"")}
666
+ ${e.length?"":o`<span class="streaming-cursor"></span>`}
667
+ </div>
668
+ </div>
669
+ </div>
670
+ </div>
671
+ `}_renderMessageContent(e){return!e||e.length===0?null:o`
672
+ <div class="markdown-content">
673
+ ${e.map(t=>t.type==="text"&&t.text?o`<p class="whitespace-pre-wrap">${t.text}</p>`:"")}
674
+ </div>
675
+ `}_renderAttachments(e){const t=e.filter(i=>i.type==="image"||i.mimeType?.startsWith("image/")),s=e.filter(i=>i.type!=="image"&&!i.mimeType?.startsWith("image/"));return o`
676
+ <div class="flex flex-col gap-2 mt-2">
677
+ ${t.length>0?this._renderImageGallery(t):""}
678
+ ${s.length>0?this._renderDocumentList(s):""}
679
+ </div>
680
+ `}_renderImageGallery(e){const t=e.length;let s="single";return t===2?s="double":t===3?s="triple":t>=4&&(s="quad"),o`
681
+ <div class="image-gallery ${s}">
682
+ ${e.map(i=>o`<img src="${i.data}" alt="${i.name||"Image"}" />`)}
683
+ </div>
684
+ `}_renderDocumentList(e){return o`
685
+ <div class="flex flex-col gap-2">
686
+ ${e.map(t=>this._renderDocumentPreview(t))}
687
+ </div>
688
+ `}_renderDocumentPreview(e){const t=e.name||"Document",s=e.size?this._formatFileSize(e.size):"";return o`
689
+ <div class="document-preview">
690
+ <div class="icon">${this._getDocumentIcon(e.mimeType||"")}</div>
691
+ <div class="info">
692
+ <div class="name">${t}</div>
693
+ <div class="meta">${s||e.mimeType||"File"}</div>
694
+ </div>
695
+ </div>
696
+ `}_getDocumentIcon(e){const t=e.includes("pdf")?"#ef4444":e.includes("word")||e.includes("document")?"#2563eb":e.includes("sheet")||e.includes("excel")?"#16a34a":"currentColor";return o`
697
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="${t}" stroke-width="2">
698
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
699
+ <polyline points="14,2 14,8 20,8"/>
700
+ </svg>
701
+ `}_renderInput(){return o`
702
+ <message-editor
703
+ .isStreaming=${this._isStreaming}
704
+ .showAttachmentButton=${this.enableAttachments}
705
+ .showModelSelector=${this.enableModelSelector}
706
+ .onSend=${(e,t)=>this._handleSend(e,t)}
707
+ .onAbort=${()=>this.abort()}
708
+ ></message-editor>
709
+ `}_formatTime(e){return new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}_formatFileSize(e){const t=["B","KB","MB","GB"];let s=0,i=e;for(;i>=1024&&s<t.length-1;)i/=1024,s++;return`${i.toFixed(1)} ${t[s]}`}};x([u({attribute:!1})],w.prototype,"config",2);x([u({attribute:!1})],w.prototype,"route",2);x([u({type:Boolean})],w.prototype,"enableAttachments",2);x([u({type:Boolean})],w.prototype,"enableModelSelector",2);x([ie("message-editor")],w.prototype,"_messageEditor",2);x([ie(".chat-messages")],w.prototype,"_chatMessages",2);x([c()],w.prototype,"_connectionState",2);x([c()],w.prototype,"_error",2);x([c()],w.prototype,"_messages",2);x([c()],w.prototype,"_isStreaming",2);x([c()],w.prototype,"_streamingContent",2);x([c()],w.prototype,"_streamingMessage",2);x([c()],w.prototype,"_reconnectCount",2);x([c()],w.prototype,"_isAtBottom",2);x([c()],w.prototype,"_currentSessionKey",2);x([c()],w.prototype,"_sessions",2);x([c()],w.prototype,"_hasMoreMessages",2);x([c()],w.prototype,"_isLoadingMore",2);w=x([k("xopcbot-gateway-chat")],w);var Us=Object.defineProperty,Hs=Object.getOwnPropertyDescriptor,Ue=(e,t,s,i)=>{for(var n=i>1?void 0:i?Hs(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Us(t,s,n),n};let Se=class extends y{constructor(){super(...arguments),this.selected=!1}createRenderRoot(){return this}_emit(e){this.dispatchEvent(new CustomEvent("session-action",{detail:{action:e,key:this.session.key},bubbles:!0,composed:!0}))}_formatDate(e){const t=new Date(e),i=Math.floor((new Date().getTime()-t.getTime())/(1e3*60*60*24));return i===0?t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):i===1?"Yesterday":i<7?t.toLocaleDateString([],{weekday:"short"}):t.toLocaleDateString([],{month:"short",day:"numeric"})}_getChannelIcon(e){return{telegram:"send",whatsapp:"phone",gateway:"globe",cli:"terminal"}[e]||"messageSquare"}_getStatusBadge(){switch(this.session.status){case"archived":return"bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400";case"pinned":return"bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400";default:return"bg-green-100 text-green-600 dark:bg-green-900/30 dark:text-green-400"}}render(){const e=this.session.name||this.session.key,t=this.session.status==="archived",s=this.session.status==="pinned";return o`
710
+ <div
711
+ class="session-card ${this.selected?"session-card--selected":""} ${t?"session-card--archived":""}"
712
+ @click=${()=>this._emit("click")}
713
+ >
714
+ <div class="session-card__header">
715
+ <div class="session-card__channel">
716
+ <span class="channel-icon">${p(this._getChannelIcon(this.session.sourceChannel))}</span>
717
+ <span class="channel-name">${this.session.sourceChannel}</span>
718
+ </div>
719
+ <div class="session-card__meta">
720
+ ${s?o`<span class="pin-badge" title="Pinned">${p("pin")}</span>`:""}
721
+ <span class="date">${this._formatDate(this.session.updatedAt)}</span>
722
+ </div>
723
+ </div>
724
+
725
+ <div class="session-card__title">
726
+ ${e}
727
+ </div>
728
+
729
+ <div class="session-card__stats">
730
+ <span class="stat">
731
+ ${p("messageSquare")}
732
+ ${this.session.messageCount}
733
+ </span>
734
+ <span class="stat">
735
+ ${p("zap")}
736
+ ${this._formatTokens(this.session.estimatedTokens)}
737
+ </span>
738
+ </div>
739
+
740
+ ${this.session.tags.length>0?o`
741
+ <div class="session-card__tags">
742
+ ${this.session.tags.slice(0,3).map(i=>o`
743
+ <span class="tag">${i}</span>
744
+ `)}
745
+ ${this.session.tags.length>3?o`
746
+ <span class="tag tag--more">+${this.session.tags.length-3}</span>
747
+ `:""}
748
+ </div>
749
+ `:""}
750
+
751
+ <div class="session-card__actions" @click=${i=>i.stopPropagation()}>
752
+ ${t?o`
753
+ <button
754
+ class="btn-icon btn-icon--success"
755
+ title="Unarchive"
756
+ @click=${()=>this._emit("unarchive")}
757
+ >${p("archiveRestore")}</button>
758
+ `:o`
759
+ <button
760
+ class="btn-icon"
761
+ title="Archive"
762
+ @click=${()=>this._emit("archive")}
763
+ >${p("archive")}</button>
764
+ `}
765
+
766
+ ${s?o`
767
+ <button
768
+ class="btn-icon btn-icon--primary"
769
+ title="Unpin"
770
+ @click=${()=>this._emit("unpin")}
771
+ >${p("pinOff")}</button>
772
+ `:o`
773
+ <button
774
+ class="btn-icon"
775
+ title="Pin"
776
+ @click=${()=>this._emit("pin")}
777
+ >${p("pin")}</button>
778
+ `}
779
+
780
+ <button
781
+ class="btn-icon"
782
+ title="Export"
783
+ @click=${()=>this._emit("export")}
784
+ >${p("download")}</button>
785
+
786
+ <button
787
+ class="btn-icon btn-icon--danger"
788
+ title="Delete"
789
+ @click=${()=>this._emit("delete")}
790
+ >${p("trash")}</button>
791
+ </div>
792
+ </div>
793
+ `}_formatTokens(e){return e>=1e3?(e/1e3).toFixed(1)+"k":e.toString()}};Ue([u({attribute:!1})],Se.prototype,"session",2);Ue([u({type:Boolean})],Se.prototype,"selected",2);Se=Ue([k("session-card")],Se);var Ns=Object.defineProperty,zs=Object.getOwnPropertyDescriptor,oe=(e,t,s,i)=>{for(var n=i>1?void 0:i?zs(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ns(t,s,n),n};let V=class extends y{constructor(){super(...arguments),this.sessions=[],this.loading=!1,this.hasMore=!1,this.selectedKey=null,this._viewMode="grid"}createRenderRoot(){return this}_emit(e,t){this.dispatchEvent(new CustomEvent("list-action",{detail:{action:e,key:t},bubbles:!0,composed:!0}))}_handleCardAction(e){const{action:t,key:s}=e.detail;t==="click"?this._emit("select",s):this._emit(t,s)}_loadMore(){this.dispatchEvent(new CustomEvent("load-more",{bubbles:!0,composed:!0}))}render(){return this.loading&&this.sessions.length===0?this._renderLoading():this.sessions.length===0?this._renderEmpty():o`
794
+ <div class="session-list">
795
+ ${this._renderToolbar()}
796
+
797
+ <div class="session-list__content session-list__content--${this._viewMode}">
798
+ ${this.sessions.map(e=>o`
799
+ <session-card
800
+ .session=${e}
801
+ .selected=${e.key===this.selectedKey}
802
+ @session-action=${this._handleCardAction}
803
+ ></session-card>
804
+ `)}
805
+ </div>
806
+
807
+ ${this.hasMore?o`
808
+ <div class="session-list__load-more">
809
+ <button class="btn btn--secondary" @click=${this._loadMore}>
810
+ ${p("chevronDown")}
811
+ Load More
812
+ </button>
813
+ </div>
814
+ `:""}
815
+
816
+ ${this.loading?o`
817
+ <div class="session-list__loading-overlay">
818
+ <div class="spinner"></div>
819
+ </div>
820
+ `:""}
821
+ </div>
822
+ `}_renderToolbar(){return o`
823
+ <div class="session-list__toolbar">
824
+ <div class="session-list__count">
825
+ ${this.sessions.length} sessions
826
+ </div>
827
+
828
+ <div class="session-list__view-toggle">
829
+ <button
830
+ class="btn-icon ${this._viewMode==="grid"?"btn-icon--active":""}"
831
+ title="Grid view"
832
+ @click=${()=>this._viewMode="grid"}
833
+ >${p("grid")}</button>
834
+ <button
835
+ class="btn-icon ${this._viewMode==="list"?"btn-icon--active":""}"
836
+ title="List view"
837
+ @click=${()=>this._viewMode="list"}
838
+ >${p("list")}</button>
839
+ </div>
840
+ </div>
841
+ `}_renderLoading(){return o`
842
+ <div class="session-list session-list--loading">
843
+ <div class="session-list__skeleton">
844
+ ${Array.from({length:6}).map(()=>o`
845
+ <div class="skeleton-card">
846
+ <div class="skeleton skeleton--header"></div>
847
+ <div class="skeleton skeleton--title"></div>
848
+ <div class="skeleton skeleton--stats"></div>
849
+ </div>
850
+ `)}
851
+ </div>
852
+ </div>
853
+ `}_renderEmpty(){return o`
854
+ <div class="session-list session-list--empty">
855
+ <div class="empty-state">
856
+ <div class="empty-state__icon">${p("folderOpen")}</div>
857
+ <div class="empty-state__title">No sessions found</div>
858
+ <div class="empty-state__description">
859
+ Start a conversation to create your first session.
860
+ </div>
861
+ </div>
862
+ </div>
863
+ `}};oe([u({attribute:!1})],V.prototype,"sessions",2);oe([u({type:Boolean})],V.prototype,"loading",2);oe([u({type:Boolean})],V.prototype,"hasMore",2);oe([u({type:String})],V.prototype,"selectedKey",2);oe([c()],V.prototype,"_viewMode",2);V=oe([k("session-list")],V);var qs=Object.defineProperty,Js=Object.getOwnPropertyDescriptor,Q=(e,t,s,i)=>{for(var n=i>1?void 0:i?Js(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&qs(t,s,n),n};let j=class extends y{constructor(){super(...arguments),this.session=null,this.open=!1,this.loading=!1,this._searchQuery="",this._searchResults=[],this._currentResultIndex=-1}createRenderRoot(){return this}_emit(e){this.dispatchEvent(new CustomEvent("detail-action",{detail:{action:e},bubbles:!0,composed:!0}))}_handleClose(){this._emit("close")}_handleBackdropClick(e){e.target===e.currentTarget&&this._handleClose()}_handleSearch(e){const t=e.target;this._searchQuery=t.value,this._performSearch()}_performSearch(){if(!this.session||!this._searchQuery.trim()){this._searchResults=[],this._currentResultIndex=-1;return}const e=this._searchQuery.toLowerCase(),t=[];this.session.messages.forEach((s,i)=>{s.content.toLowerCase().includes(e)&&t.push(i)}),this._searchResults=t,this._currentResultIndex=t.length>0?0:-1}_navigateSearch(e){if(this._searchResults.length===0)return;e==="next"?this._currentResultIndex=(this._currentResultIndex+1)%this._searchResults.length:this._currentResultIndex=(this._currentResultIndex-1+this._searchResults.length)%this._searchResults.length;const t=this._searchResults[this._currentResultIndex],s=this.querySelector(`[data-message-index="${t}"]`);s&&s.scrollIntoView({behavior:"smooth",block:"center"})}_highlightText(e){if(!this._searchQuery.trim())return e;const t=this._searchQuery;return e.split(new RegExp(`(${t})`,"gi")).map((i,n)=>i.toLowerCase()===t.toLowerCase()?o`<mark class="search-highlight">${i}</mark>`:i)}_formatDate(e){return new Date(e).toLocaleString()}render(){return this.open?o`
864
+ <div class="drawer-backdrop" @click=${this._handleBackdropClick}>
865
+ <div class="drawer drawer--${this.open?"open":"closed"}">
866
+ ${this._renderHeader()}
867
+ ${this._renderSearch()}
868
+ ${this._renderContent()}
869
+ ${this._renderActions()}
870
+ </div>
871
+ </div>
872
+ `:""}_renderHeader(){if(!this.session)return"";const e=this.session.status==="archived",t=this.session.status==="pinned";return o`
873
+ <div class="drawer-header">
874
+ <div class="drawer-header__info">
875
+ <div class="drawer-header__title">
876
+ ${this.session.name||this.session.key}
877
+ ${t?o`<span class="pin-badge">${p("pin")}</span>`:""}
878
+ ${e?o`<span class="archive-badge">Archived</span>`:""}
879
+ </div>
880
+ <div class="drawer-header__meta">
881
+ <span>${this.session.sourceChannel}</span>
882
+ <span>•</span>
883
+ <span>${this.session.messageCount} messages</span>
884
+ <span>•</span>
885
+ <span>${this._formatDate(this.session.updatedAt)}</span>
886
+ </div>
887
+ </div>
888
+ <button class="btn-icon" @click=${this._handleClose} title="Close">
889
+ ${p("x")}
890
+ </button>
891
+ </div>
892
+ `}_renderSearch(){return this.session?o`
893
+ <div class="drawer-search">
894
+ <div class="search-input-wrapper">
895
+ ${p("search")}
896
+ <input
897
+ type="text"
898
+ placeholder="Search in session..."
899
+ .value=${this._searchQuery}
900
+ @input=${this._handleSearch}
901
+ />
902
+ ${this._searchQuery?o`
903
+ <button class="btn-icon btn-icon--sm" @click=${()=>{this._searchQuery="",this._performSearch()}}>
904
+ ${p("x")}
905
+ </button>
906
+ `:""}
907
+ </div>
908
+
909
+ ${this._searchResults.length>0?o`
910
+ <div class="search-nav">
911
+ <span class="search-count">${this._currentResultIndex+1} / ${this._searchResults.length}</span>
912
+ <button class="btn-icon btn-icon--sm" @click=${()=>this._navigateSearch("prev")} title="Previous">
913
+ ${p("chevronUp")}
914
+ </button>
915
+ <button class="btn-icon btn-icon--sm" @click=${()=>this._navigateSearch("next")} title="Next">
916
+ ${p("chevronDown")}
917
+ </button>
918
+ </div>
919
+ `:""}
920
+ </div>
921
+ `:""}_renderContent(){return this.loading?o`
922
+ <div class="drawer-content drawer-content--loading">
923
+ <div class="spinner"></div>
924
+ <span>Loading...</span>
925
+ </div>
926
+ `:this.session?o`
927
+ <div class="drawer-content">
928
+ ${this.session.messages.map((e,t)=>{const s=this._searchResults.includes(t),i=this._searchResults[this._currentResultIndex]===t;return o`
929
+ <div
930
+ class="message ${e.role} ${s?"message--highlight":""} ${i?"message--current":""}"
931
+ data-message-index="${t}"
932
+ >
933
+ <div class="message__header">
934
+ <span class="message__role">${e.role}</span>
935
+ ${e.timestamp?o`<span class="message__time">${this._formatDate(e.timestamp)}</span>`:""}
936
+ </div>
937
+ <div class="message__content">${this._highlightText(e.content)}</div>
938
+ </div>
939
+ `})}
940
+ </div>
941
+ `:o`
942
+ <div class="drawer-content drawer-content--empty">
943
+ <span>No session selected</span>
944
+ </div>
945
+ `}_renderActions(){if(!this.session)return"";const e=this.session.status==="archived",t=this.session.status==="pinned";return o`
946
+ <div class="drawer-actions">
947
+ ${e?o`
948
+ <button class="btn btn--secondary" @click=${()=>this._emit("unarchive")}>
949
+ ${p("archiveRestore")} Unarchive
950
+ </button>
951
+ `:o`
952
+ <button class="btn btn--secondary" @click=${()=>this._emit("archive")}>
953
+ ${p("archive")} Archive
954
+ </button>
955
+ `}
956
+
957
+ ${t?o`
958
+ <button class="btn btn--secondary" @click=${()=>this._emit("unpin")}>
959
+ ${p("pinOff")} Unpin
960
+ </button>
961
+ `:o`
962
+ <button class="btn btn--secondary" @click=${()=>this._emit("pin")}>
963
+ ${p("pin")} Pin
964
+ </button>
965
+ `}
966
+
967
+ <button class="btn btn--secondary" @click=${()=>this._emit("export")}>
968
+ ${p("download")} Export
969
+ </button>
970
+
971
+ <button class="btn btn--danger" @click=${()=>this._emit("delete")}>
972
+ ${p("trash")} Delete
973
+ </button>
974
+ </div>
975
+ `}};Q([u({attribute:!1})],j.prototype,"session",2);Q([u({type:Boolean})],j.prototype,"open",2);Q([u({type:Boolean})],j.prototype,"loading",2);Q([c()],j.prototype,"_searchQuery",2);Q([c()],j.prototype,"_searchResults",2);Q([c()],j.prototype,"_currentResultIndex",2);j=Q([k("session-detail-drawer")],j);var Gs=Object.defineProperty,Ws=Object.getOwnPropertyDescriptor,X=(e,t,s,i)=>{for(var n=i>1?void 0:i?Ws(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Gs(t,s,n),n};let U=class extends y{constructor(){super(...arguments),this.open=!1,this.title="Confirm",this.message="Are you sure?",this.confirmText="Confirm",this.cancelText="Cancel",this.type="warning"}createRenderRoot(){return this}_emit(e){this.dispatchEvent(new CustomEvent("confirm",{detail:{confirmed:e},bubbles:!0,composed:!0})),this.open=!1}_handleBackdropClick(e){e.target===e.currentTarget&&this._emit(!1)}_getIcon(){switch(this.type){case"danger":return"trash";case"warning":return"alertTriangle";case"info":return"info";default:return"helpCircle"}}_getIconColor(){switch(this.type){case"danger":return"text-red-500";case"warning":return"text-amber-500";case"info":return"text-blue-500";default:return"text-gray-500"}}render(){return this.open?o`
976
+ <div class="modal-backdrop" @click=${this._handleBackdropClick}>
977
+ <div class="modal modal--${this.type}">
978
+ <div class="modal__icon ${this._getIconColor()}">
979
+ ${p(this._getIcon())}
980
+ </div>
981
+
982
+ <div class="modal__content">
983
+ <h3 class="modal__title">${this.title}</h3>
984
+ <p class="modal__message">${this.message}</p>
985
+ </div>
986
+
987
+ <div class="modal__actions">
988
+ <button class="btn btn--secondary" @click=${()=>this._emit(!1)}>
989
+ ${this.cancelText}
990
+ </button>
991
+ <button class="btn btn--${this.type==="danger"?"danger":"primary"}" @click=${()=>this._emit(!0)}>
992
+ ${this.confirmText}
993
+ </button>
994
+ </div>
995
+ </div>
996
+ </div>
997
+ `:""}};X([u({type:Boolean})],U.prototype,"open",2);X([u({type:String})],U.prototype,"title",2);X([u({type:String})],U.prototype,"message",2);X([u({type:String})],U.prototype,"confirmText",2);X([u({type:String})],U.prototype,"cancelText",2);X([u({type:String})],U.prototype,"type",2);U=X([k("confirm-dialog")],U);class Vs{constructor(t,s){this.baseUrl=t.replace(/\/$/,""),this.token=s}async request(t,s,i){const n={"Content-Type":"application/json"};this.token&&(n.Authorization=`Bearer ${this.token}`);const r=await fetch(`${this.baseUrl}${s}`,{method:t,headers:n,body:i?JSON.stringify(i):void 0});if(!r.ok){const l=await r.json().catch(()=>({error:"Request failed"}));throw new Error(l.error||`HTTP ${r.status}`)}return r.json()}async listSessions(t){const s=new URLSearchParams;t?.status&&s.set("status",t.status),t?.search&&s.set("search",t.search),t?.limit&&s.set("limit",String(t.limit)),t?.offset&&s.set("offset",String(t.offset));const i=s.toString(),n=`/api/sessions${i?`?${i}`:""}`;return await this.request("GET",n)}async getSession(t){try{return(await this.request("GET",`/api/sessions/${t}`)).session||null}catch(s){if(s instanceof Error&&s.message.includes("404"))return null;throw s}}async deleteSession(t){return await this.request("DELETE",`/api/sessions/${t}`)}async archiveSession(t){return await this.request("POST",`/api/sessions/${t}/archive`)}async unarchiveSession(t){return await this.request("POST",`/api/sessions/${t}/unarchive`)}async pinSession(t){return await this.request("POST",`/api/sessions/${t}/pin`)}async unpinSession(t){return await this.request("POST",`/api/sessions/${t}/unpin`)}async renameSession(t,s){return await this.request("POST",`/api/sessions/${t}/rename`,{name:s})}async exportSession(t,s="json"){return(await this.request("GET",`/api/sessions/${t}/export?format=${s}`)).content}async getStats(){return await this.request("GET","/api/sessions/stats")}}var Qs=Object.defineProperty,Xs=Object.getOwnPropertyDescriptor,A=(e,t,s,i)=>{for(var n=i>1?void 0:i?Xs(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Qs(t,s,n),n};let b=class extends y{constructor(){super(...arguments),this._sessions=[],this._loading=!1,this._hasMore=!1,this._stats=null,this._searchQuery="",this._statusFilter="all",this._offset=0,this._error=null,this._detailOpen=!1,this._detailSession=null,this._detailLoading=!1,this._confirmOpen=!1,this._confirmTitle="",this._confirmMessage="",this._confirmKey=null,this._confirmAction=null,this._limit=20,this._initialized=!1,this._debouncedSearch=this._debounce(()=>{this._loadSessions(!0)},300)}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._tryInitialize()}willUpdate(e){super.willUpdate(e),e.has("config")&&this._tryInitialize()}_tryInitialize(){if(this._initialized||!this.config?.url)return;const e=this.config.url.replace(/\/+$/,"");this._api=new Vs(e,this.config.token),this._initialized=!0,this._loadSessions(),this._loadStats()}disconnectedCallback(){super.disconnectedCallback()}async _loadSessions(e=!1){if(!this._loading){this._loading=!0,this._error=null,e&&(this._offset=0,this._sessions=[]);try{const t={limit:this._limit,offset:this._offset,sortBy:"updatedAt",sortOrder:"desc",...this._statusFilter!=="all"&&{status:this._statusFilter},...this._searchQuery&&{search:this._searchQuery}},s=await this._api.listSessions(t);e?this._sessions=s.items:this._sessions=[...this._sessions,...s.items],this._hasMore=s.hasMore,this._offset=s.offset+s.items.length}catch(t){this._error=t instanceof Error?t.message:"Failed to load sessions",console.error("[SessionManager] Load error:",t)}finally{this._loading=!1}}}async _loadStats(){try{this._stats=await this._api.getStats()}catch(e){console.error("[SessionManager] Stats error:",e)}}async _openDetail(e){this._detailOpen=!0,this._detailLoading=!0;try{const t=await this._api.getSession(e);this._detailSession=t}catch(t){console.error("[SessionManager] Load detail error:",t),this._detailOpen=!1}finally{this._detailLoading=!1}}_closeDetail(){this._detailOpen=!1,this._detailSession=null}_handleDetailAction(e){const{action:t}=e.detail,s=this._detailSession?.key;if(s)switch(t){case"close":this._closeDetail();break;case"delete":this._showConfirm(s);break;case"archive":this._archiveSession(s);break;case"unarchive":this._unarchiveSession(s);break;case"pin":this._pinSession(s);break;case"unpin":this._unpinSession(s);break;case"export":this._exportSession(s);break}}_showConfirm(e){this._confirmKey=e,this._confirmAction="delete",this._confirmTitle="Delete Session",this._confirmMessage=`Are you sure you want to delete session "${e}"?
998
+
999
+ This action cannot be undone.`,this._confirmOpen=!0}_handleConfirm(e){if(!e.detail.confirmed||!this._confirmKey){this._confirmOpen=!1,this._confirmKey=null;return}this._deleteSession(this._confirmKey),this._confirmOpen=!1,this._confirmKey=null}async _deleteSession(e){try{await this._api.deleteSession(e),this._sessions=this._sessions.filter(t=>t.key!==e),this._detailSession?.key===e&&this._closeDetail(),await this._loadStats()}catch(t){alert("Failed to delete session: "+(t instanceof Error?t.message:String(t)))}}async _archiveSession(e){try{await this._api.archiveSession(e),this._updateSessionStatus(e,"archived"),this._detailSession?.key===e&&(this._detailSession={...this._detailSession,status:"archived"}),await this._loadStats()}catch(t){console.error("[SessionManager] Archive error:",t)}}async _unarchiveSession(e){try{await this._api.unarchiveSession(e),this._updateSessionStatus(e,"active"),this._detailSession?.key===e&&(this._detailSession={...this._detailSession,status:"active"}),await this._loadStats()}catch(t){console.error("[SessionManager] Unarchive error:",t)}}async _pinSession(e){try{await this._api.pinSession(e),this._updateSessionStatus(e,"pinned"),this._detailSession?.key===e&&(this._detailSession={...this._detailSession,status:"pinned"}),await this._loadStats()}catch(t){console.error("[SessionManager] Pin error:",t)}}async _unpinSession(e){try{await this._api.unpinSession(e),this._updateSessionStatus(e,"active"),this._detailSession?.key===e&&(this._detailSession={...this._detailSession,status:"active"}),await this._loadStats()}catch(t){console.error("[SessionManager] Unpin error:",t)}}async _exportSession(e){try{const t=await this._api.exportSession(e,"json"),s=new Blob([t],{type:"application/json"}),i=URL.createObjectURL(s),n=document.createElement("a");n.href=i,n.download=`session-${e.replace(/[^a-z0-9]/gi,"_")}.json`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(i)}catch(t){alert("Failed to export session: "+(t instanceof Error?t.message:String(t)))}}_updateSessionStatus(e,t){this._sessions=this._sessions.map(s=>s.key===e?{...s,status:t}:s)}_handleListAction(e){const{action:t,key:s}=e.detail;switch(t){case"select":this._openDetail(s);break;case"delete":this._showConfirm(s);break;case"archive":this._archiveSession(s);break;case"unarchive":this._unarchiveSession(s);break;case"pin":this._pinSession(s);break;case"unpin":this._unpinSession(s);break;case"export":this._exportSession(s);break}}_handleSearch(e){const t=e.target;this._searchQuery=t.value,this._debouncedSearch()}_debounce(e,t){let s;return()=>{clearTimeout(s),s=setTimeout(e,t)}}_handleStatusFilter(e){this._statusFilter=e,this._loadSessions(!0)}_handleLoadMore(){this._loadSessions()}render(){return o`
1000
+ <div class="session-manager">
1001
+ ${this._renderHeader()}
1002
+ ${this._renderFilters()}
1003
+ ${this._renderStats()}
1004
+ ${this._error?o`<div class="error-banner">${this._error}</div>`:""}
1005
+
1006
+ <session-list
1007
+ .sessions=${this._sessions}
1008
+ .loading=${this._loading}
1009
+ .hasMore=${this._hasMore}
1010
+ @list-action=${this._handleListAction}
1011
+ @load-more=${this._handleLoadMore}
1012
+ ></session-list>
1013
+ </div>
1014
+
1015
+ <session-detail-drawer
1016
+ .session=${this._detailSession}
1017
+ .open=${this._detailOpen}
1018
+ .loading=${this._detailLoading}
1019
+ @detail-action=${this._handleDetailAction}
1020
+ ></session-detail-drawer>
1021
+
1022
+ <confirm-dialog
1023
+ .open=${this._confirmOpen}
1024
+ .title=${this._confirmTitle}
1025
+ .message=${this._confirmMessage}
1026
+ .confirmText="Delete"
1027
+ .cancelText="Cancel"
1028
+ .type="danger"
1029
+ @confirm=${this._handleConfirm}
1030
+ ></confirm-dialog>
1031
+ `}_renderHeader(){return o`
1032
+ <div class="session-manager__header">
1033
+ <h1 class="page-title">${p("folderOpen")} ${a("sessions.title")}</h1>
1034
+ <div class="search-box">
1035
+ ${p("search")}
1036
+ <input
1037
+ type="text"
1038
+ placeholder="${a("sessions.searchPlaceholder")}"
1039
+ .value=${this._searchQuery}
1040
+ @input=${this._handleSearch}
1041
+ />
1042
+ </div>
1043
+ </div>
1044
+ `}_renderFilters(){return o`
1045
+ <div class="session-manager__filters">
1046
+ ${[{key:"all",label:"All",icon:"layers"},{key:"active",label:"Active",icon:"circle"},{key:"pinned",label:"Pinned",icon:"pin"},{key:"archived",label:"Archived",icon:"archive"}].map(t=>o`
1047
+ <button
1048
+ class="filter-btn ${this._statusFilter===t.key?"filter-btn--active":""}"
1049
+ @click=${()=>this._handleStatusFilter(t.key)}
1050
+ >
1051
+ ${p(t.icon)}
1052
+ ${t.label}
1053
+ </button>
1054
+ `)}
1055
+ </div>
1056
+ `}_renderStats(){return this._stats?o`
1057
+ <div class="session-manager__stats">
1058
+ <div class="stat-card">
1059
+ <div class="stat-value">${this._stats.totalSessions}</div>
1060
+ <div class="stat-label">${a("sessions.totalSessions")}</div>
1061
+ </div>
1062
+ <div class="stat-card">
1063
+ <div class="stat-value">${this._stats.activeSessions}</div>
1064
+ <div class="stat-label">${a("sessions.activeSessions")}</div>
1065
+ </div>
1066
+ <div class="stat-card">
1067
+ <div class="stat-value">${this._stats.pinnedSessions}</div>
1068
+ <div class="stat-label">${a("sessions.pinnedSessions")}</div>
1069
+ </div>
1070
+ <div class="stat-card">
1071
+ <div class="stat-value">${this._stats.archivedSessions}</div>
1072
+ <div class="stat-label">${a("sessions.archivedSessions")}</div>
1073
+ </div>
1074
+ </div>
1075
+ `:""}};A([u({attribute:!1})],b.prototype,"config",2);A([c()],b.prototype,"_sessions",2);A([c()],b.prototype,"_loading",2);A([c()],b.prototype,"_hasMore",2);A([c()],b.prototype,"_stats",2);A([c()],b.prototype,"_searchQuery",2);A([c()],b.prototype,"_statusFilter",2);A([c()],b.prototype,"_offset",2);A([c()],b.prototype,"_error",2);A([c()],b.prototype,"_detailOpen",2);A([c()],b.prototype,"_detailSession",2);A([c()],b.prototype,"_detailLoading",2);A([c()],b.prototype,"_confirmOpen",2);A([c()],b.prototype,"_confirmTitle",2);A([c()],b.prototype,"_confirmMessage",2);A([c()],b.prototype,"_confirmKey",2);A([c()],b.prototype,"_confirmAction",2);b=A([k("session-manager")],b);class Zs{constructor(t,s){this.baseUrl=t.replace(/\/$/,""),this.token=s}async request(t,s,i){const n={"Content-Type":"application/json"};this.token&&(n.Authorization=`Bearer ${this.token}`);const r=await fetch(`${this.baseUrl}${s}`,{method:t,headers:n,body:i?JSON.stringify(i):void 0});if(!r.ok){const l=await r.json().catch(()=>({error:"Request failed"}));throw new Error(l.error||`HTTP ${r.status}`)}return r.json()}async listJobs(){return(await this.request("GET","/api/cron")).jobs||[]}async getJob(t){try{return(await this.request("GET",`/api/cron/${t}`)).job||null}catch(s){if(s instanceof Error&&s.message.includes("404"))return null;throw s}}async addJob(t,s,i){return await this.request("POST","/api/cron",{schedule:t,message:s,...i})}async updateJob(t,s){return(await this.request("PATCH",`/api/cron/${t}`,s)).updated}async removeJob(t){return(await this.request("DELETE",`/api/cron/${t}`)).removed}async toggleJob(t,s){return(await this.request("POST",`/api/cron/${t}/toggle`,{enabled:s})).toggled}async runJob(t){await this.request("POST",`/api/cron/${t}/run`)}async getHistory(t,s=10){return(await this.request("GET",`/api/cron/${t}/history?limit=${s}`)).history||[]}async getMetrics(){return await this.request("GET","/api/cron/metrics")}async getChannels(){return(await this.request("GET","/api/channels/status")).payload?.channels||[]}async getModels(){return(await this.request("GET","/api/models")).payload?.models||[]}async getConfig(){return{model:((await this.request("GET","/api/config")).config||{}).agents?.defaults?.model||""}}async getSessionChatIds(t){const s=t?`?channel=${encodeURIComponent(t)}`:"";return(await this.request("GET",`/api/sessions/chat-ids${s}`)).payload?.chatIds||[]}disconnect(){}}var Ys=Object.defineProperty,ei=Object.getOwnPropertyDescriptor,v=(e,t,s,i)=>{for(var n=i>1?void 0:i?ei(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ys(t,s,n),n};let _=class extends y{constructor(){super(...arguments),this._jobs=[],this._metrics=null,this._channels=[],this._availableModels=[],this._defaultModel="",this._sessionChatIds=[],this._loading=!1,this._error=null,this._formOpen=!1,this._formMode="add",this._formJobId=null,this._formName="",this._formSchedule="*/5 * * * *",this._formChannel="telegram",this._formChatId="",this._formMessage="",this._formSessionTarget="main",this._formModel="",this._formSubmitting=!1,this._detailOpen=!1,this._detailJob=null,this._detailHistory=[],this._detailLoading=!1,this._confirmOpen=!1,this._confirmTitle="",this._confirmMessage="",this._confirmJobId=null,this._confirmAction=null,this._initialized=!1}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._tryInitialize()}willUpdate(e){super.willUpdate(e),e.has("config")&&this._tryInitialize()}_tryInitialize(){if(this._initialized||!this.config?.url)return;const e=this.config.url.replace(/\/+$/,"");this._api=new Zs(e,this.config.token),this._initialized=!0,this._loadJobs(),this._loadMetrics(),this._loadChannels(),this._loadModels(),this._loadSessionChatIds()}disconnectedCallback(){super.disconnectedCallback(),this._api?.disconnect()}async _loadJobs(){if(!this._loading){this._loading=!0,this._error=null;try{this._jobs=await this._api.listJobs()}catch(e){this._error=e instanceof Error&&e.message||a("cron.failedToLoadJobs"),console.error("[CronManager] Load error:",e)}finally{this._loading=!1}}}async _loadMetrics(){try{this._metrics=await this._api.getMetrics()}catch(e){console.error("[CronManager] Metrics error:",e)}}async _loadChannels(){try{this._channels=await this._api.getChannels()}catch(e){console.error("[CronManager] Channels error:",e)}}async _loadModels(){try{this._availableModels=await this._api.getModels();const e=await this._api.getConfig();this._defaultModel=e.model||"",this._formModel=this._defaultModel,console.log("[CronManager] Loaded models:",this._availableModels.length,"default:",this._defaultModel)}catch(e){console.error("[CronManager] Models error:",e)}}async _loadSessionChatIds(){try{const e=await this._api.getSessionChatIds(this._formChannel);this._sessionChatIds=e,console.log("[CronManager] Loaded session chatIds for channel",this._formChannel,":",e.length,e)}catch(e){console.error("[CronManager] Session chatIds error:",e),this._sessionChatIds=[]}}_openForm(e){if(this._formOpen=!0,this._formMode=e?"edit":"add",this._formJobId=e?.id||null,e||this._loadSessionChatIds(),e)if(this._formName=e.name||"",this._formSchedule=e.schedule,this._formMessage=e.message,this._formSessionTarget=e.sessionTarget||"main",this._formModel=e.model||"",e.delivery)this._formChannel=e.delivery.channel||"telegram",this._formChatId=e.delivery.to||"";else{const t=e.message.split(":"),s=["telegram","whatsapp","cli","gateway"];t.length>=3&&s.includes(t[0])?(this._formChannel=t[0],this._formChatId=t[1],this._formMessage=t.slice(2).join(":")):(this._formChannel="telegram",this._formChatId="")}else this._formName="",this._formSchedule="*/5 * * * *",this._formChannel="telegram",this._formChatId="",this._formMessage="",this._formSessionTarget="main",this._formModel=this._defaultModel||(this._availableModels.length>0?this._availableModels[0].id:"")}_closeForm(){this._formOpen=!1,this._formMode="add",this._formJobId=null,this._formName="",this._formSchedule="*/5 * * * *",this._formChannel="telegram",this._formChatId="",this._formMessage="",this._formSessionTarget="main",this._formModel=""}async _submitForm(){if(!this._formSchedule||!this._formMessage){this._error=a("cron.scheduleRequired");return}if(!this._formChatId){this._error=a("cron.chatIdRequired");return}this._formSubmitting=!0,this._error=null;try{const e=this._formMessage,t={mode:"direct",channel:this._formChannel,to:this._formChatId},s=this._formSessionTarget==="isolated"?{kind:"agentTurn",message:e,model:this._formModel}:{kind:"systemEvent",text:e},i={name:this._formName||void 0,schedule:this._formSchedule,message:e,sessionTarget:this._formSessionTarget,model:this._formSessionTarget==="isolated"?this._formModel:void 0,delivery:t};this._formMode==="edit"&&this._formJobId?await this._api.updateJob(this._formJobId,i):await this._api.addJob(this._formSchedule,e,i),this._closeForm(),await this._loadJobs(),await this._loadMetrics()}catch(e){this._error=e instanceof Error?e.message||a("cron.failedToJob",{mode:this._formMode}):a("cron.failedToJob",{mode:this._formMode})}finally{this._formSubmitting=!1}}async _openDetail(e){this._detailOpen=!0,this._detailJob=e,this._detailLoading=!0;try{const t=await this._api.getJob(e.id);t&&(this._detailJob=t,this._detailHistory=await this._api.getHistory(e.id,20))}catch(t){console.error("[CronManager] Load detail error:",t)}finally{this._detailLoading=!1}}_closeDetail(){this._detailOpen=!1,this._detailJob=null,this._detailHistory=[]}async _toggleJob(e,t){try{await this._api.toggleJob(e.id,t),await this._loadJobs(),await this._loadMetrics()}catch(s){this._error=s instanceof Error&&s.message||a("cron.failedToToggleJob")}}_showRunConfirm(e){this._confirmOpen=!0,this._confirmTitle=a("cron.runNow"),this._confirmMessage=a("cron.confirmRun"),this._confirmJobId=e.id,this._confirmAction="run"}_showDeleteConfirm(e){this._confirmOpen=!0,this._confirmTitle=a("cron.delete"),this._confirmMessage=a("cron.confirmDelete"),this._confirmJobId=e.id,this._confirmAction="delete"}_closeConfirm(){this._confirmOpen=!1,this._confirmTitle="",this._confirmMessage="",this._confirmJobId=null,this._confirmAction=null}_handleConfirm(e){e.detail.confirmed?this._executeConfirmAction():this._closeConfirm()}async _executeConfirmAction(){if(!this._confirmJobId||!this._confirmAction)return;const e=this._confirmJobId,t=this._confirmAction;this._closeConfirm();try{t==="run"?(await this._api.runJob(e),await this._loadJobs(),await this._loadMetrics()):t==="delete"&&(await this._api.removeJob(e),await this._loadJobs(),await this._loadMetrics())}catch(s){this._error=s instanceof Error&&s.message||a("cron.actionFailed")}}render(){return o`
1076
+ <div class="cron-manager">
1077
+ ${this._error?o`<div class="error-banner">${this._error}</div>`:""}
1078
+
1079
+ <!-- Header -->
1080
+ <div class="cron-manager__header">
1081
+ <h1 class="page-title">${p("clock")} ${a("cron.title")}</h1>
1082
+ <div class="cron-manager__actions">
1083
+ <button class="btn btn-secondary" @click=${this._loadJobs} ?disabled=${this._loading}>
1084
+ ${p("refresh")} ${a("logs.refresh")}
1085
+ </button>
1086
+ <button class="btn btn-primary" @click=${()=>this._openForm()}>
1087
+ ${p("plus")} ${a("cron.addJob")}
1088
+ </button>
1089
+ </div>
1090
+ </div>
1091
+
1092
+ <!-- Stats -->
1093
+ ${this._metrics?o`
1094
+ <div class="cron-manager__stats">
1095
+ <div class="stat-card" style="text-align: center;">
1096
+ <div class="stat-value">${this._metrics.totalJobs}</div>
1097
+ <div class="stat-label">${a("sessions.totalSessions")}</div>
1098
+ </div>
1099
+ <div class="stat-card" style="text-align: center;">
1100
+ <div class="stat-value">${this._metrics.enabledJobs}</div>
1101
+ <div class="stat-label">${a("cron.enabled")}</div>
1102
+ </div>
1103
+ <div class="stat-card" style="text-align: center;">
1104
+ <div class="stat-value">${this._metrics.runningJobs}</div>
1105
+ <div class="stat-label">${a("cron.running")}</div>
1106
+ </div>
1107
+ <div class="stat-card" style="text-align: center;">
1108
+ <div class="stat-value" style="font-size: 0.875rem;">
1109
+ ${this._metrics.nextScheduledJob?this._formatNextRun(this._metrics.nextScheduledJob.runAt):"N/A"}
1110
+ </div>
1111
+ <div class="stat-label">${a("cron.nextRun")}</div>
1112
+ </div>
1113
+ </div>
1114
+ `:m}
1115
+
1116
+ <!-- Job List -->
1117
+ <div class="session-list">
1118
+ ${this._loading&&this._jobs.length===0?o`
1119
+ <div class="session-list__loading-overlay">
1120
+ <div class="spinner"></div>
1121
+ </div>
1122
+ `:this._jobs.length===0?o`
1123
+ <div class="session-list session-list--empty">
1124
+ <div class="empty-state">
1125
+ <div class="empty-state__icon">${p("clock")}</div>
1126
+ <div class="empty-state__title">No cron jobs yet</div>
1127
+ <button class="btn btn-primary" @click=${this._openForm}>Create your first job</button>
1128
+ </div>
1129
+ </div>
1130
+ `:o`
1131
+ <div class="session-list__toolbar">
1132
+ <div class="session-list__count">${this._jobs.length} job${this._jobs.length!==1?"s":""}</div>
1133
+ </div>
1134
+ <div class="session-list__content">
1135
+ <table class="data-table">
1136
+ <thead>
1137
+ <tr>
1138
+ <th>${a("cron.name")}</th>
1139
+ <th>${a("cron.scheduleLabel")}</th>
1140
+ <th>${a("cron.nextRun")}</th>
1141
+ <th>${a("cron.status")}</th>
1142
+ <th>${a("cron.actions")}</th>
1143
+ </tr>
1144
+ </thead>
1145
+ <tbody>
1146
+ ${this._jobs.map(e=>o`
1147
+ <tr>
1148
+ <td style="vertical-align: middle; text-align: center;">
1149
+ <button class="btn btn-link" @click=${()=>this._openDetail(e)}>
1150
+ ${e.name||e.id}
1151
+ </button>
1152
+ </td>
1153
+ <td style="vertical-align: middle; text-align: center;"><code>${e.schedule}</code></td>
1154
+ <td style="vertical-align: middle; text-align: center;">${e.next_run?this._formatNextRun(e.next_run):"-"}</td>
1155
+ <td style="vertical-align: middle; text-align: center;">
1156
+ <label class="toggle">
1157
+ <input
1158
+ type="checkbox"
1159
+ ?checked=${e.enabled}
1160
+ @change=${t=>this._toggleJob(e,t.target.checked)}
1161
+ />
1162
+ <span class="toggle__slider"></span>
1163
+ </label>
1164
+ </td>
1165
+ <td style="vertical-align: middle; text-align: center;">
1166
+ <div class="action-buttons">
1167
+ <button class="btn btn-icon btn-secondary" title="Edit" @click=${()=>this._openForm(e)}>
1168
+ ${p("edit")}
1169
+ </button>
1170
+ <button class="btn btn-icon btn-secondary" title="${a("cron.runNow")}" @click=${()=>this._showRunConfirm(e)}>
1171
+ ${p("play")}
1172
+ </button>
1173
+ <button class="btn btn-icon btn-danger" title="${a("cron.delete")}" @click=${()=>this._showDeleteConfirm(e)}>
1174
+ ${p("trash")}
1175
+ </button>
1176
+ </div>
1177
+ </td>
1178
+ </tr>
1179
+ `)}
1180
+ </tbody>
1181
+ </table>
1182
+ </div>
1183
+ `}
1184
+ </div>
1185
+ </div>
1186
+
1187
+ <!-- Add/Edit Job Form Modal -->
1188
+ ${this._formOpen?o`
1189
+ <div class="modal-backdrop" @click=${this._closeForm}>
1190
+ <div class="modal modal--form" @click=${e=>e.stopPropagation()}>
1191
+ <div class="modal__header">
1192
+ <h2 class="modal__title">${this._formMode==="edit"?a("cron.editJob"):a("cron.addJob")}</h2>
1193
+ <button class="btn-icon" @click=${this._closeForm}>${p("x")}</button>
1194
+ </div>
1195
+ <div class="modal__content">
1196
+ <div class="form-field">
1197
+ <label class="form-field__label">${a("cron.name")}</label>
1198
+ <input
1199
+ type="text"
1200
+ class="form-field__input"
1201
+ .value=${this._formName??""}
1202
+ @input=${e=>this._formName=e.target.value}
1203
+ placeholder="${a("cron.namePlaceholder")??"My scheduled task"}"
1204
+ />
1205
+ </div>
1206
+ <div class="form-field">
1207
+ <label class="form-field__label">${a("cron.schedule")}</label>
1208
+ <div style="display: flex; gap: 0.5rem; align-items: center;">
1209
+ <input
1210
+ type="text"
1211
+ class="form-field__input"
1212
+ style="flex: 2; min-width: 0;"
1213
+ .value=${this._formSchedule??"*/5 * * * *"}
1214
+ @input=${e=>this._formSchedule=e.target.value}
1215
+ placeholder="*/5 * * * *"
1216
+ />
1217
+ <select
1218
+ class="form-field__select"
1219
+ style="flex: 1; min-width: 0;"
1220
+ .value=${this._formSchedule??"*/5 * * * *"}
1221
+ @change=${e=>{const t=e.target.value;t&&(this._formSchedule=t)}}
1222
+ >
1223
+ <option value="">${a("cron.schedulePresets.custom")}</option>
1224
+ <option value="*/1 * * * *">${a("cron.schedulePresets.everyMinute")}</option>
1225
+ <option value="*/5 * * * *">${a("cron.schedulePresets.every5Minutes")}</option>
1226
+ <option value="*/10 * * * *">${a("cron.schedulePresets.every10Minutes")}</option>
1227
+ <option value="*/15 * * * *">${a("cron.schedulePresets.every15Minutes")}</option>
1228
+ <option value="*/30 * * * *">${a("cron.schedulePresets.every30Minutes")}</option>
1229
+ <option value="0 * * * *">${a("cron.schedulePresets.everyHour")}</option>
1230
+ <option value="0 */2 * * *">${a("cron.schedulePresets.every2Hours")}</option>
1231
+ <option value="0 */4 * * *">${a("cron.schedulePresets.every4Hours")}</option>
1232
+ <option value="0 */6 * * *">${a("cron.schedulePresets.every6Hours")}</option>
1233
+ <option value="0 */12 * * *">${a("cron.schedulePresets.every12Hours")}</option>
1234
+ <option value="0 0 * * *">${a("cron.schedulePresets.everyDayMidnight")}</option>
1235
+ <option value="0 9 * * *">${a("cron.schedulePresets.everyDay9AM")}</option>
1236
+ <option value="0 21 * * *">${a("cron.schedulePresets.everyDay9PM")}</option>
1237
+ </select>
1238
+ </div>
1239
+ <p class="form-field__hint">
1240
+ ${a("cron.scheduleHintPreset")}
1241
+ </p>
1242
+ </div>
1243
+ <div class="form-field">
1244
+ <label class="form-field__label">${a("cron.mode")}</label>
1245
+ <select
1246
+ class="form-field__select"
1247
+ .value=${this._formSessionTarget??"main"}
1248
+ @change=${e=>this._formSessionTarget=e.target.value}
1249
+ >
1250
+ <option value="main">${a("cron.modeDirectOption")||"Direct (send message directly)"}</option>
1251
+ <option value="isolated">${a("cron.modeAgentOption")||"AI Agent (process with AI then send)"}</option>
1252
+ </select>
1253
+ <p class="form-field__hint">
1254
+ ${this._formSessionTarget==="main"?a("cron.modeDirect"):a("cron.modeAgent")}
1255
+ </p>
1256
+ </div>
1257
+ ${this._formSessionTarget==="isolated"?o`
1258
+ <div class="form-field">
1259
+ <label class="form-field__label">${a("cron.model")}</label>
1260
+ <select
1261
+ class="form-field__select"
1262
+ .value=${this._formModel??""}
1263
+ @change=${e=>this._formModel=e.target.value}
1264
+ >
1265
+ ${this._availableModels.length>0?this._availableModels.map(e=>o`
1266
+ <option value=${e.id}>${e.name} (${e.provider})</option>
1267
+ `):o`
1268
+ <option value="">${a("cron.noConfiguredModels")}</option>
1269
+ `}
1270
+ </select>
1271
+ </div>
1272
+ `:m}
1273
+ <div class="form-field">
1274
+ <label class="form-field__label">Channel</label>
1275
+ <select
1276
+ class="form-field__select"
1277
+ .value=${this._formChannel??"telegram"}
1278
+ @change=${e=>{this._formChannel=e.target.value,this._loadSessionChatIds(),this._formChatId=""}}
1279
+ >
1280
+ ${this._channels.map(e=>o`
1281
+ <option value=${e.name} ?disabled=${!e.enabled}>
1282
+ ${e.name} ${e.enabled?"":"(disabled)"}
1283
+ </option>
1284
+ `)}
1285
+ </select>
1286
+ </div>
1287
+ <div class="form-field">
1288
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;">
1289
+ <label class="form-field__label" style="margin: 0;">Chat ID *</label>
1290
+ <button
1291
+ type="button"
1292
+ class="btn btn-secondary btn-sm"
1293
+ @click=${()=>this._loadSessionChatIds()}
1294
+ title="Refresh chat list"
1295
+ style="padding: 0.25rem 0.5rem; font-size: 0.75rem;"
1296
+ >
1297
+ ${p("refresh")} Refresh
1298
+ </button>
1299
+ </div>
1300
+ <div style="display: flex; gap: 0.5rem; align-items: center;">
1301
+ <input
1302
+ type="text"
1303
+ class="form-field__input"
1304
+ style="flex: 2; min-width: 0;"
1305
+ .value=${this._formChatId??""}
1306
+ @input=${e=>this._formChatId=e.target.value}
1307
+ placeholder="e.g., 123456789"
1308
+ />
1309
+ <select
1310
+ class="form-field__select"
1311
+ style="flex: 1; min-width: 0;"
1312
+ .value=${this._formChatId??""}
1313
+ @change=${e=>{const t=e.target.value;t&&(this._formChatId=t)}}
1314
+ >
1315
+ <option value="">-- Select --</option>
1316
+ ${this._sessionChatIds.length>0?this._sessionChatIds.map(e=>o`
1317
+ <option value=${e.chatId}>
1318
+ ${e.channel}: ${e.chatId} (${this._formatLastActive(e.lastActive)})
1319
+ </option>
1320
+ `):o`
1321
+ <option value="" disabled>No recent chats</option>
1322
+ `}
1323
+ </select>
1324
+ </div>
1325
+ <p class="form-field__hint">
1326
+ ${this._sessionChatIds.length>0?a("cron.enterManuallyOrSelect"):a("cron.noRecentChats")}
1327
+ </p>
1328
+ </div>
1329
+ <div class="form-field">
1330
+ <label class="form-field__label">${a("cron.message")}</label>
1331
+ <textarea
1332
+ class="form-field__textarea"
1333
+ .value=${this._formMessage??""}
1334
+ @input=${e=>this._formMessage=e.target.value}
1335
+ placeholder="${a("cron.messagePlaceholder")??"What should the assistant do?"}"
1336
+ rows="4"
1337
+ ></textarea>
1338
+ </div>
1339
+ </div>
1340
+ <div class="modal__actions">
1341
+ <button class="btn btn-secondary" @click=${this._closeForm}>${a("common.cancel")}</button>
1342
+ <button
1343
+ class="btn btn-primary"
1344
+ @click=${this._submitForm}
1345
+ ?disabled=${this._formSubmitting||!this._formSchedule||!this._formChatId||!this._formMessage}
1346
+ >
1347
+ ${this._formSubmitting?a("common.loading"):this._formMode==="edit"?a("cron.save"):a("cron.create")}
1348
+ </button>
1349
+ </div>
1350
+ </div>
1351
+ </div>
1352
+ `:m}
1353
+
1354
+ <!-- Detail Drawer -->
1355
+ ${this._detailOpen?o`
1356
+ <div class="drawer-backdrop" @click=${this._closeDetail}>
1357
+ <div class="drawer drawer--open" @click=${e=>e.stopPropagation()}>
1358
+ <div class="drawer-header">
1359
+ <div class="drawer-header__info">
1360
+ <div class="drawer-header__title">${this._detailJob?.name||this._detailJob?.id}</div>
1361
+ </div>
1362
+ <button class="btn-icon" @click=${this._closeDetail}>${p("x")}</button>
1363
+ </div>
1364
+ <div class="drawer-content ${this._detailLoading?"drawer-content--loading":""}">
1365
+ ${this._detailLoading?o`
1366
+ <div class="spinner"></div>
1367
+ `:o`
1368
+ <div class="session-detail">
1369
+ <div class="session-detail__row">
1370
+ <span class="session-detail__label">${a("cron.scheduleLabel")}</span>
1371
+ <code>${this._detailJob?.schedule}</code>
1372
+ </div>
1373
+ <div class="session-detail__row">
1374
+ <span class="session-detail__label">${a("cron.messageLabel")}</span>
1375
+ <span>${this._detailJob?.message}</span>
1376
+ </div>
1377
+ <div class="session-detail__row">
1378
+ <span class="session-detail__label">${a("cron.status")}</span>
1379
+ <span>${this._detailJob?.enabled?a("cron.enabled"):a("cron.disabled")}</span>
1380
+ </div>
1381
+ <div class="session-detail__row">
1382
+ <span class="session-detail__label">${a("cron.nextRun")}</span>
1383
+ <span>${this._detailJob?.next_run?this._formatNextRun(this._detailJob.next_run):"N/A"}</span>
1384
+ </div>
1385
+ </div>
1386
+ `}
1387
+ </div>
1388
+ </div>
1389
+ </div>
1390
+ `:m}
1391
+
1392
+ <!-- Confirm Dialog -->
1393
+ <confirm-dialog
1394
+ .open=${this._confirmOpen}
1395
+ .title=${this._confirmTitle}
1396
+ .message=${this._confirmMessage}
1397
+ .confirmText=${this._confirmAction==="delete"?a("cron.delete"):a("cron.runNow")}
1398
+ .cancelText=${a("common.cancel")}
1399
+ .type=${this._confirmAction==="delete"?"danger":"warning"}
1400
+ @confirm=${this._handleConfirm}
1401
+ ></confirm-dialog>
1402
+ `}_formatNextRun(e){const t=typeof e=="string"?new Date(e):e,s=new Date,i=t.getTime()-s.getTime();if(i<0)return a("cron.timeLabels.overdue");if(i<6e4)return a("cron.timeLabels.lessThanMinute");if(i<36e5){const n=Math.floor(i/6e4);return a("cron.timeLabels.minutes",{count:n})}if(i<864e5){const n=Math.floor(i/36e5);return a("cron.timeLabels.hours",{count:n})}return t.toLocaleString()}_formatLastActive(e){const t=new Date(e),i=new Date().getTime()-t.getTime();if(i<0||i<6e4)return a("cron.lastActiveLabels.justNow");if(i<36e5){const n=Math.floor(i/6e4);return a("cron.lastActiveLabels.minutesAgo",{count:n})}if(i<864e5){const n=Math.floor(i/36e5);return a("cron.lastActiveLabels.hoursAgo",{count:n})}if(i<6048e5){const n=Math.floor(i/864e5);return a("cron.lastActiveLabels.daysAgo",{count:n})}return t.toLocaleDateString()}_formatTime(e){return new Date(e).toLocaleString()}};v([u({attribute:!1})],_.prototype,"config",2);v([c()],_.prototype,"_jobs",2);v([c()],_.prototype,"_metrics",2);v([c()],_.prototype,"_channels",2);v([c()],_.prototype,"_availableModels",2);v([c()],_.prototype,"_defaultModel",2);v([c()],_.prototype,"_sessionChatIds",2);v([c()],_.prototype,"_loading",2);v([c()],_.prototype,"_error",2);v([c()],_.prototype,"_formOpen",2);v([c()],_.prototype,"_formMode",2);v([c()],_.prototype,"_formJobId",2);v([c()],_.prototype,"_formName",2);v([c()],_.prototype,"_formSchedule",2);v([c()],_.prototype,"_formChannel",2);v([c()],_.prototype,"_formChatId",2);v([c()],_.prototype,"_formMessage",2);v([c()],_.prototype,"_formSessionTarget",2);v([c()],_.prototype,"_formModel",2);v([c()],_.prototype,"_formSubmitting",2);v([c()],_.prototype,"_detailOpen",2);v([c()],_.prototype,"_detailJob",2);v([c()],_.prototype,"_detailHistory",2);v([c()],_.prototype,"_detailLoading",2);v([c()],_.prototype,"_confirmOpen",2);v([c()],_.prototype,"_confirmTitle",2);v([c()],_.prototype,"_confirmMessage",2);v([c()],_.prototype,"_confirmJobId",2);v([c()],_.prototype,"_confirmAction",2);_=v([k("cron-manager")],_);const ti=["trace","debug","info","warn","error","fatal"],fe={trace:"#9ca3af",debug:"#6b7280",info:"#3b82f6",warn:"#f59e0b",error:"#ef4444",fatal:"#dc2626"};class si{constructor(t,s){this.baseUrl=t.replace(/\/$/,""),this.token=s}async request(t,s,i){const n={"Content-Type":"application/json"};this.token&&(n.Authorization=`Bearer ${this.token}`);const r=await fetch(`${this.baseUrl}${s}`,{method:t,headers:n,body:i?JSON.stringify(i):void 0});if(!r.ok){const l=await r.json().catch(()=>({error:"Request failed"}));throw new Error(l.error||`HTTP ${r.status}`)}return r.json()}async queryLogs(t){const s=new URLSearchParams;t?.level?.length&&s.set("level",t.level.join(",")),t?.from&&s.set("from",t.from),t?.to&&s.set("to",t.to),t?.q&&s.set("q",t.q),t?.module&&s.set("module",t.module),t?.limit&&s.set("limit",String(t.limit)),t?.offset&&s.set("offset",String(t.offset));const i=s.toString(),n=`/api/logs${i?`?${i}`:""}`;return await this.request("GET",n)}async getLogFiles(){return(await this.request("GET","/api/logs/files")).files||[]}async getLogStats(){return await this.request("GET","/api/logs/stats")}async getLogLevels(){return(await this.request("GET","/api/logs/levels")).levels||[]}async getLogModules(){return(await this.request("GET","/api/logs/modules")).modules||[]}async getLogDir(){return(await this.request("GET","/api/logs/dir")).dir}}var ii=Object.defineProperty,ni=Object.getOwnPropertyDescriptor,C=(e,t,s,i)=>{for(var n=i>1?void 0:i?ni(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&ii(t,s,n),n};let $=class extends y{constructor(){super(...arguments),this._logs=[],this._loading=!1,this._hasMore=!1,this._files=[],this._modules=[],this._showFilesPanel=!1,this._selectedLevels=new Set,this._searchQuery="",this._selectedModule="",this._dateFrom="",this._dateTo="",this._offset=0,this._error=null,this._selectedLog=null,this._autoRefresh=!1,this._limit=50,this._initialized=!1,this._debouncedSearch=this._debounce(()=>{this._loadLogs(!0)},300)}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._tryInitialize()}willUpdate(e){super.willUpdate(e),e.has("config")&&this._tryInitialize()}disconnectedCallback(){super.disconnectedCallback(),this._stopAutoRefresh()}firstUpdated(){this._tryInitialize()}_tryInitialize(){if(this._initialized||!this.config?.url)return;const e=this.config.url.replace(/\/+$/,"");this._api=new si(e,this.config.token),this._initialized=!0,this._loadLogs(),this._loadFiles(),this._loadModules()}async _loadLogs(e=!1){if(!this._loading){this._loading=!0,this._error=null,e&&(this._offset=0,this._logs=[]);try{const t={level:this._selectedLevels.size>0?Array.from(this._selectedLevels):void 0,from:this._dateFrom||void 0,to:this._dateTo||void 0,q:this._searchQuery||void 0,module:this._selectedModule||void 0,limit:this._limit,offset:this._offset},s=await this._api.queryLogs(t);e?this._logs=s.logs:this._logs=[...this._logs,...s.logs],console.log("[LogManager] Total logs in state:",this._logs.length),this._hasMore=s.logs.length===this._limit,this._offset=this._offset+s.logs.length}catch(t){this._error=t instanceof Error?t.message:"Failed to load logs",console.error("[LogManager] Load error:",t)}finally{this._loading=!1}}}async _loadFiles(){try{this._files=await this._api.getLogFiles()}catch(e){console.error("[LogManager] Files error:",e)}}async _loadModules(){try{this._modules=await this._api.getLogModules()}catch(e){console.error("[LogManager] Modules error:",e)}}_toggleLevel(e){this._selectedLevels.has(e)?this._selectedLevels.delete(e):this._selectedLevels.add(e),this._selectedLevels=new Set(this._selectedLevels),this._loadLogs(!0)}_handleSearch(e){const t=e.target;this._searchQuery=t.value,this._debouncedSearch()}_debounce(e,t){let s;return()=>{clearTimeout(s),s=setTimeout(e,t)}}_handleModuleChange(e){const t=e.target;this._selectedModule=t.value,this._loadLogs(!0)}_handleDateFromChange(e){const t=e.target;this._dateFrom=t.value,this._loadLogs(!0)}_handleDateToChange(e){const t=e.target;this._dateTo=t.value,this._loadLogs(!0)}_clearFilters(){this._selectedLevels.clear(),this._selectedLevels=new Set,this._searchQuery="",this._selectedModule="",this._dateFrom="",this._dateTo="",this._loadLogs(!0)}_selectLog(e){this._selectedLog=e}_closeDetail(){this._selectedLog=null}_toggleAutoRefresh(){this._autoRefresh=!this._autoRefresh,this._autoRefresh?this._startAutoRefresh():this._stopAutoRefresh()}_startAutoRefresh(){this._refreshInterval=window.setInterval(()=>{this._loadLogs(!0)},5e3)}_stopAutoRefresh(){this._refreshInterval&&(clearInterval(this._refreshInterval),this._refreshInterval=void 0)}_handleLoadMore(){this._loadLogs()}_formatTimestamp(e){try{return new Date(e).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return e}}_formatFileSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}render(){return o`
1403
+ <div class="log-manager">
1404
+ ${this._renderHeader()}
1405
+ <div class="log-manager__main">
1406
+ ${this._renderFilters()}
1407
+ ${this._renderLogTable()}
1408
+ ${this._renderFilesPanel()}
1409
+ </div>
1410
+ ${this._error?o`<div class="error-banner">${this._error}</div>`:""}
1411
+ </div>
1412
+
1413
+ ${this._selectedLog?this._renderDetailDrawer():""}
1414
+ `}_renderHeader(){return o`
1415
+ <div class="log-manager__header">
1416
+ <div class="log-manager__title">
1417
+ <span class="title-icon">${p("fileText")}</span>
1418
+ <div class="title-text">
1419
+ <h1>${a("logs.title")}</h1>
1420
+ <span class="title-subtitle">System logs and diagnostics</span>
1421
+ </div>
1422
+ </div>
1423
+ <div class="log-manager__actions">
1424
+ <button
1425
+ class="btn-icon"
1426
+ @click=${this._toggleFilesPanel}
1427
+ title="Toggle log files"
1428
+ >
1429
+ ${p("folder")}
1430
+ ${this._files.length>0?o`<span class="badge">${this._files.length}</span>`:""}
1431
+ </button>
1432
+ <button
1433
+ class="btn-icon ${this._autoRefresh?"btn-icon--active":""}"
1434
+ @click=${this._toggleAutoRefresh}
1435
+ title=${this._autoRefresh?a("logs.pause"):a("logs.autoRefresh")}
1436
+ >
1437
+ ${p(this._autoRefresh?"pause":"play")}
1438
+ </button>
1439
+ <button
1440
+ class="btn-icon"
1441
+ @click=${()=>this._loadLogs(!0)}
1442
+ title=${a("logs.refresh")}
1443
+ >
1444
+ ${p("refreshCw")}
1445
+ </button>
1446
+ </div>
1447
+ </div>
1448
+ `}_renderFilters(){return o`
1449
+ <div class="log-manager__filters">
1450
+ <div class="filter-group">
1451
+ <label class="filter-label">${a("logs.level")}</label>
1452
+ <div class="level-filters">
1453
+ ${ti.map(e=>o`
1454
+ <button
1455
+ class="level-badge ${this._selectedLevels.has(e)?"level-badge--active":""}"
1456
+ style="--level-color: ${fe[e]}"
1457
+ @click=${()=>this._toggleLevel(e)}
1458
+ >
1459
+ ${e}
1460
+ </button>
1461
+ `)}
1462
+ </div>
1463
+ </div>
1464
+
1465
+ <div class="filter-group">
1466
+ <label class="filter-label">${a("logs.search")}</label>
1467
+ <div class="search-box">
1468
+ ${p("search")}
1469
+ <input
1470
+ type="text"
1471
+ placeholder="${a("logs.searchPlaceholder")}"
1472
+ .value=${this._searchQuery}
1473
+ @input=${this._handleSearch}
1474
+ />
1475
+ </div>
1476
+ </div>
1477
+
1478
+ <div class="filter-row">
1479
+ <div class="filter-group">
1480
+ <label class="filter-label">Module</label>
1481
+ <select @change=${this._handleModuleChange}>
1482
+ <option value="">All modules</option>
1483
+ ${this._modules.map(e=>o`<option value="${e}">${e}</option>`)}
1484
+ </select>
1485
+ </div>
1486
+
1487
+ <div class="filter-group">
1488
+ <label class="filter-label">From</label>
1489
+ <input
1490
+ type="datetime-local"
1491
+ .value=${this._dateFrom}
1492
+ @input=${this._handleDateFromChange}
1493
+ />
1494
+ </div>
1495
+
1496
+ <div class="filter-group">
1497
+ <label class="filter-label">To</label>
1498
+ <input
1499
+ type="datetime-local"
1500
+ .value=${this._dateTo}
1501
+ @input=${this._handleDateToChange}
1502
+ />
1503
+ </div>
1504
+
1505
+ <button class="btn btn-ghost" @click=${this._clearFilters}>
1506
+ ${p("x")}
1507
+ Clear
1508
+ </button>
1509
+ </div>
1510
+ </div>
1511
+ `}_renderLogTable(){return this._loading&&this._logs.length===0?this._renderLoading():this._logs.length===0?o`
1512
+ <div class="log-manager__empty">
1513
+ <div class="empty-state">
1514
+ <div class="empty-state__icon">${p("fileText")}</div>
1515
+ <div class="empty-state__title">${a("logs.noLogs")}</div>
1516
+ <div class="empty-state__description">
1517
+ ${a("logs.noLogsDescription")}
1518
+ </div>
1519
+ </div>
1520
+ </div>
1521
+ `:o`
1522
+ <div class="log-table-container">
1523
+ <table class="log-table">
1524
+ <thead>
1525
+ <tr>
1526
+ <th>${a("logs.time")}</th>
1527
+ <th>${a("logs.level")}</th>
1528
+ <th>${a("logs.module")}</th>
1529
+ <th>${a("logs.message")}</th>
1530
+ </tr>
1531
+ </thead>
1532
+ <tbody>
1533
+ ${this._logs.length===0?o`
1534
+ <tr>
1535
+ <td colspan="4" style="padding: 2rem; text-align: center; color: var(--text-muted);">
1536
+ No logs to display
1537
+ </td>
1538
+ </tr>
1539
+ `:this._logs.map(e=>o`
1540
+ <tr class="log-row log-row--${e.level||"info"}" @click=${()=>this._selectLog(e)}>
1541
+ <td class="log-cell log-cell--time">${this._formatTimestamp(e.timestamp)}</td>
1542
+ <td class="log-cell log-cell--level">
1543
+ <span
1544
+ class="level-badge level-badge--small"
1545
+ style="--level-color: ${fe[e.level]||fe.info}"
1546
+ >
1547
+ ${e.level||"info"}
1548
+ </span>
1549
+ </td>
1550
+ <td class="log-cell log-cell--module">${e.module||e.prefix||e.service||"-"}</td>
1551
+ <td class="log-cell log-cell--message">${e.message||JSON.stringify(e)}</td>
1552
+ </tr>
1553
+ `)}
1554
+ </tbody>
1555
+ </table>
1556
+
1557
+ ${this._hasMore?o`
1558
+ <div class="log-table__load-more">
1559
+ <button class="btn btn-secondary" @click=${this._handleLoadMore} ?disabled=${this._loading}>
1560
+ ${this._loading?o`<span class="spinner"></span>`:p("chevronDown")}
1561
+ Load More
1562
+ </button>
1563
+ </div>
1564
+ `:""}
1565
+ </div>
1566
+ `}_toggleFilesPanel(){this._showFilesPanel=!this._showFilesPanel}_renderFilesPanel(){return o`
1567
+ ${this._showFilesPanel?o`
1568
+ <div class="drawer-overlay" @click=${this._toggleFilesPanel}></div>
1569
+ `:""}
1570
+ <div class="files-panel ${this._showFilesPanel?"files-panel--open":""}">
1571
+ <div class="files-panel__header">
1572
+ <span class="files-panel__title">
1573
+ ${p("folder")}
1574
+ Log Files
1575
+ </span>
1576
+ <button class="btn btn-icon" @click=${this._toggleFilesPanel}>
1577
+ ${p("x")}
1578
+ </button>
1579
+ </div>
1580
+ <div class="files-panel__content">
1581
+ ${this._files.length===0?o`
1582
+ <div class="files-panel__empty">No log files found</div>
1583
+ `:o`
1584
+ <div class="file-list">
1585
+ ${this._files.map(e=>o`
1586
+ <div class="file-item">
1587
+ <span class="file-name">${p("file")}${e.name}</span>
1588
+ <span class="file-meta">
1589
+ <span class="file-size">${this._formatFileSize(e.size)}</span>
1590
+ <span class="file-time">${this._formatTimestamp(e.modified)}</span>
1591
+ </span>
1592
+ </div>
1593
+ `)}
1594
+ </div>
1595
+ `}
1596
+ </div>
1597
+ </div>
1598
+ `}_renderDetailDrawer(){if(!this._selectedLog)return"";const e=this._selectedLog;return o`
1599
+ <div class="drawer-overlay" @click=${this._closeDetail}></div>
1600
+ <div class="drawer drawer--right">
1601
+ <div class="drawer-header">
1602
+ <h3 class="drawer-header__title">${a("logs.details")}</h3>
1603
+ <button class="btn btn-icon" @click=${this._closeDetail}>${p("x")}</button>
1604
+ </div>
1605
+ <div class="drawer__content">
1606
+ <div class="log-detail">
1607
+ <div class="log-detail__field">
1608
+ <label>${a("logs.time")}</label>
1609
+ <code>${e.timestamp}</code>
1610
+ </div>
1611
+ <div class="log-detail__field">
1612
+ <label>${a("logs.level")}</label>
1613
+ <span
1614
+ class="level-badge"
1615
+ style="--level-color: ${fe[e.level]}"
1616
+ >
1617
+ ${e.level}
1618
+ </span>
1619
+ </div>
1620
+ <div class="log-detail__field">
1621
+ <label>${a("logs.module")}</label>
1622
+ <code>${e.module}</code>
1623
+ </div>
1624
+ <div class="log-detail__field">
1625
+ <label>${a("logs.message")}</label>
1626
+ <pre class="log-detail__message">${e.message}</pre>
1627
+ </div>
1628
+ ${e.meta?o`
1629
+ <div class="log-detail__field">
1630
+ <label>Metadata</label>
1631
+ <pre class="log-detail__meta">${JSON.stringify(e.meta,null,2)}</pre>
1632
+ </div>
1633
+ `:""}
1634
+ </div>
1635
+ </div>
1636
+ </div>
1637
+ `}_renderLoading(){return o`
1638
+ <div class="log-manager__loading">
1639
+ <div class="skeleton-table">
1640
+ ${Array.from({length:10}).map(()=>o`
1641
+ <div class="skeleton-row">
1642
+ <div class="skeleton skeleton--time"></div>
1643
+ <div class="skeleton skeleton--level"></div>
1644
+ <div class="skeleton skeleton--module"></div>
1645
+ <div class="skeleton skeleton--message"></div>
1646
+ </div>
1647
+ `)}
1648
+ </div>
1649
+ </div>
1650
+ `}};C([u({attribute:!1})],$.prototype,"config",2);C([c()],$.prototype,"_logs",2);C([c()],$.prototype,"_loading",2);C([c()],$.prototype,"_hasMore",2);C([c()],$.prototype,"_files",2);C([c()],$.prototype,"_modules",2);C([c()],$.prototype,"_showFilesPanel",2);C([c()],$.prototype,"_selectedLevels",2);C([c()],$.prototype,"_searchQuery",2);C([c()],$.prototype,"_selectedModule",2);C([c()],$.prototype,"_dateFrom",2);C([c()],$.prototype,"_dateTo",2);C([c()],$.prototype,"_offset",2);C([c()],$.prototype,"_error",2);C([c()],$.prototype,"_selectedLog",2);C([c()],$.prototype,"_autoRefresh",2);C([c()],$.prototype,"_refreshInterval",2);$=C([k("log-manager")],$);var oi=Object.defineProperty,ri=Object.getOwnPropertyDescriptor,D=(e,t,s,i)=>{for(var n=i>1?void 0:i?ri(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&oi(t,s,n),n};let P=class extends y{constructor(){super(...arguments),this._activeSection="agent",this._loading=!1,this._saving=!1,this._dirtyFields=new Set,this._errors=new Map,this._saveSuccess=!1,this._models=[],this._values={model:"anthropic/claude-sonnet-4-5",maxTokens:8192,temperature:.7,maxToolIterations:20,telegramEnabled:!1,telegramToken:"",telegramApiRoot:"",telegramDebug:!1,telegramAllowFrom:"",whatsappEnabled:!1,whatsappBridgeUrl:"ws://localhost:3001",whatsappAllowFrom:"",heartbeatEnabled:!0,heartbeatIntervalMs:6e4,openaiApiKey:"",anthropicApiKey:"",googleApiKey:"",qwenApiKey:"",kimiApiKey:"",minimaxApiKey:"",deepseekApiKey:"",grokApiKey:"",openrouterApiKey:"",workspace:"",theme:"system"},this._initialized=!1}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._tryInitialize()}willUpdate(e){super.willUpdate(e),e.has("config")&&this._tryInitialize()}_tryInitialize(){this.config?.url&&this._loadSettings()}get _sections(){const e=this._models.map(t=>({value:t.id,label:`${t.provider}/${t.name}`}));return[{id:"agent",title:a("settings.sections.agent"),icon:"bot",fields:[{key:"model",label:a("settings.fields.model"),type:"select",description:a("settings.descriptionsFields.model"),options:e},{key:"workspace",label:a("settings.fields.workspace"),type:"text",description:a("settings.descriptionsFields.workspace"),placeholder:a("settings.placeholders.workspace")},{key:"maxTokens",label:a("settings.fields.maxTokens"),type:"number",description:a("settings.descriptionsFields.maxTokens"),validation:{min:256,max:128e3}},{key:"temperature",label:a("settings.fields.temperature"),type:"number",description:a("settings.descriptionsFields.temperature"),validation:{min:0,max:2}},{key:"maxToolIterations",label:a("settings.fields.maxToolIterations"),type:"number",description:a("settings.descriptionsFields.maxToolIterations"),validation:{min:1,max:100}}]},{id:"providers",title:a("settings.sections.providers"),icon:"cloud",fields:[{key:"openaiApiKey",label:a("settings.fields.openaiApiKey"),type:"password",description:a("settings.descriptionsFields.openaiApiKey"),placeholder:a("settings.placeholders.openaiApiKey")},{key:"anthropicApiKey",label:a("settings.fields.anthropicApiKey"),type:"password",description:a("settings.descriptionsFields.anthropicApiKey"),placeholder:a("settings.placeholders.anthropicApiKey")},{key:"googleApiKey",label:a("settings.fields.googleApiKey"),type:"password",description:a("settings.descriptionsFields.googleApiKey"),placeholder:a("settings.placeholders.googleApiKey")},{key:"qwenApiKey",label:a("settings.fields.qwenApiKey"),type:"password",description:a("settings.descriptionsFields.qwenApiKey"),placeholder:a("settings.placeholders.qwenApiKey")},{key:"kimiApiKey",label:a("settings.fields.kimiApiKey"),type:"password",description:a("settings.descriptionsFields.kimiApiKey"),placeholder:a("settings.placeholders.kimiApiKey")},{key:"minimaxApiKey",label:a("settings.fields.minimaxApiKey"),type:"password",description:a("settings.descriptionsFields.minimaxApiKey"),placeholder:a("settings.placeholders.minimaxApiKey")},{key:"deepseekApiKey",label:a("settings.fields.deepseekApiKey"),type:"password",description:a("settings.descriptionsFields.deepseekApiKey"),placeholder:a("settings.placeholders.deepseekApiKey")},{key:"openrouterApiKey",label:a("settings.fields.openrouterApiKey"),type:"password",description:a("settings.descriptionsFields.openrouterApiKey"),placeholder:a("settings.placeholders.openrouterApiKey")}]},{id:"channels",title:a("settings.sections.channels"),icon:"plug",fields:[{key:"telegramEnabled",label:a("settings.fields.telegramEnabled"),type:"boolean",description:a("settings.descriptionsFields.telegramEnabled")},...this._values.telegramEnabled?[{key:"telegramToken",label:a("settings.fields.telegramToken"),type:"password",description:a("settings.descriptionsFields.telegramToken"),placeholder:a("settings.placeholders.telegramToken")},{key:"telegramApiRoot",label:a("settings.fields.telegramApiRoot"),type:"text",description:a("settings.descriptionsFields.telegramApiRoot"),placeholder:a("settings.placeholders.telegramApiRoot")},{key:"telegramAllowFrom",label:a("settings.fields.telegramAllowFrom"),type:"text",description:a("settings.descriptionsFields.telegramAllowFrom"),placeholder:a("settings.placeholders.telegramAllowFrom")},{key:"telegramDebug",label:a("settings.fields.telegramDebug"),type:"boolean",description:a("settings.descriptionsFields.telegramDebug")}]:[],{key:"whatsappEnabled",label:a("settings.fields.whatsappEnabled"),type:"boolean",description:a("settings.descriptionsFields.whatsappEnabled")},...this._values.whatsappEnabled?[{key:"whatsappBridgeUrl",label:a("settings.fields.whatsappBridgeUrl"),type:"text",description:a("settings.descriptionsFields.whatsappBridgeUrl"),placeholder:a("settings.placeholders.whatsappBridgeUrl")},{key:"whatsappAllowFrom",label:a("settings.fields.whatsappAllowFrom"),type:"text",description:a("settings.descriptionsFields.whatsappAllowFrom"),placeholder:a("settings.placeholders.whatsappAllowFrom")}]:[]]},{id:"gateway",title:a("settings.sections.gateway"),icon:"globe",fields:[{key:"heartbeatEnabled",label:a("settings.fields.heartbeatEnabled"),type:"boolean",description:a("settings.descriptionsFields.heartbeatEnabled")},{key:"heartbeatIntervalMs",label:a("settings.fields.heartbeatIntervalMs"),type:"number",description:a("settings.descriptionsFields.heartbeatIntervalMs"),validation:{min:1e3,max:6e5}}]}]}async _loadSettings(){if(!this.config?.url)return;this._loading=!0;const{url:e,token:t}=this.config;try{await this._loadModels();const s=await fetch(`${e}/api/config`,{headers:t?{Authorization:`Bearer ${t}`}:{}});if(s.ok){const n=(await s.json()).payload?.config;if(n){let r=n.agents?.defaults?.model;r&&typeof r=="object"&&(r=r.primary||""),this._values={...this._values,model:r||"anthropic/claude-sonnet-4-5",workspace:n.agents?.defaults?.workspace||"",maxTokens:n.agents?.defaults?.maxTokens||8192,temperature:n.agents?.defaults?.temperature??.7,maxToolIterations:n.agents?.defaults?.maxToolIterations||20,openaiApiKey:n.providers?.openai?.apiKey||"",anthropicApiKey:n.providers?.anthropic?.apiKey||"",googleApiKey:n.providers?.google?.apiKey||"",qwenApiKey:n.providers?.qwen?.apiKey||"",kimiApiKey:n.providers?.kimi?.apiKey||"",minimaxApiKey:n.providers?.minimax?.apiKey||"",deepseekApiKey:n.providers?.deepseek?.apiKey||"",openrouterApiKey:n.providers?.openrouter?.apiKey||"",telegramEnabled:n.channels?.telegram?.enabled||!1,telegramToken:n.channels?.telegram?.token||"",telegramApiRoot:n.channels?.telegram?.apiRoot||"",telegramDebug:n.channels?.telegram?.debug||!1,telegramAllowFrom:(n.channels?.telegram?.allowFrom||[]).join(", "),whatsappEnabled:n.channels?.whatsapp?.enabled||!1,whatsappBridgeUrl:n.channels?.whatsapp?.bridgeUrl||"ws://localhost:3001",whatsappAllowFrom:(n.channels?.whatsapp?.allowFrom||[]).join(", "),heartbeatEnabled:n.gateway?.heartbeat?.enabled??!0,heartbeatIntervalMs:n.gateway?.heartbeat?.intervalMs||6e4}}}}catch(s){console.error("Failed to load settings:",s)}finally{this._loading=!1}}async _loadModels(){if(this.config?.url)try{const{url:e,token:t}=this.config,s=await fetch(`${e}/api/models`,{headers:t?{Authorization:`Bearer ${t}`}:{}});if(s.ok){const i=await s.json();i.payload?.models&&(this._models=i.payload.models)}}catch(e){console.error("Failed to load models:",e)}}async _saveSettings(){if(!this.config?.url||this._errors.size>0)return;this._saving=!0,this._saveSuccess=!1;const{url:e,token:t}=this.config,s={};(this._dirtyFields.has("model")||this._dirtyFields.has("maxTokens")||this._dirtyFields.has("temperature")||this._dirtyFields.has("maxToolIterations")||this._dirtyFields.has("workspace"))&&(s.agents={defaults:{}},this._dirtyFields.has("model")&&(s.agents.defaults.model=this._values.model),this._dirtyFields.has("workspace")&&(s.agents.defaults.workspace=this._values.workspace),this._dirtyFields.has("maxTokens")&&(s.agents.defaults.maxTokens=Number(this._values.maxTokens)),this._dirtyFields.has("temperature")&&(s.agents.defaults.temperature=Number(this._values.temperature)),this._dirtyFields.has("maxToolIterations")&&(s.agents.defaults.maxToolIterations=Number(this._values.maxToolIterations))),["openaiApiKey","anthropicApiKey","googleApiKey","qwenApiKey","kimiApiKey","minimaxApiKey","deepseekApiKey","openrouterApiKey"].filter(r=>this._dirtyFields.has(r)).length>0&&(s.providers={},this._dirtyFields.has("openaiApiKey")&&(s.providers.openai={apiKey:this._values.openaiApiKey}),this._dirtyFields.has("anthropicApiKey")&&(s.providers.anthropic={apiKey:this._values.anthropicApiKey}),this._dirtyFields.has("googleApiKey")&&(s.providers.google={apiKey:this._values.googleApiKey}),this._dirtyFields.has("qwenApiKey")&&(s.providers.qwen={apiKey:this._values.qwenApiKey}),this._dirtyFields.has("kimiApiKey")&&(s.providers.kimi={apiKey:this._values.kimiApiKey}),this._dirtyFields.has("minimaxApiKey")&&(s.providers.minimax={apiKey:this._values.minimaxApiKey}),this._dirtyFields.has("deepseekApiKey")&&(s.providers.deepseek={apiKey:this._values.deepseekApiKey}),this._dirtyFields.has("openrouterApiKey")&&(s.providers.openrouter={apiKey:this._values.openrouterApiKey})),(this._dirtyFields.has("telegramEnabled")||this._dirtyFields.has("whatsappEnabled")||this._dirtyFields.has("telegramToken")||this._dirtyFields.has("telegramApiRoot")||this._dirtyFields.has("telegramDebug")||this._dirtyFields.has("telegramAllowFrom")||this._dirtyFields.has("whatsappBridgeUrl")||this._dirtyFields.has("whatsappAllowFrom"))&&(s.channels={},(this._dirtyFields.has("telegramEnabled")||this._dirtyFields.has("telegramToken")||this._dirtyFields.has("telegramApiRoot")||this._dirtyFields.has("telegramDebug")||this._dirtyFields.has("telegramAllowFrom"))&&(s.channels={...s.channels,telegram:{}},this._dirtyFields.has("telegramEnabled")&&(s.channels.telegram.enabled=!!this._values.telegramEnabled),this._dirtyFields.has("telegramToken")&&(s.channels.telegram.token=this._values.telegramToken),this._dirtyFields.has("telegramApiRoot")&&(s.channels.telegram.apiRoot=this._values.telegramApiRoot||void 0),this._dirtyFields.has("telegramDebug")&&(s.channels.telegram.debug=!!this._values.telegramDebug),this._dirtyFields.has("telegramAllowFrom")&&(s.channels.telegram.allowFrom=this._values.telegramAllowFrom?this._values.telegramAllowFrom.split(",").map(r=>r.trim()).filter(r=>r):[])),(this._dirtyFields.has("whatsappEnabled")||this._dirtyFields.has("whatsappBridgeUrl")||this._dirtyFields.has("whatsappAllowFrom"))&&(s.channels={...s.channels,whatsapp:{}},this._dirtyFields.has("whatsappEnabled")&&(s.channels.whatsapp.enabled=!!this._values.whatsappEnabled),this._dirtyFields.has("whatsappBridgeUrl")&&(s.channels.whatsapp.bridgeUrl=this._values.whatsappBridgeUrl),this._dirtyFields.has("whatsappAllowFrom")&&(s.channels.whatsapp.allowFrom=this._values.whatsappAllowFrom?this._values.whatsappAllowFrom.split(",").map(r=>r.trim()).filter(r=>r):[]))),(this._dirtyFields.has("heartbeatEnabled")||this._dirtyFields.has("heartbeatIntervalMs"))&&(s.gateway={heartbeat:{}},this._dirtyFields.has("heartbeatEnabled")&&(s.gateway.heartbeat.enabled=!!this._values.heartbeatEnabled),this._dirtyFields.has("heartbeatIntervalMs")&&(s.gateway.heartbeat.intervalMs=Number(this._values.heartbeatIntervalMs)));try{const r=await fetch(`${e}/api/config`,{method:"PATCH",headers:{"Content-Type":"application/json",...t?{Authorization:`Bearer ${t}`}:{}},body:JSON.stringify(s)});if(!r.ok){const l=await r.json();throw new Error(l.error||"Failed to save settings")}this._dirtyFields.clear(),this._saveSuccess=!0,setTimeout(()=>{this._saveSuccess=!1},3e3)}catch(r){console.error("Failed to save settings:",r),alert(r instanceof Error?r.message:"Failed to save settings")}finally{this._saving=!1}}_handleInput(e,t){this._values={...this._values,[e]:t},this._dirtyFields.add(e),this.requestUpdate()}render(){return o`
1651
+ <div class="settings-page">
1652
+ <div class="settings-sidebar">
1653
+ <div class="sidebar-header">
1654
+ <h3>${a("settings.title")}</h3>
1655
+ </div>
1656
+ <nav class="sidebar-nav">
1657
+ ${this._sections.map(e=>o`
1658
+ <button
1659
+ class="nav-item ${this._activeSection===e.id?"active":""}"
1660
+ @click=${()=>this._activeSection=e.id}
1661
+ >
1662
+ ${p(e.icon)}
1663
+ <span>${e.title}</span>
1664
+ </button>
1665
+ `)}
1666
+ </nav>
1667
+ </div>
1668
+
1669
+ <div class="settings-main">
1670
+ ${this._loading?o`
1671
+ <div class="loading-state">
1672
+ <div class="spinner"></div>
1673
+ <p>${a("settings.loading")}</p>
1674
+ </div>
1675
+ `:this._renderSection()}
1676
+ </div>
1677
+
1678
+ <!-- Save button floating -->
1679
+ ${this._dirtyFields.size>0?o`
1680
+ <div class="floating-save">
1681
+ <span class="dirty-count">${a("settings.unsaved",{count:this._dirtyFields.size})}</span>
1682
+ <button
1683
+ class="btn btn-primary"
1684
+ ?disabled=${this._saving||this._errors.size>0}
1685
+ @click=${this._saveSettings}
1686
+ >
1687
+ ${this._saving?o`
1688
+ <span class="spinner-sm"></span>
1689
+ ${a("settings.saving")}
1690
+ `:o`
1691
+ <span>${p("save")}</span>
1692
+ ${a("settings.saveChanges")}
1693
+ `}
1694
+ </button>
1695
+ </div>
1696
+ `:""}
1697
+ </div>
1698
+ `}_renderSection(){const e=this._sections.find(s=>s.id===this._activeSection);if(!e)return o`<div>${a("settings.noSection")}</div>`;const t=`settings.descriptions.${e.id}`;return o`
1699
+ <div class="section-content">
1700
+ <div class="section-header">
1701
+ <h2>${e.title}</h2>
1702
+ <p class="section-desc">${a(t)}</p>
1703
+ </div>
1704
+
1705
+ <div class="fields-grid">
1706
+ ${e.fields.map(s=>this._renderField(s))}
1707
+ </div>
1708
+ </div>
1709
+ `}_renderField(e){const t=this._values[e.key],s=this._errors.get(e.key);return o`
1710
+ <div class="field-group ${s?"has-error":""}">
1711
+ <div class="field-header">
1712
+ <label class="field-label">${e.label}</label>
1713
+ ${e.validation?.required?o`<span class="required-mark">*</span>`:""}
1714
+ </div>
1715
+
1716
+ ${e.description?o`<p class="field-desc">${e.description}</p>`:""}
1717
+
1718
+ ${e.type==="boolean"?this._renderBooleanField(e,t):""}
1719
+ ${e.type==="select"?this._renderSelectField(e,t):""}
1720
+ ${["text","password","number"].includes(e.type)?this._renderInputField(e,t):""}
1721
+
1722
+ ${s?o`
1723
+ <div class="field-error">
1724
+ <span>${s}</span>
1725
+ </div>
1726
+ `:""}
1727
+ </div>
1728
+ `}_renderInputField(e,t){return o`
1729
+ <input
1730
+ type=${e.type==="number"?"number":"text"}
1731
+ class="text-input"
1732
+ .value=${String(t??"")}
1733
+ placeholder=${e.placeholder||""}
1734
+ minlength=${e.validation?.min}
1735
+ maxlength=${e.validation?.max}
1736
+ min=${e.validation?.min}
1737
+ max=${e.validation?.max}
1738
+ @input=${s=>this._handleInput(e.key,s.target.value)}
1739
+ />
1740
+ `}_renderSelectField(e,t){return o`
1741
+ <select
1742
+ class="select-input"
1743
+ .value=${String(t??"")}
1744
+ @change=${s=>this._handleInput(e.key,s.target.value)}
1745
+ >
1746
+ ${e.options?.map(s=>o`
1747
+ <option value=${s.value} ?selected=${t===s.value}>${s.label}</option>
1748
+ `)}
1749
+ </select>
1750
+ `}_renderBooleanField(e,t){return o`
1751
+ <label class="toggle-label">
1752
+ <input
1753
+ type="checkbox"
1754
+ class="toggle-input"
1755
+ .checked=${!!t}
1756
+ @change=${s=>this._handleInput(e.key,s.target.checked)}
1757
+ />
1758
+ <span class="toggle-switch"></span>
1759
+ <span class="toggle-text">${e.description||a("settings.enableFeature")}</span>
1760
+ </label>
1761
+ `}};D([u({attribute:!1})],P.prototype,"config",2);D([c()],P.prototype,"_activeSection",2);D([c()],P.prototype,"_loading",2);D([c()],P.prototype,"_saving",2);D([c()],P.prototype,"_dirtyFields",2);D([c()],P.prototype,"_errors",2);D([c()],P.prototype,"_saveSuccess",2);D([c()],P.prototype,"_models",2);D([c()],P.prototype,"_values",2);P=D([k("settings-page")],P);function ai(){return[{label:a("nav.chat"),tabs:["chat"]},{label:a("nav.management"),tabs:["sessions","cron","logs"]},{label:a("nav.settings"),tabs:["settings"]}]}function li(e){return a(`nav.${e}`)}const ci={chat:"messageSquare",sessions:"folderOpen",cron:"clock",logs:"fileText",settings:"settings"};function hi(e){const t=e.replace(/^#\/?chat\/?/,"");if(!t||t==="/")return{type:"recent"};const s=t.replace(/^\/?/,"");return s==="new"?{type:"new"}:s&&s.length>0?{type:"session",sessionKey:decodeURIComponent(s)}:{type:"recent"}}function st(e){switch(e.type){case"recent":return"#/chat";case"new":return"#/chat/new";case"session":return`#/chat/${encodeURIComponent(e.sessionKey)}`}}function di(e,t,s){const i=ci[e],n=li(e);return o`
1762
+ <button
1763
+ class="nav-item ${t?"nav-item--active":""}"
1764
+ @click=${s}
1765
+ role="tab"
1766
+ aria-selected=${t}
1767
+ >
1768
+ <span class="nav-item__icon">${p(i)}</span>
1769
+ <span class="nav-item__text">${n}</span>
1770
+ </button>
1771
+ `}var pi=Object.defineProperty,ui=Object.getOwnPropertyDescriptor,R=(e,t,s,i)=>{for(var n=i>1?void 0:i?ui(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&pi(t,s,n),n};let I=class extends y{constructor(){super(...arguments),this._activeTab="chat",this._navCollapsed=!1,this._navMobileOpen=!1,this._theme="system",this._language="en",this._chatRoute={type:"recent"}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._loadTheme(),this._loadLanguage(),this._loadRouteFromHash(),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{this._theme==="system"&&this._applyTheme()}),window.addEventListener("languagechange",()=>{this.requestUpdate()}),window.addEventListener("hashchange",()=>{this._loadRouteFromHash()})}_loadRouteFromHash(){const e=location.hash.slice(1);if(e.startsWith("chat")){const i=hi(e);i&&(this._activeTab!=="chat"&&(this._activeTab="chat"),JSON.stringify(this._chatRoute)!==JSON.stringify(i)&&(this._chatRoute=i));return}const t=e;["sessions","cron","logs","settings"].includes(t)&&this._activeTab!==t&&(this._activeTab=t)}_switchTab(e){this._activeTab=e;let t;e==="chat"?t=st(this._chatRoute):t=`#${e}`,location.hash!==t&&history.pushState(null,"",t),this._navMobileOpen=!1}_updateChatRoute(e){this._chatRoute=e;const t=st(e);history.pushState(null,"",t)}_loadTheme(){const e=localStorage.getItem("xopcbot-theme");e&&(this._theme=e),this._applyTheme()}_loadLanguage(){const e=localStorage.getItem("xopcbot-language");e&&(this._language=e,tt(e))}_applyTheme(){const e=document.documentElement;e.classList.remove("light","dark");let t=!1;this._theme==="dark"?t=!0:this._theme==="system"&&(t=window.matchMedia("(prefers-color-scheme: dark)").matches),t?e.classList.add("dark"):e.classList.add("light"),window.dispatchEvent(new CustomEvent("themechange",{detail:{theme:t?"dark":"light"}}))}_setTheme(e){this._theme=e,localStorage.setItem("xopcbot-theme",e),this._applyTheme()}_setLanguage(e){this._language=e,tt(e),localStorage.setItem("xopcbot-language",e),this.requestUpdate()}_renderThemeToggle(){return o`
1772
+ <div class="pill-toggle">
1773
+ <button
1774
+ class="pill-btn ${this._theme==="light"?"active":""}"
1775
+ @click=${()=>this._setTheme("light")}
1776
+ title="Light"
1777
+ >
1778
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1779
+ <circle cx="12" cy="12" r="5"></circle>
1780
+ <line x1="12" y1="1" x2="12" y2="3"></line>
1781
+ <line x1="12" y1="21" x2="12" y2="23"></line>
1782
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
1783
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
1784
+ <line x1="1" y1="12" x2="3" y2="12"></line>
1785
+ <line x1="21" y1="12" x2="23" y2="12"></line>
1786
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
1787
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
1788
+ </svg>
1789
+ </button>
1790
+ <button
1791
+ class="pill-btn ${this._theme==="dark"?"active":""}"
1792
+ @click=${()=>this._setTheme("dark")}
1793
+ title="Dark"
1794
+ >
1795
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1796
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
1797
+ </svg>
1798
+ </button>
1799
+ <button
1800
+ class="pill-btn ${this._theme==="system"?"active":""}"
1801
+ @click=${()=>this._setTheme("system")}
1802
+ title="System"
1803
+ >
1804
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1805
+ <rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
1806
+ <line x1="8" y1="21" x2="16" y2="21"></line>
1807
+ <line x1="12" y1="17" x2="12" y2="21"></line>
1808
+ </svg>
1809
+ </button>
1810
+ </div>
1811
+ `}_renderLanguageToggle(){return o`
1812
+ <div class="pill-toggle">
1813
+ <button
1814
+ class="pill-btn ${this._language==="en"?"active":""}"
1815
+ @click=${()=>this._setLanguage("en")}
1816
+ title="English"
1817
+ >
1818
+ EN
1819
+ </button>
1820
+ <button
1821
+ class="pill-btn ${this._language==="zh"?"active":""}"
1822
+ @click=${()=>this._setLanguage("zh")}
1823
+ title="中文"
1824
+ >
1825
+
1826
+ </button>
1827
+ </div>
1828
+ `}_toggleNav(){window.innerWidth<768?this._navMobileOpen=!this._navMobileOpen:this._navCollapsed=!this._navCollapsed}_closeNavMobile(){this._navMobileOpen=!1}render(){return o`
1829
+ <div class="shell ${this._activeTab==="chat"?"shell--chat":""} ${this._navCollapsed?"shell--nav-collapsed":""}">
1830
+ <!-- Topbar -->
1831
+ <header class="topbar">
1832
+ <div class="topbar-left">
1833
+ <button
1834
+ class="nav-collapse-toggle"
1835
+ @click=${this._toggleNav}
1836
+ title="${this._navCollapsed?"Expand sidebar":"Collapse sidebar"}"
1837
+ aria-label="${this._navCollapsed?"Expand sidebar":"Collapse sidebar"}"
1838
+ >
1839
+ <span class="nav-collapse-toggle__icon">${p("menu")}</span>
1840
+ </button>
1841
+
1842
+ <div class="brand">
1843
+ <div class="brand-logo">
1844
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1845
+ <rect width="24" height="24" rx="6" fill="url(#logo-gradient)"/>
1846
+ <path d="M8 12L11 15L16 9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1847
+ <defs>
1848
+ <linearGradient id="logo-gradient" x1="0" y1="0" x2="24" y2="24" gradientUnits="userSpaceOnUse">
1849
+ <stop stop-color="#3b82f6"/>
1850
+ <stop offset="1" stop-color="#8b5cf6"/>
1851
+ </linearGradient>
1852
+ </defs>
1853
+ </svg>
1854
+ </div>
1855
+ <div class="brand-text">
1856
+ <div class="brand-title">XOPCBOT</div>
1857
+ <div class="brand-sub">Gateway</div>
1858
+ </div>
1859
+ </div>
1860
+ </div>
1861
+
1862
+ <div class="topbar-status">
1863
+ ${this._renderLanguageToggle()}
1864
+ ${this._renderThemeToggle()}
1865
+ </div>
1866
+ </header>
1867
+
1868
+ <!-- Mobile Overlay Backdrop -->
1869
+ ${this._navMobileOpen?o`
1870
+ <div class="nav-overlay" @click=${this._closeNavMobile}></div>
1871
+ `:m}
1872
+
1873
+ <div class="shell-main">
1874
+ <!-- Sidebar Navigation -->
1875
+ <aside class="nav ${this._navCollapsed?"nav--collapsed":""} ${this._navMobileOpen?"nav--mobile-open":""}">
1876
+ ${ai().map(e=>(e.tabs.some(t=>t===this._activeTab),o`
1877
+ <div class="nav-group">
1878
+ <div class="nav-label nav-label--static">
1879
+ <span class="nav-label__text">${e.label}</span>
1880
+ </div>
1881
+ <div class="nav-group__items">
1882
+ ${e.tabs.map(t=>di(t,this._activeTab===t,()=>{this._switchTab(t)}))}
1883
+ </div>
1884
+ </div>
1885
+ `))}
1886
+ </aside>
1887
+
1888
+ <!-- Main Content -->
1889
+ <main class="content ${this._activeTab==="chat"?"content--chat":""}">
1890
+ ${this._activeTab==="chat"?this._renderChat():m}
1891
+ ${this._activeTab==="sessions"?this._renderSessions():m}
1892
+ ${this._activeTab==="cron"?this._renderCron():m}
1893
+ ${this._activeTab==="logs"?this._renderLogs():m}
1894
+ ${this._activeTab==="settings"?this._renderSettings():m}
1895
+ </main>
1896
+ </div>
1897
+ </div>
1898
+ `}_renderChat(){return o`
1899
+ <xopcbot-gateway-chat
1900
+ .config=${this.gatewayConfig}
1901
+ .route=${this._chatRoute}
1902
+ .enableAttachments=${!0}
1903
+ .enableModelSelector=${!0}
1904
+ .enableThinkingSelector=${!0}
1905
+ @route-change=${e=>this._updateChatRoute(e.detail)}
1906
+ ></xopcbot-gateway-chat>
1907
+ `}_renderSessions(){const e=this.gatewayConfig?.url||"",t=this.gatewayConfig?.token;return o`
1908
+ <session-manager
1909
+ .config=${{url:e,token:t}}
1910
+ ></session-manager>
1911
+ `}_renderCron(){const e=this.gatewayConfig?.url||"",t=this.gatewayConfig?.token;return o`
1912
+ <cron-manager
1913
+ .config=${{url:e,token:t}}
1914
+ ></cron-manager>
1915
+ `}_renderLogs(){const e=this.gatewayConfig?.url||"",t=this.gatewayConfig?.token;return o`
1916
+ <log-manager
1917
+ .config=${{url:e,token:t}}
1918
+ ></log-manager>
1919
+ `}_renderSettings(){const e=this.gatewayConfig?.url||"",t=this.gatewayConfig?.token;return o`
1920
+ <settings-page
1921
+ .config=${{url:e,token:t}}
1922
+ ></settings-page>
1923
+ `}showChat(){this._activeTab="chat"}get chatElement(){return this._chatElement}};R([u({attribute:!1})],I.prototype,"gatewayConfig",2);R([c()],I.prototype,"_activeTab",2);R([c()],I.prototype,"_navCollapsed",2);R([c()],I.prototype,"_navMobileOpen",2);R([c()],I.prototype,"_theme",2);R([c()],I.prototype,"_language",2);R([c()],I.prototype,"_chatRoute",2);R([ie("xopcbot-gateway-chat")],I.prototype,"_chatElement",2);I=R([k("xopcbot-app")],I);var gi=Object.defineProperty,mi=Object.getOwnPropertyDescriptor,O=(e,t,s,i)=>{for(var n=i>1?void 0:i?mi(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&gi(t,s,n),n};let F=class extends y{constructor(){super(...arguments),this.sections=[],this.values={},this.loading=!1,this._activeSection="",this._dirtyFields=new Set,this._showPasswords=new Set,this._errors=new Map}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._updateActiveSection()}willUpdate(e){e.has("sections")&&this._updateActiveSection()}_updateActiveSection(){this.sections.length>0&&!this._activeSection&&(this._activeSection=this.sections[0].id)}_getIcon(e){return{user:o`<User class="w-5 h-5" />`,bot:o`<Bot class="w-5 h-5" />`,plug:o`<Plug class="w-5 h-5" />`,globe:o`<Globe class="w-5 h-5" />`,search:o`<Search class="w-5 h-5" />`,clock:o`<Clock class="w-5 h-5" />`,puzzle:o`<Puzzle class="w-5 h-5" />`,settings:o`<Settings class="w-5 h-5" />`}[e]||o`<Settings class="w-5 h-5" />`}render(){return o`
1924
+ <div class="settings-overlay" @click=${e=>e.target===e.currentTarget&&this.onClose?.()}>
1925
+ <div class="settings-dialog">
1926
+ ${this.renderHeader()}
1927
+ <div class="settings-content">
1928
+ ${this.renderSidebar()}
1929
+ ${this.renderMain()}
1930
+ </div>
1931
+ ${this.renderFooter()}
1932
+ </div>
1933
+ </div>
1934
+ `}renderHeader(){return o`
1935
+ <div class="settings-header">
1936
+ <div class="settings-title">
1937
+ <Settings class="w-5 h-5" />
1938
+ <span>Settings</span>
1939
+ </div>
1940
+ <button class="close-btn" @click=${()=>this.onClose?.()}>
1941
+ <X class="w-5 h-5" />
1942
+ </button>
1943
+ </div>
1944
+ `}renderSidebar(){return o`
1945
+ <nav class="settings-sidebar">
1946
+ ${this.sections.map(e=>o`
1947
+ <button
1948
+ class="sidebar-item ${this._activeSection===e.id?"active":""}"
1949
+ @click=${()=>this._activeSection=e.id}
1950
+ >
1951
+ ${this._getIcon(e.icon)}
1952
+ <span>${e.title}</span>
1953
+ <ChevronRight class="w-4 h-4 chevron" />
1954
+ </button>
1955
+ `)}
1956
+ </nav>
1957
+ `}renderMain(){const e=this.sections.find(s=>s.id===this._activeSection);if(!e)return o`<div class="settings-main">${a("settings.noSection")}</div>`;const t=`settings.descriptions.${e.id}`;return o`
1958
+ <div class="settings-main">
1959
+ <div class="section-header">
1960
+ <h2>${e.title}</h2>
1961
+ <p class="section-description">${a(t)}</p>
1962
+ </div>
1963
+
1964
+ <div class="fields-grid">
1965
+ ${e.fields.map(s=>this.renderField(s,e.id))}
1966
+ </div>
1967
+ </div>
1968
+ `}renderField(e,t){const s=`${t}.${e.key}`,i=this._getValue(e.key),n=this._dirtyFields.has(s),r=this._errors.get(s),l=this._showPasswords.has(s);return o`
1969
+ <div class="field-group ${r?"has-error":""}">
1970
+ <div class="field-header">
1971
+ <label class="field-label">${e.label}</label>
1972
+ ${e.validation?.required?o`<span class="required-mark">*</span>`:""}
1973
+ </div>
1974
+
1975
+ ${e.description?o`<p class="field-description">${e.description}</p>`:""}
1976
+
1977
+ ${e.type==="boolean"?this.renderBooleanField(e,i,s):""}
1978
+
1979
+ ${e.type==="select"?this.renderSelectField(e,i,s):""}
1980
+
1981
+ ${e.type==="textarea"?this.renderTextareaField(e,i,s):""}
1982
+
1983
+ ${["text","password","number"].includes(e.type)?this.renderInputField(e,i,s,l):""}
1984
+
1985
+ ${r?o`
1986
+ <div class="field-error">
1987
+ <AlertCircle class="w-4 h-4" />
1988
+ <span>${r}</span>
1989
+ </div>
1990
+ `:""}
1991
+
1992
+ ${n&&!r?o`
1993
+ <div class="field-dirty">${a("settings.unsavedChanges")}</div>
1994
+ `:""}
1995
+ </div>
1996
+ `}renderInputField(e,t,s,i){const n=e.type==="password"?i?"text":"password":e.type;return o`
1997
+ <div class="input-wrapper">
1998
+ <input
1999
+ type=${n}
2000
+ class="text-input ${e.type==="password"?"has-toggle":""}"
2001
+ .value=${String(t??"")}
2002
+ placeholder=${e.placeholder||""}
2003
+ minlength=${e.validation?.min}
2004
+ maxlength=${e.validation?.max}
2005
+ pattern=${e.validation?.pattern||""}
2006
+ @input=${r=>this._handleInput(e,s,r.target.value)}
2007
+ />
2008
+ ${e.type==="password"?o`
2009
+ <button
2010
+ type="button"
2011
+ class="password-toggle"
2012
+ @click=${()=>this._togglePassword(s)}
2013
+ >
2014
+ ${i?o`<EyeOff class="w-4 h-4" />`:o`<Eye class="w-4 h-4" />`}
2015
+ </button>
2016
+ `:""}
2017
+ </div>
2018
+ `}renderTextareaField(e,t,s){return o`
2019
+ <textarea
2020
+ class="textarea-input"
2021
+ .value=${String(t??"")}
2022
+ placeholder=${e.placeholder||""}
2023
+ rows="4"
2024
+ @input=${i=>this._handleInput(e,s,i.target.value)}
2025
+ ></textarea>
2026
+ `}renderSelectField(e,t,s){return o`
2027
+ <select
2028
+ class="select-input"
2029
+ .value=${String(t??"")}
2030
+ @change=${i=>this._handleInput(e,s,i.target.value)}
2031
+ >
2032
+ ${e.options?.map(i=>o`
2033
+ <option value=${i.value} ?selected=${t===i.value}>${i.label}</option>
2034
+ `)}
2035
+ </select>
2036
+ `}renderBooleanField(e,t,s){return o`
2037
+ <label class="toggle-label">
2038
+ <input
2039
+ type="checkbox"
2040
+ class="toggle-input"
2041
+ .checked=${!!t}
2042
+ @change=${i=>this._handleInput(e,s,i.target.checked)}
2043
+ />
2044
+ <span class="toggle-switch"></span>
2045
+ <span class="toggle-text">${e.description||a("settings.enableFeature")}</span>
2046
+ </label>
2047
+ `}renderFooter(){const e=this._dirtyFields.size>0;return o`
2048
+ <div class="settings-footer">
2049
+ <button class="btn btn-ghost" @click=${()=>this.onClose?.()}>
2050
+ ${a("settings.cancel")}
2051
+ </button>
2052
+ <button
2053
+ class="btn btn-primary"
2054
+ ?disabled=${this.loading||!e}
2055
+ @click=${()=>this._save()}
2056
+ >
2057
+ ${this.loading?o`
2058
+ <Loader2 class="w-4 h-4 animate-spin" />
2059
+ ${a("settings.saving")}
2060
+ `:o`
2061
+ <Save class="w-4 h-4" />
2062
+ ${a("settings.saveChanges")}
2063
+ `}
2064
+ </button>
2065
+ </div>
2066
+ `}_getValue(e){return this.values[e]}_handleInput(e,t,s){e.validation?.required&&!s?this._errors.set(t,a("settings.required",{field:e.label})):e.validation?.pattern&&s?new RegExp(e.validation.pattern).test(s)?this._errors.delete(t):this._errors.set(t,a("settings.invalidFormat")):this._errors.delete(t),this._dirtyFields.add(t),this.requestUpdate()}_togglePassword(e){this._showPasswords.has(e)?this._showPasswords.delete(e):this._showPasswords.add(e),this.requestUpdate()}_save(){this._errors.size>0||this.onSave&&this.onSave(this.values)}};O([u({attribute:!1})],F.prototype,"sections",2);O([u({attribute:!1})],F.prototype,"values",2);O([u({type:Boolean})],F.prototype,"loading",2);O([u({attribute:!1})],F.prototype,"onSave",2);O([u({attribute:!1})],F.prototype,"onClose",2);O([c()],F.prototype,"_activeSection",2);O([c()],F.prototype,"_dirtyFields",2);O([c()],F.prototype,"_showPasswords",2);O([c()],F.prototype,"_errors",2);F=O([k("xopcbot-settings")],F);var _i=Object.defineProperty,vi=Object.getOwnPropertyDescriptor,Z=(e,t,s,i)=>{for(var n=i>1?void 0:i?vi(t,s):t,r=e.length-1,l;r>=0;r--)(l=e[r])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&_i(t,s,n),n};let H=class extends y{constructor(){super(...arguments),this.enableAttachments=!0,this.enableModelSelector=!0,this.enableThinkingSelector=!0,this._autoScroll=!0,this._lastScrollTop=0,this._handleScroll=()=>{if(!this._scrollContainer)return;const e=this._scrollContainer.scrollTop,t=this._scrollContainer.scrollHeight,s=this._scrollContainer.clientHeight,i=t-e-s;if(s<this._lastClientHeight){this._lastClientHeight=s;return}e!==0&&e<this._lastScrollTop&&i>50?this._autoScroll=!1:i<10&&(this._autoScroll=!0),this._lastScrollTop=e,this._lastClientHeight=s}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.style.display="flex",this.style.flexDirection="column",this.style.height="100%",this.style.minHeight="0",this.setupSessionSubscription()}disconnectedCallback(){super.disconnectedCallback(),this._resizeObserver?.disconnect(),this._scrollContainer?.removeEventListener("scroll",this._handleScroll),this._unsubscribeSession?.()}setupSessionSubscription(){this._unsubscribeSession&&this._unsubscribeSession(),this.agent&&(this._unsubscribeSession=this.agent.subscribe(async e=>{switch(e.type){case"message_start":case"message_end":case"turn_start":case"turn_end":case"agent_start":this.requestUpdate();break;case"agent_end":this._streamingContainer&&(this._streamingContainer.isStreaming=!1,this._streamingContainer.setMessage(null,!0)),this.requestUpdate();break;case"message_update":this._streamingContainer&&(this._streamingContainer.isStreaming=this.agent?.state.isStreaming||!1,this._streamingContainer.setMessage(e.message,!this._streamingContainer.isStreaming)),this.requestUpdate();break}}))}setInput(e,t){this._messageEditor&&(this._messageEditor.value=e,this._messageEditor.attachments=t||[])}setAutoScroll(e){this._autoScroll=e}async sendMessage(e,t){if(!(!e.trim()&&t?.length===0||this.agent?.state.isStreaming)){if(!this.agent)throw new Error("No agent set");if(!this.agent.state.model)throw new Error("No model set");this._messageEditor.value="",this._messageEditor.attachments=[],this._autoScroll=!0,t&&t.length>0?await this.agent.prompt({role:"user-with-attachments",content:e,attachments:t,timestamp:Date.now()}):await this.agent.prompt(e)}}renderMessages(){if(!this.agent)return o`<div class="p-4 text-center text-muted-foreground">${te("No session available")}</div>`;const e=this.agent.state;return o`
2067
+ <div class="flex flex-col gap-3">
2068
+ <message-list
2069
+ .messages=${this.agent.state.messages}
2070
+ .tools=${e.tools}
2071
+ .pendingToolCalls=${this.agent?this.agent.state.pendingToolCalls:new Set}
2072
+ .isStreaming=${e.isStreaming}
2073
+ ></message-list>
2074
+
2075
+ <streaming-message-container
2076
+ class="${e.isStreaming?"":"hidden"}"
2077
+ .tools=${e.tools}
2078
+ .isStreaming=${e.isStreaming}
2079
+ .pendingToolCalls=${e.pendingToolCalls}
2080
+ .isStreaming=${e.isStreaming}
2081
+ ></streaming-message-container>
2082
+ </div>
2083
+ `}render(){if(!this.agent)return o`<div class="p-4 text-center text-muted-foreground">${te("No agent set")}</div>`;const e=this.agent.state;return o`
2084
+ <div class="flex flex-col h-full bg-background text-foreground">
2085
+ <div class="flex-1 overflow-y-auto">
2086
+ <div class="max-w-3xl mx-auto p-4 pb-0">${this.renderMessages()}</div>
2087
+ </div>
2088
+
2089
+ <div class="shrink-0">
2090
+ <div class="max-w-3xl mx-auto px-2">
2091
+ <message-editor
2092
+ .isStreaming=${e.isStreaming}
2093
+ .currentModel=${e.model}
2094
+ .thinkingLevel=${e.thinkingLevel}
2095
+ .showAttachmentButton=${this.enableAttachments}
2096
+ .showModelSelector=${this.enableModelSelector}
2097
+ .showThinkingSelector=${this.enableThinkingSelector}
2098
+ .onSend=${(t,s)=>this.sendMessage(t,s)}
2099
+ .onAbort=${()=>this.agent?.abort()}
2100
+ ></message-editor>
2101
+ </div>
2102
+ </div>
2103
+ </div>
2104
+ `}};Z([u({attribute:!1})],H.prototype,"agent",2);Z([u({type:Boolean})],H.prototype,"enableAttachments",2);Z([u({type:Boolean})],H.prototype,"enableModelSelector",2);Z([u({type:Boolean})],H.prototype,"enableThinkingSelector",2);Z([ie("message-editor")],H.prototype,"_messageEditor",2);Z([ie("streaming-message-container")],H.prototype,"_streamingContainer",2);H=Z([k("xopcbot-chat")],H);
2105
+ //# sourceMappingURL=main-CfIxL-cL.js.map