@shawnstack/quickforge 1.7.4 → 1.7.6

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 (258) hide show
  1. package/dist/assets/AgentProfilesPage-Dl5Peqov.js +1 -0
  2. package/dist/assets/ChatPanelHost-D3987TUJ.js +307 -0
  3. package/dist/assets/CloudAccountSettingsPage-BG5Nn3bq.js +1 -0
  4. package/dist/assets/PluginsPage-BDKYfLna.js +1 -0
  5. package/dist/assets/ScheduledTasksPage--GAki3lB.js +2 -0
  6. package/dist/assets/SettingsWorkspacePage-DSy66Tuw.js +1696 -0
  7. package/dist/assets/ShareLinksSettingsPage-BQQMsvJo.js +1 -0
  8. package/dist/assets/SharedConversationPage-B9BUVCri.js +1 -0
  9. package/dist/assets/TerminalDock-CT1nYo7P.js +2 -0
  10. package/dist/assets/WorkspaceInspector-BnfDLf9a.js +36 -0
  11. package/dist/assets/{abnfDiagram-VRR7QNED-Dy7veffk.js → abnfDiagram-VRR7QNED-CMhVoYUh.js} +1 -1
  12. package/dist/assets/{arc-Bo3p2lGy.js → arc-w21O0TLn.js} +1 -1
  13. package/dist/assets/architecture-TIHT7OUA-DMwFMHxq.js +1 -0
  14. package/dist/assets/{architectureDiagram-ZJ3FMSHR-Cwx8qOvu.js → architectureDiagram-ZJ3FMSHR-C52qL6Hg.js} +1 -1
  15. package/dist/assets/{blockDiagram-677ZJIJ3-BiuaAOFa.js → blockDiagram-677ZJIJ3-CM3XbLol.js} +1 -1
  16. package/dist/assets/{c4Diagram-LMCZKHZV-BTcGfhK2.js → c4Diagram-LMCZKHZV-D7Bh1ui1.js} +1 -1
  17. package/dist/assets/channel-Duu1CuH9.js +1 -0
  18. package/dist/assets/chunk-2Q5K7J3B-B6rHWc4S.js +1 -0
  19. package/dist/assets/{chunk-32BRIVSS-B9PuF_RF.js → chunk-32BRIVSS-xgrtbT8e.js} +1 -1
  20. package/dist/assets/{chunk-52WLFC77-3zGItfIM.js → chunk-52WLFC77-CDbaHw80.js} +1 -1
  21. package/dist/assets/{chunk-5FCAYU7R-DQ66qlmt.js → chunk-5FCAYU7R-CcSvVbPc.js} +1 -1
  22. package/dist/assets/{chunk-5HE753X5-CLqTO-VF.js → chunk-5HE753X5-erFpzzgx.js} +1 -1
  23. package/dist/assets/{chunk-5JV3BV7I-Csxv1jr6.js → chunk-5JV3BV7I-rEhN9F6G.js} +1 -1
  24. package/dist/assets/{chunk-5TONJI2A-BCQttpBr.js → chunk-5TONJI2A-D8L-QTwD.js} +1 -1
  25. package/dist/assets/{chunk-5VM5RSS4-DEWJGSTb.js → chunk-5VM5RSS4-CjlfMBbM.js} +1 -1
  26. package/dist/assets/{chunk-7BUUIJ7U-DNorm9MM.js → chunk-7BUUIJ7U-CCcsI9XE.js} +1 -1
  27. package/dist/assets/{chunk-BIQX33UG-DgvY_BOT.js → chunk-BIQX33UG-FSqFbmb3.js} +1 -1
  28. package/dist/assets/{chunk-C7G6YPKG-DMvn9IPs.js → chunk-C7G6YPKG-ZMLUvfLy.js} +1 -1
  29. package/dist/assets/{chunk-CQNSW5MT-Dq2duUgr.js → chunk-CQNSW5MT-DZuBpk25.js} +1 -1
  30. package/dist/assets/{chunk-CYSBUYHQ-BovYyc4Y.js → chunk-CYSBUYHQ-CB26wsG0.js} +1 -1
  31. package/dist/assets/{chunk-EMLP6XTP-BMDOpuYN.js → chunk-EMLP6XTP-BbsM8oRw.js} +1 -1
  32. package/dist/assets/{chunk-EX3LRPZG-6eP2UPOf.js → chunk-EX3LRPZG-BcQhaqt7.js} +1 -1
  33. package/dist/assets/{chunk-FWX5IMBZ-D4q-wTSy.js → chunk-FWX5IMBZ-DrnrdrSu.js} +2 -2
  34. package/dist/assets/{chunk-HOUHSVGY-XjIcuzH7.js → chunk-HOUHSVGY-tdc-Z9eW.js} +1 -1
  35. package/dist/assets/{chunk-ICXQ74PX-YBXbanq9.js → chunk-ICXQ74PX-Cd7igVGt.js} +1 -1
  36. package/dist/assets/{chunk-JG7HCLWE-CcN3uNXF.js → chunk-JG7HCLWE-iXXGW8nf.js} +1 -1
  37. package/dist/assets/{chunk-JWPE2WC7-Cwg6AUAt.js → chunk-JWPE2WC7-BZ87mXEv.js} +1 -1
  38. package/dist/assets/{chunk-MOJQB5TN-NNspcGIU.js → chunk-MOJQB5TN-CLTjV5ov.js} +1 -1
  39. package/dist/assets/{chunk-MOZMSUNE-pMJ_jMos.js → chunk-MOZMSUNE-B3SCBrRH.js} +1 -1
  40. package/dist/assets/{chunk-OGEWGWER-CJy-3Ldv.js → chunk-OGEWGWER-TgvkXkFX.js} +1 -1
  41. package/dist/assets/{chunk-OSBZ3O6U-D7cLHHOA.js → chunk-OSBZ3O6U-B9E2E5v1.js} +1 -1
  42. package/dist/assets/{chunk-PUDLZKDR-D5YBi1Pi.js → chunk-PUDLZKDR-C5GMVYup.js} +1 -1
  43. package/dist/assets/{chunk-Q4XR5HBZ-DYmqQdIf.js → chunk-Q4XR5HBZ-fo5-HsqY.js} +1 -1
  44. package/dist/assets/{chunk-QBLGF6JB-Bfcx00X0.js → chunk-QBLGF6JB-Dwfg8sKc.js} +1 -1
  45. package/dist/assets/{chunk-R7FJI6CG-oXzadpZY.js → chunk-R7FJI6CG-DpBrv4ni.js} +1 -1
  46. package/dist/assets/{chunk-RYQCIY6F-Dt3-8yUh.js → chunk-RYQCIY6F-DzzmTl11.js} +1 -1
  47. package/dist/assets/{chunk-U6XO7XAA-B55eSvpx.js → chunk-U6XO7XAA-Dw6aviKa.js} +1 -1
  48. package/dist/assets/{chunk-V7JOEXUC-Btk4JwCt.js → chunk-V7JOEXUC-CEDazV6w.js} +1 -1
  49. package/dist/assets/chunk-VAUOI2AC-CWYjg8zE.js +1 -0
  50. package/dist/assets/{chunk-VR4S4FIN-DgaSiVOY.js → chunk-VR4S4FIN-C_-eEj-9.js} +1 -1
  51. package/dist/assets/{chunk-WYO6CB5R-rRDZ_Tta.js → chunk-WYO6CB5R-NF-MsJJR.js} +3 -3
  52. package/dist/assets/chunk-XXDRQBXY-DzTwx8ZH.js +1 -0
  53. package/dist/assets/{chunk-YOTPTUD7-BnFxj5o4.js → chunk-YOTPTUD7-DqzqtdII.js} +1 -1
  54. package/dist/assets/{chunk-ZGVPDNZ5-CrnlPlmJ.js → chunk-ZGVPDNZ5-CRrAYi4g.js} +1 -1
  55. package/dist/assets/{chunk-ZIRB5QZD-BYTiATIH.js → chunk-ZIRB5QZD-Dc1s5bLM.js} +1 -1
  56. package/dist/assets/classDiagram-OUVF2IWQ-Cc63fLWP.js +1 -0
  57. package/dist/assets/classDiagram-v2-EOCWNBFH-CoXU0qT6.js +1 -0
  58. package/dist/assets/{cose-bilkent-JH36ORCC-BORKJRwF.js → cose-bilkent-JH36ORCC-cL247pHg.js} +1 -1
  59. package/dist/assets/cynefin-VYW2F7L2-C8yCvH_o.js +1 -0
  60. package/dist/assets/{cynefinDiagram-TSTJHNR4-BXKeaSl8.js → cynefinDiagram-TSTJHNR4-D4sZ7LYI.js} +1 -1
  61. package/dist/assets/{dagre-CrA0XVwJ.js → dagre-DmHb3Ctt.js} +1 -1
  62. package/dist/assets/{dagre-VKFMJZFB-ouq_lA1a.js → dagre-VKFMJZFB-BlsnSh-Q.js} +1 -1
  63. package/dist/assets/{diagram-FQU43EPY-BxR5kUiQ.js → diagram-FQU43EPY-DW1yQiRO.js} +1 -1
  64. package/dist/assets/{diagram-G47NLZAW-DWonk1sL.js → diagram-G47NLZAW-BTUAsFjb.js} +1 -1
  65. package/dist/assets/{diagram-NH7WQ7WH-fmV_wV5e.js → diagram-NH7WQ7WH-BcaomqSd.js} +1 -1
  66. package/dist/assets/{diagram-OA4YK3LP-DvOSRRiV.js → diagram-OA4YK3LP-DDLX7Xwr.js} +1 -1
  67. package/dist/assets/{diagram-WEI45ONY-Bp-xb3uS.js → diagram-WEI45ONY-CIave0An.js} +1 -1
  68. package/dist/assets/{dist-DLKC_odd.js → dist-yDHbi5ux.js} +1 -1
  69. package/dist/assets/{ebnfDiagram-CCIWWBDH-BTlnwneA.js → ebnfDiagram-CCIWWBDH-Cr1Y6lPu.js} +1 -1
  70. package/dist/assets/{erDiagram-Q63AITRT-C3fFWGCm.js → erDiagram-Q63AITRT-D3EgiVVH.js} +1 -1
  71. package/dist/assets/{esm-oa69b5u4.js → esm-sdsK6gaB.js} +2 -2
  72. package/dist/assets/eventmodeling-45OFAUF4-DO1vRTM0.js +1 -0
  73. package/dist/assets/flowDiagram-23GEKE2U-BS7KXcqn.js +1 -0
  74. package/dist/assets/{ganttDiagram-NO4QXBWP-DzAiojNi.js → ganttDiagram-NO4QXBWP-B0oyDIqK.js} +1 -1
  75. package/dist/assets/gitGraph-TEB2WS4Q-m5F5ef09.js +1 -0
  76. package/dist/assets/{gitGraphDiagram-IHSO6WYX-Cv57oNEA.js → gitGraphDiagram-IHSO6WYX-uQtr6IqK.js} +1 -1
  77. package/dist/assets/icons-2D18YbSI.js +1 -0
  78. package/dist/assets/index-1ei6nhs-.css +3 -0
  79. package/dist/assets/index-BivLuZvX.js +65 -0
  80. package/dist/assets/info-DKCQHKI2-CZxPlQJ0.js +1 -0
  81. package/dist/assets/{infoDiagram-FWYZ7A6U-B5Z_O3Ro.js → infoDiagram-FWYZ7A6U-B_GzlLIM.js} +1 -1
  82. package/dist/assets/{ishikawaDiagram-FXEZZL3T-CKTK_TKV.js → ishikawaDiagram-FXEZZL3T-CKQIsSdU.js} +1 -1
  83. package/dist/assets/{journeyDiagram-5HDEW3XC-Cm9k4ywW.js → journeyDiagram-5HDEW3XC-DrrvzZL1.js} +1 -1
  84. package/dist/assets/{kanban-definition-HUTT4EX6-DzNteLwx.js → kanban-definition-HUTT4EX6-CJQRTdXz.js} +1 -1
  85. package/dist/assets/{line-BG78c_WJ.js → line-B4DxX7tC.js} +1 -1
  86. package/dist/assets/{linear-1X20_EGu.js → linear-U-nKUhyW.js} +1 -1
  87. package/dist/assets/{map-CCI8WZkS.js → map-BneTM-ri.js} +1 -1
  88. package/dist/assets/{mcp-servers-dialog-GXXD9K0U.js → mcp-servers-dialog-BEV4_TXC.js} +2 -2
  89. package/dist/assets/{mermaid-parser.core-Bb8HI_OS.js → mermaid-parser.core-BlKWrEdZ.js} +2 -2
  90. package/dist/assets/{mermaid-renderer-PIaNiXAz.js → mermaid-renderer-jEbqFaTe.js} +2 -2
  91. package/dist/assets/{mermaid.core-DUHOIwL5.js → mermaid.core-DWpShXCs.js} +3 -3
  92. package/dist/assets/{mindmap-definition-LN4V7U3C-Tnbszo7b.js → mindmap-definition-LN4V7U3C-CEVwZD78.js} +1 -1
  93. package/dist/assets/{logger-8REuLPGK.js → model-display-label-C6-0eDxF.js} +1 -1
  94. package/dist/assets/model-identity-CgA6_Pbm.js +1 -0
  95. package/dist/assets/model-reference-o41fJ6jQ.js +1 -0
  96. package/dist/assets/{monaco-BVtCspYZ.js → monaco-DvXErxp2.js} +1 -1
  97. package/dist/assets/{ordinal-v4prQcuq.js → ordinal-B2r5L1v4.js} +1 -1
  98. package/dist/assets/{otel-D1LswXpM.js → otel-BFnphzjt.js} +1 -1
  99. package/dist/assets/packet-7NZHBO7P-zIioIZVN.js +1 -0
  100. package/dist/assets/{pegDiagram-2B236MQR-CX824Kd0.js → pegDiagram-2B236MQR-CBLkBdnQ.js} +1 -1
  101. package/dist/assets/{pi-ai-DAJlO9ZB.js → pi-ai-Cr2ee4a0.js} +2 -2
  102. package/dist/assets/{pi-web-ui-B-RJSxjR.js → pi-web-ui-DV5jKjSg.js} +1 -1
  103. package/dist/assets/pie-RZYD4A2V-GGWijBvB.js +1 -0
  104. package/dist/assets/{pieDiagram-ENE6RG2P-BT04VWPQ.js → pieDiagram-ENE6RG2P-8tCnwtWS.js} +1 -1
  105. package/dist/assets/{quadrantDiagram-ABIIQ3AL-BvOZxkBr.js → quadrantDiagram-ABIIQ3AL-CWd28cHF.js} +1 -1
  106. package/dist/assets/radar-I7S5WNFK-yvwFH3RV.js +1 -0
  107. package/dist/assets/railroad-3IZDKUUU-BVadlswB.js +1 -0
  108. package/dist/assets/railroad-abnf-AHOZXSZD-B7R-p_2-.js +1 -0
  109. package/dist/assets/railroad-ebnf-EBAXGLYW-BnbJxPug.js +1 -0
  110. package/dist/assets/railroad-peg-LSFZ7HO6-Ci3DcEuQ.js +1 -0
  111. package/dist/assets/{railroadDiagram-RFXS5EU6-DnTU--BV.js → railroadDiagram-RFXS5EU6-CI4ouOBs.js} +1 -1
  112. package/dist/assets/{react-vendor-eWH0QhNU.js → react-vendor-3UaA-C9W.js} +1 -1
  113. package/dist/assets/{requirementDiagram-TGXJPOKE--MZX_yEv.js → requirementDiagram-TGXJPOKE-DtFz7sw4.js} +1 -1
  114. package/dist/assets/{sankeyDiagram-HTMAVEWB-SEZkHhYn.js → sankeyDiagram-HTMAVEWB--VeOwwk9.js} +1 -1
  115. package/dist/assets/{sequenceDiagram-DBY2YBRQ-BhC2OHiz.js → sequenceDiagram-DBY2YBRQ-B8AHk5Oe.js} +1 -1
  116. package/dist/assets/{sizeCapture-X5ZJPWSS-Ci5LeToV.js → sizeCapture-X5ZJPWSS-vV_ArM8D.js} +1 -1
  117. package/dist/assets/{skills-dialog-DDh1h8eH.js → skills-dialog-BTJ7mzk_.js} +3 -3
  118. package/dist/assets/{src-CovulcRC.js → src-PYsDme0X.js} +1 -1
  119. package/dist/assets/{stateDiagram-2N3HPSRC-DKK5tFT4.js → stateDiagram-2N3HPSRC-etXnJ8X8.js} +1 -1
  120. package/dist/assets/stateDiagram-v2-6OUMAXLB-Dms3pICj.js +1 -0
  121. package/dist/assets/{swimlanes-5IMT3BWC-DxxGCk67.js → swimlanes-5IMT3BWC-pabIKAmn.js} +2 -2
  122. package/dist/assets/swimlanesDiagram-G3AALYLV-B14aWjv6.js +8 -0
  123. package/dist/assets/{timeline-definition-FHXFAJF6-BPXB3Sue.js → timeline-definition-FHXFAJF6-C55MKm3L.js} +1 -1
  124. package/dist/assets/treeView-QDETBFTQ-Cru9B2zv.js +1 -0
  125. package/dist/assets/treemap-6X3UGDF4-DNOVHFaJ.js +1 -0
  126. package/dist/assets/{vennDiagram-L72KCM5P-CxcBCKye.js → vennDiagram-L72KCM5P-CgNf1Q9W.js} +1 -1
  127. package/dist/assets/wardley-OPB4EBWU-E3m1BOJQ.js +1 -0
  128. package/dist/assets/{wardleyDiagram-EHGQE667-DEL6Yes5.js → wardleyDiagram-EHGQE667-Drt5ytec.js} +1 -1
  129. package/dist/assets/{web-RgX7H-OH.js → web-B5qgZJRv.js} +1 -1
  130. package/dist/assets/{xychartDiagram-FW5EYKEG-N8cPbcjC.js → xychartDiagram-FW5EYKEG-hhoEo_Ar.js} +1 -1
  131. package/dist/index.html +11 -10
  132. package/dist/sw.js +17 -0
  133. package/package.json +4 -1
  134. package/plugins/{openai-documents → documents}/plugin.json +2 -2
  135. package/plugins/{openai-presentations → presentations}/plugin.json +2 -2
  136. package/plugins/{openai-spreadsheets → spreadsheets}/plugin.json +2 -2
  137. package/runtime-assets/agent/darwin-arm64/qf-agent +0 -0
  138. package/runtime-assets/agent/darwin-x64/qf-agent +0 -0
  139. package/runtime-assets/agent/linux-arm64/qf-agent +0 -0
  140. package/runtime-assets/agent/linux-x64/qf-agent +0 -0
  141. package/runtime-assets/agent/win32-x64/qf-agent.exe +0 -0
  142. package/server/access-policy.mjs +11 -0
  143. package/server/acp/server.mjs +36 -26
  144. package/server/agent-manager.mjs +474 -71
  145. package/server/agent-profile-files.mjs +8 -4
  146. package/server/agent-profile-schema.mjs +47 -23
  147. package/server/agent-profiles.mjs +28 -9
  148. package/server/ai-http-logger.mjs +98 -12
  149. package/server/auto-compaction.mjs +35 -8
  150. package/server/cloud/chat-idempotency-store.mjs +96 -0
  151. package/server/cloud/client.mjs +99 -0
  152. package/server/cloud/config.mjs +54 -0
  153. package/server/cloud/credential-store.mjs +200 -0
  154. package/server/cloud/identity.mjs +312 -0
  155. package/server/cloud/index.mjs +7 -0
  156. package/server/cloud/models.mjs +80 -0
  157. package/server/cloud/qf-agent-process.mjs +571 -0
  158. package/server/cloud/runtime.mjs +135 -0
  159. package/server/cloud/service-config.mjs +81 -0
  160. package/server/index.mjs +124 -48
  161. package/server/mcp/registry.mjs +8 -7
  162. package/server/message-converters.mjs +40 -19
  163. package/server/model-catalog.mjs +269 -0
  164. package/server/opencode-acp-agent.mjs +1151 -0
  165. package/server/plugins/registry.mjs +29 -5
  166. package/server/public-api.mjs +11 -5
  167. package/server/routes/agent-profiles.mjs +46 -9
  168. package/server/routes/agent.mjs +60 -11
  169. package/server/routes/backup.mjs +8 -1
  170. package/server/routes/cloud.mjs +246 -0
  171. package/server/routes/models.mjs +7 -1
  172. package/server/routes/scheduled-tasks.mjs +38 -8
  173. package/server/routes/shared-conversation.mjs +62 -58
  174. package/server/routes/shares.mjs +75 -1
  175. package/server/routes/storage.mjs +9 -1
  176. package/server/routes/system.mjs +7 -4
  177. package/server/routes/workspace.mjs +6 -4
  178. package/server/share-store.mjs +168 -13
  179. package/server/skills.mjs +30 -3
  180. package/server/storage.mjs +7 -1
  181. package/server/subagents.mjs +3 -3
  182. package/server/tools/definitions.mjs +1 -1
  183. package/server/tools/index.mjs +2 -2
  184. package/server/utils/network.mjs +9 -0
  185. package/server/utils/process-tree.mjs +78 -0
  186. package/server/utils/response.mjs +8 -1
  187. package/skills/skill-creator/LICENSE.txt +202 -0
  188. package/skills/skill-creator/SKILL.md +485 -0
  189. package/skills/skill-creator/UPSTREAM.md +6 -0
  190. package/skills/skill-creator/agents/analyzer.md +274 -0
  191. package/skills/skill-creator/agents/comparator.md +202 -0
  192. package/skills/skill-creator/agents/grader.md +223 -0
  193. package/skills/skill-creator/assets/eval_review.html +146 -0
  194. package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  195. package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  196. package/skills/skill-creator/references/schemas.md +430 -0
  197. package/skills/skill-creator/scripts/__init__.py +0 -0
  198. package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  199. package/skills/skill-creator/scripts/generate_report.py +326 -0
  200. package/skills/skill-creator/scripts/improve_description.py +247 -0
  201. package/skills/skill-creator/scripts/package_skill.py +136 -0
  202. package/skills/skill-creator/scripts/quick_validate.py +103 -0
  203. package/skills/skill-creator/scripts/run_eval.py +310 -0
  204. package/skills/skill-creator/scripts/run_loop.py +328 -0
  205. package/skills/skill-creator/scripts/utils.py +47 -0
  206. package/dist/assets/AgentProfilesPage-B84w-r9S.js +0 -1
  207. package/dist/assets/ChatPanelHost-CyO8fEoj.js +0 -288
  208. package/dist/assets/PluginsPage-D2862wul.js +0 -1
  209. package/dist/assets/ScheduledTasksPage-GqbiJDPX.js +0 -2
  210. package/dist/assets/SettingsWorkspacePage-B53_eDf2.js +0 -1628
  211. package/dist/assets/SharedConversationPage-Cw2QFnbC.js +0 -1
  212. package/dist/assets/TerminalDock-Dgg-_ZmU.js +0 -2
  213. package/dist/assets/WorkspaceInspector-3uLiu6Bv.js +0 -13
  214. package/dist/assets/architecture-TIHT7OUA-7FQo5GbP.js +0 -1
  215. package/dist/assets/channel-DToA8d-4.js +0 -1
  216. package/dist/assets/chunk-2Q5K7J3B-D_Wxpk-T.js +0 -1
  217. package/dist/assets/chunk-VAUOI2AC-CIZseNLi.js +0 -1
  218. package/dist/assets/chunk-XXDRQBXY-Do-XYxat.js +0 -1
  219. package/dist/assets/classDiagram-OUVF2IWQ-Bu24Sy-k.js +0 -1
  220. package/dist/assets/classDiagram-v2-EOCWNBFH-DKhh5HSW.js +0 -1
  221. package/dist/assets/cynefin-VYW2F7L2-oyiAgYC4.js +0 -1
  222. package/dist/assets/eventmodeling-45OFAUF4-YB_0MefX.js +0 -1
  223. package/dist/assets/flowDiagram-23GEKE2U-Bc73xdBd.js +0 -1
  224. package/dist/assets/gitGraph-TEB2WS4Q-Bvp27L0n.js +0 -1
  225. package/dist/assets/icons-cTkqD_Gi.js +0 -1
  226. package/dist/assets/index-B48prgLL.js +0 -65
  227. package/dist/assets/index-DQhwHHer.css +0 -3
  228. package/dist/assets/info-DKCQHKI2-BsLOivgq.js +0 -1
  229. package/dist/assets/packet-7NZHBO7P-BKQkXRtk.js +0 -1
  230. package/dist/assets/pie-RZYD4A2V-BTiTN5Ge.js +0 -1
  231. package/dist/assets/radar-I7S5WNFK-BU-oVjKM.js +0 -1
  232. package/dist/assets/railroad-3IZDKUUU-7H2hxNbL.js +0 -1
  233. package/dist/assets/railroad-abnf-AHOZXSZD-Mx6wf6XQ.js +0 -1
  234. package/dist/assets/railroad-ebnf-EBAXGLYW-BgXSKhYy.js +0 -1
  235. package/dist/assets/railroad-peg-LSFZ7HO6-DTEl2rAC.js +0 -1
  236. package/dist/assets/stateDiagram-v2-6OUMAXLB-D8x3mkni.js +0 -1
  237. package/dist/assets/swimlanesDiagram-G3AALYLV-C4nOBNp8.js +0 -8
  238. package/dist/assets/treeView-QDETBFTQ-DOE6NSdf.js +0 -1
  239. package/dist/assets/treemap-6X3UGDF4-Ca7QD_b4.js +0 -1
  240. package/dist/assets/wardley-OPB4EBWU-D9O4RKRm.js +0 -1
  241. /package/dist/assets/{array-DqLCdDFv.js → array-B9UHiPd-.js} +0 -0
  242. /package/dist/assets/{chunk-KEIR6QF5-s7Qq-R3i.js → chunk-KEIR6QF5-jrz1pRUS.js} +0 -0
  243. /package/dist/assets/{chunk-Y2CYZVJY-BgISNSiw.js → chunk-Y2CYZVJY-D6N-CrJv.js} +0 -0
  244. /package/dist/assets/{cytoscape.esm-iekjSZ2n.js → cytoscape.esm-DyfqweF2.js} +0 -0
  245. /package/dist/assets/{defaultLocale-CrJzLgRD.js → defaultLocale-5eAKkKJC.js} +0 -0
  246. /package/dist/assets/{dist-zzfqk5hx.js → dist-CLg13NtV.js} +0 -0
  247. /package/dist/assets/{graphlib-CIz_CfxW.js → graphlib-DJkmx0Cq.js} +0 -0
  248. /package/dist/assets/{init-C0r9Gk5G.js → init-DlZdxViB.js} +0 -0
  249. /package/dist/assets/{path-DIKpVbHL.js → path-6uRLdFF7.js} +0 -0
  250. /package/dist/assets/{plugin-api-C8hMT5W6.js → plugin-api-Uu2xAB4d.js} +0 -0
  251. /package/dist/assets/{rough.esm-BMOtDaaS.js → rough.esm-Bud4g4fh.js} +0 -0
  252. /package/dist/assets/{xterm-BFzZ1FH4.js → xterm-Bm_IbozX.js} +0 -0
  253. /package/plugins/{openai-documents → documents}/commands/document.md +0 -0
  254. /package/plugins/{openai-documents → documents}/skills/documents/SKILL.md +0 -0
  255. /package/plugins/{openai-presentations → presentations}/commands/presentation.md +0 -0
  256. /package/plugins/{openai-presentations → presentations}/skills/presentations/SKILL.md +0 -0
  257. /package/plugins/{openai-spreadsheets → spreadsheets}/commands/spreadsheet.md +0 -0
  258. /package/plugins/{openai-spreadsheets → spreadsheets}/skills/spreadsheets/SKILL.md +0 -0
@@ -0,0 +1,1696 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/AgentProfilesPage-Dl5Peqov.js","assets/rolldown-runtime-DWdDZTNf.js","assets/index-BivLuZvX.js","assets/pi-ai-Cr2ee4a0.js","assets/dist-yDHbi5ux.js","assets/pi-web-ui-DV5jKjSg.js","assets/lit-vendor-DvaQX_UQ.js","assets/css-utils-31qzCXsk.js","assets/icons-2D18YbSI.js","assets/react-vendor-3UaA-C9W.js","assets/skills-dialog-BTJ7mzk_.js","assets/model-display-label-C6-0eDxF.js","assets/model-reference-o41fJ6jQ.js","assets/index-1ei6nhs-.css","assets/model-identity-CgA6_Pbm.js","assets/mcp-servers-dialog-BEV4_TXC.js","assets/PluginsPage-BDKYfLna.js","assets/plugin-api-Uu2xAB4d.js","assets/ScheduledTasksPage--GAki3lB.js","assets/ShareLinksSettingsPage-BQQMsvJo.js","assets/CloudAccountSettingsPage-BG5Nn3bq.js"])))=>i.map(i=>d[i]);
2
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{Ct as t,Gt as n,It as r,Lt as i,P as a,Q as o,Rt as s,Vt as c,Wt as ee,Y as l,_ as u,_t as d,f as te,gt as f,jt as ne,m as p,qt as m,u as h,w as g,xt as _,y as re,zt as v}from"./icons-2D18YbSI.js";import{n as y,r as ie}from"./react-vendor-3UaA-C9W.js";import{c as ae,d as oe,f as se,l as ce,p as b,u as le}from"./lit-vendor-DvaQX_UQ.js";import{m as x,x as S}from"./pi-web-ui-DV5jKjSg.js";import{J as C}from"./pi-ai-Cr2ee4a0.js";import{n as w,t as ue}from"./model-display-label-C6-0eDxF.js";import{t as de}from"./model-reference-o41fJ6jQ.js";import{Ct as fe,J as pe,K as me,Pt as he,Qt as ge,St as _e,Tt as T,V as ve,Zt as E,_n as ye,a as be,an as xe,bt as Se,c as Ce,ct as we,dt as Te,en as Ee,fn as De,ft as D,gn as Oe,hn as O,ht as ke,i as Ae,in as je,l as Me,lt as Ne,mn as Pe,nn as Fe,on as Ie,ot as Le,pt as k,rn as Re,s as ze,sn as Be,st as Ve,un as He,ut as Ue,vn as A,vt as We,wt as j,yn as M,yt as Ge}from"./index-BivLuZvX.js";var N=e(m(),1),Ke={openai:{name:`OpenAI`,baseUrl:`https://api.openai.com/v1`,protocol:`openai-completions`,modelId:`gpt-4o`,supportsImages:!0},deepseek:{name:`DeepSeek`,baseUrl:`https://api.deepseek.com/v1`,protocol:`openai-completions`,modelId:`deepseek-chat`},glm:{name:`Zhipu GLM`,baseUrl:`https://open.bigmodel.cn/api/paas/v4`,protocol:`openai-completions`,modelId:`glm-4-plus`},ollama:{name:`Ollama`,baseUrl:`http://localhost:11434/v1`,protocol:`openai-completions`,modelId:`llama3.1`},litellm:{name:E.name,baseUrl:E.baseUrl,protocol:`openai-completions`,modelId:E.modelId,supportsImages:E.supportsImages}},qe=[{key:`openai`,label:M(`presetOpenai`)},{key:`deepseek`,label:M(`presetDeepseek`)},{key:`glm`,label:M(`presetGlm`)},{key:`ollama`,label:M(`presetOllama`)},{key:`litellm`,label:M(`presetLitellm`)},{key:`custom`,label:M(`presetCustom`)}],P=()=>({modelId:``,contextWindow:E.contextWindow,maxTokens:E.maxTokens,reasoning:!0,supportsImages:!1,visibleInSelectors:!0,open:!1}),F=()=>({name:E.name,baseUrl:E.baseUrl,apiKey:``,headerRows:[],protocol:`openai-completions`,models:[P()]}),Je=class extends x{providers=[];form=F();editingProviderId;formOpen=!1;loading=!0;apiKeyVisible=!1;advancedOpen=!1;activePreset=``;testing=!1;testResult=`idle`;testError=``;autoEditProviderName=null;async connectedCallback(){if(super.connectedCallback(),await this.loadProviders(),this.autoEditProviderName){let e=this.providers.find(e=>e.name===this.autoEditProviderName);e&&await this.openEditForm(e),this.autoEditProviderName=null}}getTabName(){return M(`customModels`)}async loadProviders(){this.loading=!0,this.requestUpdate();try{this.providers=await S().customProviders.getAll()}catch(e){w.error(`Failed to load custom providers:`,e),this.providers=[]}finally{this.loading=!1,this.requestUpdate()}}resetTestState(){this.testing=!1,this.testResult=`idle`,this.testError=``}openAddForm(){this.editingProviderId=void 0,this.form=F(),this.apiKeyVisible=!1,this.advancedOpen=!1,this.activePreset=``,this.resetTestState(),this.formOpen=!0,this.requestUpdate()}async openEditForm(e){let t=await S().providerKeys.get(e.name)??e.apiKey??``,n=e.models??[],r=n.length>0?n.map(e=>({modelId:e.id,contextWindow:e.contextWindow??E.contextWindow,maxTokens:e.maxTokens??E.maxTokens,reasoning:e.reasoning===!0,supportsImages:e.input?.includes(`image`)===!0,visibleInSelectors:e.quickforgeHidden!==!0,open:!1})):[P()],i=n[0]?.headers??{},a=Object.entries(i).map(([e,t])=>({key:e,value:String(t)}));this.editingProviderId=e.id,this.form={providerId:e.id,id:e.id,name:e.name,baseUrl:e.baseUrl,apiKey:t,headerRows:a,protocol:e.type===`anthropic-messages`?`anthropic-messages`:`openai-completions`,models:r},this.apiKeyVisible=!1,this.advancedOpen=a.length>0||e.type===`anthropic-messages`,this.activePreset=``,this.resetTestState(),this.formOpen=!0,this.requestUpdate()}closeForm(){this.formOpen=!1,this.editingProviderId=void 0,this.form=F(),this.apiKeyVisible=!1,this.advancedOpen=!1,this.activePreset=``,this.resetTestState(),this.requestUpdate()}toggleApiKeyVisibility(){this.apiKeyVisible=!this.apiKeyVisible,this.requestUpdate()}updateForm(e,t){this.form={...this.form,[e]:t},(e===`name`||e===`baseUrl`)&&(this.activePreset=``),this.resetTestState(),this.requestUpdate()}updateModelField(e,t,n){let r=this.form.models.map((r,i)=>i===e?{...r,[t]:n}:r);this.form={...this.form,models:r},t===`modelId`&&(this.activePreset=``,this.resetTestState()),this.requestUpdate()}addModelRow(){this.form={...this.form,models:[...this.form.models,P()]},this.requestUpdate()}removeModelRow(e){let t=this.form.models.filter((t,n)=>n!==e);this.form={...this.form,models:t},this.requestUpdate()}toggleModelExpanded(e){let t=this.form.models.map((t,n)=>n===e?{...t,open:!t.open}:t);this.form={...this.form,models:t},this.requestUpdate()}addHeaderRow(){this.form={...this.form,headerRows:[...this.form.headerRows,{key:``,value:``}]},this.requestUpdate()}updateHeaderRow(e,t,n){let r=this.form.headerRows.map((r,i)=>i===e?{...r,[t]:n}:r);this.form={...this.form,headerRows:r},this.requestUpdate()}removeHeaderRow(e){let t=this.form.headerRows.filter((t,n)=>n!==e);this.form={...this.form,headerRows:t},this.requestUpdate()}applyPreset(e){if(this.activePreset=e,e===`custom`)this.form={...this.form,name:``,baseUrl:``,protocol:`openai-completions`,models:[P()]};else{let t=Ke[e];this.form={...this.form,name:t.name,baseUrl:t.baseUrl,protocol:t.protocol,models:[{...P(),modelId:t.modelId,supportsImages:t.supportsImages===!0,open:!1}]}}this.resetTestState(),this.requestUpdate()}buildHeadersFromRows(){let e={};for(let t of this.form.headerRows){let n=t.key.trim(),r=t.value.trim();n&&r&&(e[n]=r)}return e}buildModel(e,t){let n=this.form.name.trim(),r=this.form.baseUrl.trim(),i=e.reasoning===!0,a=e.supportsImages===!0?[`text`,`image`]:[`text`],o=r.includes(`api.deepseek.com`);return je({id:e.modelId,name:`${e.modelId} (${n})`,api:this.form.protocol,provider:n,baseUrl:r.replace(/\/$/,``),reasoning:i,input:a,quickforgeHidden:e.visibleInSelectors?void 0:!0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:Number(e.contextWindow)||E.contextWindow,maxTokens:Number(e.maxTokens)||E.maxTokens,headers:Object.keys(t).length>0?t:void 0,thinkingLevelMap:o&&i?{low:`high`,medium:`high`,high:`high`,xhigh:`max`}:void 0,compat:this.form.protocol===`openai-completions`?{supportsStore:!1,supportsDeveloperRole:!1,supportsReasoningEffort:i,supportsUsageInStreaming:!1,supportsStrictMode:!1,maxTokensField:`max_tokens`,...o&&i?{requiresReasoningContentOnAssistantMessages:!0,thinkingFormat:`deepseek`}:{}}:void 0})}async testConnection(){let e=this.form.baseUrl.trim(),t=this.form.models.find(e=>e.modelId.trim());if(!e||!t){this.testing=!1,this.testResult=`fail`,this.testError=M(`testRequiresFields`),this.requestUpdate();return}let n=this.buildHeadersFromRows(),r=this.buildModel(t,n);this.testing=!0,this.testResult=`idle`,this.testError=``,this.requestUpdate();try{let e=await(await fetch(`/api/models/test-connection`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({model:r,apiKey:this.form.apiKey.trim()})})).json().catch(()=>({}));e?.ok?(this.testResult=`ok`,this.testError=``):(this.testResult=`fail`,this.testError=e?.error||M(`connectionFailed`))}catch(e){this.testResult=`fail`,this.testError=e?.message||M(`connectionFailed`)}finally{this.testing=!1,this.requestUpdate()}}async saveModel(){let e=this.form.name.trim(),t=this.form.baseUrl.trim();if(!e||!t){j(M(`fillProviderBaseUrlModel`));return}let n=this.form.models.filter(e=>e.modelId.trim());if(n.length===0){j(M(`atLeastOneModel`));return}let r=n.map(e=>e.modelId.trim());if(new Set(r).size!==r.length){j(M(`duplicateModelId`));return}let i=this.buildHeadersFromRows(),a=n.map(e=>this.buildModel(e,i)),o=this.form.apiKey.trim(),s=this.editingProviderId?this.providers.find(e=>e.id===this.editingProviderId):void 0,c={id:this.editingProviderId??Be(),name:e,type:this.form.protocol,baseUrl:a[0].baseUrl,apiKey:o||void 0,models:a};try{let e=S();await e.customProviders.set(c),s&&s.name!==c.name&&await e.providerKeys.delete(s.name),o?await e.providerKeys.set(c.name,o):await e.providerKeys.delete(c.name),He(),this.closeForm(),await this.loadProviders()}catch(e){w.error(`Failed to save custom model:`,e),j(M(`saveCustomModelFailed`))}}async deleteProvider(e){if(await T({description:M(`confirmDeleteProvider`,{name:e.name}),confirmLabel:M(`confirmDelete`),cancelLabel:M(`cancel`),variant:`destructive`}))try{let t=S();await t.customProviders.delete(e.id),await t.providerKeys.delete(e.name),He(),await this.loadProviders()}catch(e){w.error(`Failed to delete custom provider:`,e),j(M(`deleteFailed`))}}renderProvider(e){let t=e.models??[],n=t.length,r=e.type===`anthropic-messages`?`Anthropic Messages`:`OpenAI Compatible`;return b`
3
+ <div class="quickforge-settings-list-item">
4
+ <div class="quickforge-settings-list-item-main">
5
+ <div class="flex min-w-0 items-start gap-3">
6
+ <span class="quickforge-settings-avatar" aria-hidden="true">${e.name.trim().charAt(0).toUpperCase()||`M`}</span>
7
+ <div class="min-w-0 flex-1">
8
+ <div class="quickforge-settings-row-title">${e.name}</div>
9
+ <div class="quickforge-settings-row-description break-all">${e.baseUrl}</div>
10
+ <div class="quickforge-settings-meta">
11
+ <span class="quickforge-settings-badge quickforge-settings-badge-muted">${M(`providerProtocol`)}: ${r}</span>
12
+ <span class="quickforge-settings-badge quickforge-settings-badge-info">${M(`modelsCount`,{count:n})}</span>
13
+ ${n===0?b`<span class="quickforge-settings-badge quickforge-settings-badge-warning">${M(`noModelAdded`)}</span>`:null}
14
+ </div>
15
+ ${n>0?b`
16
+ <div class="quickforge-settings-meta">
17
+ ${t.slice(0,6).map(e=>b`
18
+ <code class="quickforge-settings-command-name">${e.id}</code>
19
+ `)}
20
+ ${t.length>6?b`<span class="quickforge-settings-badge quickforge-settings-badge-muted">+${t.length-6}</span>`:null}
21
+ </div>
22
+ `:null}
23
+ </div>
24
+ </div>
25
+ </div>
26
+ <div class="quickforge-settings-list-item-actions">
27
+ <button
28
+ class="quickforge-settings-button quickforge-settings-button-secondary quickforge-settings-button-compact"
29
+ type="button"
30
+ @click=${()=>this.openEditForm(e)}
31
+ >
32
+ ${M(`editModel`)}
33
+ </button>
34
+ <button
35
+ class="quickforge-settings-button quickforge-settings-button-danger quickforge-settings-button-compact"
36
+ type="button"
37
+ @click=${()=>this.deleteProvider(e)}
38
+ >
39
+ ${M(`delete`)}
40
+ </button>
41
+ </div>
42
+ </div>
43
+ `}renderPresetChips(){return b`
44
+ <div class="quickforge-settings-form-row">
45
+ <span class="quickforge-settings-form-label">${M(`presets`)}</span>
46
+ <div class="quickforge-settings-segmented quickforge-settings-segmented-wrap">
47
+ ${qe.map(e=>b`
48
+ <button
49
+ class="quickforge-settings-segmented-option ${this.activePreset===e.key?`quickforge-settings-segmented-option-active`:``}"
50
+ type="button"
51
+ @click=${()=>this.applyPreset(e.key)}
52
+ >
53
+ ${e.label}
54
+ </button>
55
+ `)}
56
+ </div>
57
+ </div>
58
+ `}renderModelRow(e,t){let n=e.open===!0;return b`
59
+ <div class="quickforge-settings-subrow quickforge-settings-row-align-start">
60
+ <button
61
+ class="quickforge-settings-icon-action"
62
+ type="button"
63
+ title=${M(`expandModel`)}
64
+ aria-expanded=${n?`true`:`false`}
65
+ @click=${()=>this.toggleModelExpanded(t)}
66
+ >
67
+ ${n?`▾`:`▸`}
68
+ </button>
69
+ <div class="quickforge-settings-list-item-main">
70
+ <input
71
+ class="quickforge-settings-input quickforge-settings-mono"
72
+ .value=${e.modelId}
73
+ @input=${e=>this.updateModelField(t,`modelId`,e.target.value)}
74
+ placeholder=${M(`modelIdPlaceholder`)}
75
+ />
76
+ ${n?b`
77
+ <div class="quickforge-settings-model-grid mt-3">
78
+ <label class="quickforge-settings-form-row">
79
+ <span class="quickforge-settings-form-label">${M(`contextWindow`)}</span>
80
+ <input
81
+ class="quickforge-settings-input"
82
+ .value=${String(e.contextWindow)}
83
+ type="number"
84
+ @input=${e=>this.updateModelField(t,`contextWindow`,Number(e.target.value))}
85
+ />
86
+ </label>
87
+ <label class="quickforge-settings-form-row">
88
+ <span class="quickforge-settings-form-label">${M(`maxTokens`)}</span>
89
+ <input
90
+ class="quickforge-settings-input"
91
+ .value=${String(e.maxTokens)}
92
+ type="number"
93
+ @input=${e=>this.updateModelField(t,`maxTokens`,Number(e.target.value))}
94
+ />
95
+ </label>
96
+ </div>
97
+ <label class="mt-3 flex items-center gap-2 text-sm text-muted-foreground">
98
+ <input
99
+ type="checkbox"
100
+ .checked=${e.reasoning}
101
+ @change=${e=>this.updateModelField(t,`reasoning`,e.target.checked)}
102
+ />
103
+ <span>${M(`reasoningModel`)}</span>
104
+ </label>
105
+ <label class="mt-2 flex items-center gap-2 text-sm text-muted-foreground">
106
+ <input
107
+ type="checkbox"
108
+ .checked=${e.supportsImages}
109
+ @change=${e=>this.updateModelField(t,`supportsImages`,e.target.checked)}
110
+ />
111
+ <span>
112
+ ${M(`imageInputModel`)}
113
+ <quickforge-info-tip .label=${M(`imageInputModelHelp`)}></quickforge-info-tip>
114
+ </span>
115
+ </label>
116
+ <div class="mt-3 flex items-center justify-between gap-3 rounded-lg border border-border px-3 py-2">
117
+ <span class="text-sm text-muted-foreground">${M(`showModelInSelectors`)}</span>
118
+ <label class="quickforge-settings-switch" title=${M(`showModelInSelectorsHelp`)}>
119
+ <input
120
+ type="checkbox"
121
+ .checked=${e.visibleInSelectors}
122
+ @change=${e=>this.updateModelField(t,`visibleInSelectors`,e.target.checked)}
123
+ />
124
+ <span aria-hidden="true"></span>
125
+ </label>
126
+ </div>
127
+ `:null}
128
+ </div>
129
+ ${this.form.models.length>1?b`
130
+ <button
131
+ class="quickforge-settings-icon-action quickforge-settings-icon-action-danger"
132
+ type="button"
133
+ title=${M(`delete`)}
134
+ @click=${()=>this.removeModelRow(t)}
135
+ >
136
+
137
+ </button>
138
+ `:null}
139
+ </div>
140
+ `}renderHeadersEditor(){return b`
141
+ <div class="quickforge-settings-form-row">
142
+ <span class="quickforge-settings-form-label">
143
+ ${M(`customHeaders`)}
144
+ <quickforge-info-tip .label=${M(`customHeadersHelp`)}></quickforge-info-tip>
145
+ </span>
146
+ ${this.form.headerRows.length===0?b``:b`
147
+ <div class="quickforge-settings-nested-list">
148
+ ${this.form.headerRows.map((e,t)=>b`
149
+ <div class="quickforge-settings-subrow">
150
+ <input
151
+ class="quickforge-settings-input"
152
+ .value=${e.key}
153
+ @input=${e=>this.updateHeaderRow(t,`key`,e.target.value)}
154
+ placeholder=${M(`headerName`)}
155
+ />
156
+ <input
157
+ class="quickforge-settings-input"
158
+ .value=${e.value}
159
+ @input=${e=>this.updateHeaderRow(t,`value`,e.target.value)}
160
+ placeholder=${M(`headerValue`)}
161
+ />
162
+ <button
163
+ class="quickforge-settings-icon-action quickforge-settings-icon-action-danger"
164
+ type="button"
165
+ title=${M(`removeHeader`)}
166
+ @click=${()=>this.removeHeaderRow(t)}
167
+ >
168
+
169
+ </button>
170
+ </div>
171
+ `)}
172
+ </div>
173
+ `}
174
+ <button
175
+ class="quickforge-settings-button quickforge-settings-button-secondary quickforge-settings-button-compact"
176
+ type="button"
177
+ @click=${()=>this.addHeaderRow()}
178
+ >
179
+ + ${M(`addHeader`)}
180
+ </button>
181
+ </div>
182
+ `}renderTestStatus(){return this.testResult===`idle`&&!this.testing?b``:this.testing?b`<span class="quickforge-settings-status">${M(`testingConnection`)}</span>`:this.testResult===`ok`?b`<span class="quickforge-settings-badge quickforge-settings-badge-success">✓ ${M(`connectionOk`)}</span>`:b`<span class="quickforge-settings-alert">✗ ${this.testError||M(`connectionFailed`)}</span>`}renderForm(){return b`
183
+ <section class="quickforge-settings-section" aria-label=${this.editingProviderId?M(`editCustomModel`):M(`addCustomModel`)}>
184
+ <div class="quickforge-settings-toolbar">
185
+ <button
186
+ class="quickforge-settings-button quickforge-settings-button-secondary"
187
+ type="button"
188
+ @click=${()=>this.closeForm()}
189
+ >
190
+ <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m12 19-7-7 7-7"/><path d="M19 12H5"/></svg>
191
+ ${M(`back`)}
192
+ </button>
193
+ <div class="quickforge-settings-row-main">
194
+ <div class="quickforge-settings-row-title">${this.editingProviderId?M(`editCustomModel`):M(`addCustomModel`)}</div>
195
+ <div class="quickforge-settings-row-description">${M(`customModelsDescription`)}</div>
196
+ </div>
197
+ </div>
198
+
199
+ <div class="quickforge-settings-form-grid">
200
+ ${this.renderPresetChips()}
201
+
202
+ <label class="quickforge-settings-form-row">
203
+ <span class="quickforge-settings-form-label">${M(`providerName`)}</span>
204
+ <input
205
+ class="quickforge-settings-input"
206
+ .value=${this.form.name}
207
+ @input=${e=>this.updateForm(`name`,e.target.value)}
208
+ placeholder=${M(`providerNamePlaceholder`)}
209
+ />
210
+ </label>
211
+
212
+ <label class="quickforge-settings-form-row">
213
+ <span class="quickforge-settings-form-label">Base URL</span>
214
+ <input
215
+ class="quickforge-settings-input"
216
+ .value=${this.form.baseUrl}
217
+ @input=${e=>this.updateForm(`baseUrl`,e.target.value)}
218
+ placeholder=${this.form.protocol===`anthropic-messages`?`e.g., https://api.anthropic.com`:`e.g., http://localhost:4000/v1`}
219
+ />
220
+ </label>
221
+
222
+ <label class="quickforge-settings-form-row">
223
+ <span class="quickforge-settings-form-label">${M(`apiKey`)}</span>
224
+ <div class="quickforge-settings-inline-field">
225
+ <input
226
+ class="quickforge-settings-input pr-10"
227
+ .value=${this.form.apiKey}
228
+ type=${this.apiKeyVisible?`text`:`password`}
229
+ @input=${e=>this.updateForm(`apiKey`,e.target.value)}
230
+ placeholder=${M(`apiKeyPlaceholder`)}
231
+ />
232
+ <button
233
+ class="quickforge-settings-inline-field-button"
234
+ type="button"
235
+ title=${this.apiKeyVisible?M(`hideApiKey`):M(`showApiKey`)}
236
+ aria-label=${this.apiKeyVisible?M(`hideApiKey`):M(`showApiKey`)}
237
+ aria-pressed=${this.apiKeyVisible?`true`:`false`}
238
+ @click=${()=>this.toggleApiKeyVisibility()}
239
+ >
240
+ ${this.apiKeyVisible?b`<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.53 13.53 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" y1="2" x2="22" y2="22"/><path d="M8.53 8.53A5 5 0 0 0 12 17a5 5 0 0 0 3.47-8.53"/></svg>`:b`<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>`}
241
+ </button>
242
+ </div>
243
+ </label>
244
+
245
+ <div class="quickforge-settings-form-row">
246
+ <div class="flex items-center justify-between gap-3">
247
+ <span class="quickforge-settings-form-label">${M(`modelsList`)}</span>
248
+ <button
249
+ class="quickforge-settings-button quickforge-settings-button-secondary quickforge-settings-button-compact"
250
+ type="button"
251
+ @click=${()=>this.addModelRow()}
252
+ >
253
+ + ${M(`addModel`)}
254
+ </button>
255
+ </div>
256
+ <div class="quickforge-settings-nested-list">
257
+ ${this.form.models.map((e,t)=>this.renderModelRow(e,t))}
258
+ </div>
259
+ </div>
260
+
261
+ <button
262
+ class="quickforge-settings-details-toggle"
263
+ type="button"
264
+ aria-expanded=${this.advancedOpen?`true`:`false`}
265
+ @click=${()=>{this.advancedOpen=!this.advancedOpen,this.requestUpdate()}}
266
+ >
267
+ <span>${this.advancedOpen?`▾`:`▸`}</span>
268
+ ${M(`providerAdvanced`)}
269
+ </button>
270
+
271
+ ${this.advancedOpen?b`
272
+ <div class="quickforge-settings-form-grid rounded-lg border border-border p-3">
273
+ <label class="quickforge-settings-form-row">
274
+ <span class="quickforge-settings-form-label">
275
+ ${M(`protocolType`)}
276
+ <quickforge-info-tip .label=${M(`protocolHelp`)}></quickforge-info-tip>
277
+ </span>
278
+ <select
279
+ class="quickforge-settings-select"
280
+ .value=${this.form.protocol}
281
+ @change=${e=>this.updateForm(`protocol`,e.target.value)}
282
+ >
283
+ <option value="openai-completions">OpenAI Compatible / Chat Completions</option>
284
+ <option value="anthropic-messages">Anthropic Messages</option>
285
+ </select>
286
+ </label>
287
+ ${this.renderHeadersEditor()}
288
+ </div>
289
+ `:null}
290
+ </div>
291
+
292
+ <div class="quickforge-settings-row">
293
+ <div class="quickforge-settings-row-main">
294
+ ${this.renderTestStatus()}
295
+ </div>
296
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
297
+ <button
298
+ class="quickforge-settings-button quickforge-settings-button-secondary"
299
+ type="button"
300
+ @click=${()=>this.closeForm()}
301
+ >
302
+ ${M(`cancel`)}
303
+ </button>
304
+ <button
305
+ class="quickforge-settings-button quickforge-settings-button-secondary"
306
+ type="button"
307
+ ?disabled=${this.testing}
308
+ @click=${()=>this.testConnection()}
309
+ >
310
+ ${this.testing?M(`testingConnection`):M(`testConnection`)}
311
+ </button>
312
+ <button
313
+ class="quickforge-settings-button quickforge-settings-button-primary"
314
+ type="button"
315
+ @click=${()=>this.saveModel()}
316
+ >
317
+ ${M(`save`)}
318
+ </button>
319
+ </div>
320
+ </div>
321
+ </section>
322
+ `}render(){return this.formOpen?b`
323
+ <div class="quickforge-settings-stack">
324
+ <div class="quickforge-settings-heading">
325
+ <h3 class="quickforge-settings-title">
326
+ ${this.editingProviderId?M(`editCustomModel`):M(`addCustomModel`)}
327
+ <quickforge-info-tip .label=${M(`customModelsDescription`)}></quickforge-info-tip>
328
+ </h3>
329
+ </div>
330
+ ${this.renderForm()}
331
+ </div>
332
+ `:b`
333
+ <div class="quickforge-settings-stack">
334
+ <section class="quickforge-settings-section" aria-label=${M(`customModelsTitle`)}>
335
+ <div class="quickforge-settings-toolbar">
336
+ <div>
337
+ <div class="quickforge-settings-row-title">${M(`customModelsTitle`)}</div>
338
+ <div class="quickforge-settings-row-description">${M(`customModelsDescription`)}</div>
339
+ </div>
340
+ <button
341
+ class="quickforge-settings-button quickforge-settings-button-primary"
342
+ type="button"
343
+ @click=${()=>this.openAddForm()}
344
+ >
345
+ ${M(`addModel`)}
346
+ </button>
347
+ </div>
348
+
349
+ ${this.loading?b`<div class="quickforge-settings-empty-row">${M(`loading`)}</div>`:this.providers.length===0?b`<div class="quickforge-settings-empty-row">${M(`noCustomModels`)}</div>`:this.providers.map(e=>this.renderProvider(e))}
350
+ </section>
351
+ </div>
352
+ `}},I=`quickforge-custom-providers-only-tab`;customElements.get(I)||customElements.define(I,Je);function Ye(e){let t=document.createElement(I);return e&&(t.autoEditProviderName=e),t}var Xe=[{value:`light`,label:()=>M(`lightTheme`)},{value:`dark`,label:()=>M(`darkTheme`)}],Ze=class extends x{theme=Ne();interfaceFontSizePx=D.interfaceFontSizePx;messageFontSizePx=D.messageFontSizePx;loading=!0;error=``;getTabName(){return M(`appearance`)}async connectedCallback(){super.connectedCallback(),await this.loadSettings()}async loadSettings(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=S(),[t,n]=await Promise.all([Ue(e),We(e)]);this.theme=t.theme,this.interfaceFontSizePx=n.interfaceFontSizePx,this.messageFontSizePx=n.messageFontSizePx}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async selectTheme(e){if(this.theme!==e){this.theme=e,this.requestUpdate();try{await Te(S(),{theme:e}),this.error=``,this.requestUpdate()}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}}}currentFontSizeSettings(){return Ge({interfaceFontSizePx:this.interfaceFontSizePx,messageFontSizePx:this.messageFontSizePx})}previewFontSize(e){let t=Ge(e);this.interfaceFontSizePx=t.interfaceFontSizePx,this.messageFontSizePx=t.messageFontSizePx,ke(t),this.requestUpdate()}updateInterfaceFontSize(e){this.previewFontSize({...this.currentFontSizeSettings(),interfaceFontSizePx:Number(e)||D.interfaceFontSizePx})}updateMessageFontSize(e){this.previewFontSize({...this.currentFontSizeSettings(),messageFontSizePx:Number(e)||D.messageFontSizePx})}async saveFontSize(){try{await Se(S(),this.currentFontSizeSettings()),this.error=``,this.requestUpdate()}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}}renderThemeOption(e){let t=this.theme===e.value;return b`
353
+ <button
354
+ type="button"
355
+ class="quickforge-settings-segmented-option ${t?`quickforge-settings-segmented-option-active`:``}"
356
+ aria-pressed=${t?`true`:`false`}
357
+ @click=${()=>this.selectTheme(e.value)}
358
+ >
359
+ ${e.label()}
360
+ </button>
361
+ `}getFontSizeRangeProgress(e){return(e-k.min)/(k.max-k.min)*100}renderFontSizeSlider(e,t,n,r){return b`
362
+ <div class="quickforge-settings-row">
363
+ <div class="quickforge-settings-row-main">
364
+ <div class="quickforge-settings-row-title">
365
+ ${e}
366
+ ${t?b`<quickforge-info-tip .label=${t}></quickforge-info-tip>`:null}
367
+ </div>
368
+ <div class="quickforge-settings-row-description">${M(`fontSizeRangeDescription`)}</div>
369
+ </div>
370
+ <div class="quickforge-settings-row-control quickforge-settings-slider-control">
371
+ <span class="quickforge-settings-value-badge">${n}px</span>
372
+ <input
373
+ class="quickforge-font-size-slider"
374
+ style=${`--quickforge-font-size-slider-progress: ${this.getFontSizeRangeProgress(n)}%`}
375
+ type="range"
376
+ min=${String(k.min)}
377
+ max=${String(k.max)}
378
+ step="1"
379
+ .value=${String(n)}
380
+ @input=${e=>r(e.target.value)}
381
+ @change=${()=>this.saveFontSize()}
382
+ />
383
+ </div>
384
+ </div>
385
+ `}render(){return this.loading?b`<div class="text-sm text-muted-foreground">${M(`loading`)}</div>`:b`
386
+ <div class="quickforge-settings-stack">
387
+ <section class="quickforge-settings-section" aria-label=${M(`appearance`)}>
388
+ <div class="quickforge-settings-row">
389
+ <div class="quickforge-settings-row-main">
390
+ <div class="quickforge-settings-row-title">
391
+ ${M(`theme`)}
392
+ <quickforge-info-tip .label=${M(`themeDescription`)}></quickforge-info-tip>
393
+ </div>
394
+ <div class="quickforge-settings-row-description">${M(`themeDescription`)}</div>
395
+ </div>
396
+ <div class="quickforge-settings-row-control">
397
+ <div class="quickforge-settings-segmented" role="group" aria-label=${M(`theme`)}>
398
+ ${Xe.map(e=>this.renderThemeOption(e))}
399
+ </div>
400
+ </div>
401
+ </div>
402
+
403
+ ${this.renderFontSizeSlider(M(`interfaceFontSize`),null,this.interfaceFontSizePx,e=>this.updateInterfaceFontSize(e))}
404
+
405
+ ${this.renderFontSizeSlider(M(`messageFontSize`),M(`messageFontSizeNote`),this.messageFontSizePx,e=>this.updateMessageFontSize(e))}
406
+ </section>
407
+
408
+ ${this.error?b`<span class="quickforge-settings-error">${this.error}</span>`:null}
409
+ </div>
410
+ `}},L=`quickforge-appearance-settings-tab`;customElements.get(L)||customElements.define(L,Ze);function Qe(){return document.createElement(L)}var $e=`auto-compact-settings`,R={enabled:!0,thresholdPercent:80,keepRecentTurns:3,minSourceChars:1600,requireConfirmation:!0};function z(e,t,n,r){let i=Number(e);return Number.isFinite(i)?Math.min(r,Math.max(n,Math.round(i))):t}function et(e){if(!e||typeof e!=`object`)return{...R};let t=e;return{enabled:t.enabled!==!1,thresholdPercent:z(t.thresholdPercent,R.thresholdPercent,50,95),keepRecentTurns:z(t.keepRecentTurns,R.keepRecentTurns,1,20),minSourceChars:z(t.minSourceChars,R.minSourceChars,0,2e5),requireConfirmation:t.requireConfirmation!==!1}}async function tt(e){return et(await e.settings.get($e))}async function nt(e,t){await e.settings.set($e,et(t))}var rt=`auto-archive-settings`,it={enabled:!1};function at(e){return!e||typeof e!=`object`?{...it}:{enabled:e.enabled===!0}}async function ot(e){return at(await e.settings.get(rt))}async function st(e,t){await e.settings.set(rt,at(t))}var ct=0,lt=class extends le{static properties={value:{type:String},placeholder:{type:String},options:{type:Array},disabled:{type:Boolean},label:{type:String},searchable:{type:Boolean},searchPlaceholder:{type:String},noResultsLabel:{type:String}};value=``;placeholder=``;options=[];disabled=!1;label=``;searchable=!1;searchPlaceholder=``;noResultsLabel=``;triggerRef=ae();searchRef=ae();_menu=null;_menuId=`quickforge-settings-select-menu-${++ct}`;_listboxId=`quickforge-settings-select-listbox-${++ct}`;_open=!1;_searchQuery=``;focusedIndex=-1;createRenderRoot(){return this}render(){let e=this.options.find(e=>e.value===this.value);return b`
411
+ <button
412
+ ${ce(this.triggerRef)}
413
+ type="button"
414
+ class="quickforge-settings-select quickforge-settings-select-button quickforge-settings-select-trigger"
415
+ role="combobox"
416
+ aria-haspopup="listbox"
417
+ aria-expanded=${this._open?`true`:`false`}
418
+ aria-controls=${this._listboxId}
419
+ aria-activedescendant=${this._open?this._focusedOptionId():void 0}
420
+ aria-label=${this.label}
421
+ ?disabled=${this.disabled}
422
+ @click=${this._toggle}
423
+ @keydown=${this._handleTriggerKeyDown}
424
+ >
425
+ <span class="quickforge-settings-select-trigger-label">${e?e.label:this.placeholder}</span>
426
+ <span class="quickforge-settings-select-chevron" aria-hidden="true">▾</span>
427
+ </button>
428
+ `}updated(){this._refreshMenu()}disconnectedCallback(){super.disconnectedCallback(),this._close()}_toggle=()=>{this.disabled||(this._open?this._close(!0):this._openMenu())};_handleTriggerKeyDown=e=>{if(this.disabled||this._open)return;let t;switch(e.key){case`ArrowDown`:case`Home`:t=this._selectableIndexes()[0]??-1;break;case`ArrowUp`:case`End`:{let e=this._selectableIndexes();t=e[e.length-1]??-1;break}default:return}e.preventDefault(),this._openMenu(t)};_openMenu(e){if(this.disabled||this._open||!this.triggerRef.value)return;let t=this._selectableIndexes(),n=this.options.findIndex(e=>e.value===this.value);this.focusedIndex=e===void 0?n>=0&&!this.options[n].disabled?n:t[0]??-1:e,this._open=!0,this._attachMenu(),document.addEventListener(`pointerdown`,this._handlePointerDown,!0),document.addEventListener(`keydown`,this._handleKeyDown),window.addEventListener(`scroll`,this._reposition,!0),window.addEventListener(`resize`,this._reposition),this.requestUpdate(),this.searchable&&this.searchRef.value?.focus(),this._scrollFocusedIntoView()}_close(e=!1){this._open&&(this._open=!1,this.focusedIndex=-1,this._searchQuery=``,this._removeMenu(),document.removeEventListener(`pointerdown`,this._handlePointerDown,!0),document.removeEventListener(`keydown`,this._handleKeyDown),window.removeEventListener(`scroll`,this._reposition,!0),window.removeEventListener(`resize`,this._reposition),e&&this.triggerRef.value?.focus(),this.requestUpdate())}_select(e){this._close(!0),this.dispatchEvent(new CustomEvent(`change`,{detail:e,bubbles:!0,composed:!0}))}_selectFocused(){let e=this.options[this.focusedIndex];e&&!e.disabled&&this._select(e.value)}_isVisible(e){if(!this.searchable)return!0;let t=this._searchQuery.trim().toLowerCase();return t?e.label.toLowerCase().includes(t):!0}_selectableIndexes(){return this.options.map((e,t)=>!e.disabled&&this._isVisible(e)?t:-1).filter(e=>e>=0)}_moveFocus(e){let t=this._selectableIndexes();if(t.length===0)return;let n=t.indexOf(this.focusedIndex),r=n>=0?n:e>0?-1:0,i=Math.max(0,Math.min(t.length-1,r+e));this.focusedIndex=t[i],this._scrollFocusedIntoView()}_attachMenu(){if(this._removeMenu(),!this.triggerRef.value)return;let e=document.createElement(`div`);e.className=`quickforge-settings-select-menu`,e.id=this._menuId,document.body.appendChild(e),this._menu=e,this._renderMenuItems(),this._reposition()}_removeMenu(){this._menu&&=(this._menu.remove(),null)}_renderMenuItems(){this._menu&&se(this._menuTemplate(),this._menu)}_rerenderMenuItems(){this._open&&this._menu&&this._renderMenuItems()}_refreshMenu(){if(!this._open||!this._menu)return;let e=this._selectableIndexes();e.includes(this.focusedIndex)||(this.focusedIndex=e[0]??-1),this._renderMenuItems(),this._reposition()}_reposition=()=>{let e=this._menu,t=this.triggerRef.value;if(!e||!t)return;let n=t.getBoundingClientRect(),r=Math.min(300,e.offsetHeight||300),i=window.innerHeight-n.bottom,a=n.top,o=i-6<r&&a>i,s=Math.max(0,(o?a:i)-6-8);e.style.top=o?`auto`:`${Math.round(n.bottom+6)}px`,e.style.bottom=o?`${Math.round(window.innerHeight-n.top+6)}px`:`auto`,e.style.maxHeight=`${Math.max(120,Math.min(300,s))}px`,e.style.minWidth=`max(12rem, ${Math.round(n.width)}px)`;let c=e.offsetWidth,ee=Math.max(8,Math.min(n.left,window.innerWidth-c-8));e.style.left=`${Math.round(ee)}px`};_optionId(e){return`${this._listboxId}-option-${e}`}_focusedOptionId(){return this.focusedIndex>=0?this._optionId(this.focusedIndex):void 0}_isSearchFocused(){return this.searchable&&document.activeElement===this.searchRef.value}_scrollFocusedIntoView(){let e=this._menu;if(!e||this.focusedIndex<0)return;let t=e.querySelector(`.quickforge-settings-select-listbox`),n=e.querySelector(`[id="${this._optionId(this.focusedIndex)}"]`);if(!t||!n)return;let r=t.getBoundingClientRect(),i=n.getBoundingClientRect();i.top<r.top?t.scrollTop-=r.top-i.top:i.bottom>r.bottom&&(t.scrollTop+=i.bottom-r.bottom)}_menuTemplate(){let e=this._focusedOptionId(),t=this.options.filter(e=>this._isVisible(e)).length;return b`
429
+ ${this.searchable?b`
430
+ <div class="quickforge-settings-select-search">
431
+ <input
432
+ ${ce(this.searchRef)}
433
+ class="quickforge-settings-select-search-input"
434
+ type="text"
435
+ role="searchbox"
436
+ placeholder=${this.searchPlaceholder}
437
+ aria-label=${this.label}
438
+ aria-controls=${this._listboxId}
439
+ aria-activedescendant=${e}
440
+ .value=${this._searchQuery}
441
+ @input=${this._handleSearchInput}
442
+ >
443
+ </div>
444
+ `:``}
445
+ <div
446
+ id=${this._listboxId}
447
+ class="quickforge-settings-select-listbox"
448
+ role="listbox"
449
+ aria-label=${this.label}
450
+ >
451
+ ${this.options.map((e,t)=>{if(!this._isVisible(e))return oe;let n=e.value===this.value,r=this.focusedIndex===t;return b`
452
+ <div
453
+ id=${this._optionId(t)}
454
+ role="option"
455
+ aria-selected=${n?`true`:`false`}
456
+ aria-disabled=${e.disabled?`true`:`false`}
457
+ class="quickforge-settings-select-option${r?` quickforge-settings-select-option-focused`:``}${n?` quickforge-settings-select-option-selected`:``}${e.disabled?` quickforge-settings-select-option-disabled`:``}"
458
+ @mousemove=${()=>{!e.disabled&&this.focusedIndex!==t&&(this.focusedIndex=t,this._rerenderMenuItems())}}
459
+ @click=${()=>{e.disabled||this._select(e.value)}}
460
+ >
461
+ <span class="quickforge-settings-select-option-label">${e.label}</span>
462
+ ${n?b`
463
+ <svg class="quickforge-settings-select-option-check" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"></polyline></svg>
464
+ `:``}
465
+ </div>
466
+ `})}
467
+ </div>
468
+ ${this.searchable&&t===0?b`
469
+ <div class="quickforge-settings-select-no-results" role="status">${this.noResultsLabel}</div>
470
+ `:``}
471
+ `}_handleSearchInput=e=>{let t=e.target;this._searchQuery=t.value,this._rerenderMenuItems();let n=this._selectableIndexes();n.includes(this.focusedIndex)||(this.focusedIndex=n[0]??-1),this._reposition(),this._scrollFocusedIntoView()};_handlePointerDown=e=>{let t=e.target;t&&(this.contains(t)||this._menu?.contains(t)||this._close(!0))};_handleKeyDown=e=>{if(!(!this._open||e.isComposing))switch(e.key){case`ArrowDown`:e.preventDefault(),this._moveFocus(1),this._rerenderMenuItems();break;case`ArrowUp`:e.preventDefault(),this._moveFocus(-1),this._rerenderMenuItems();break;case`Home`:{e.preventDefault();let t=this._selectableIndexes();this.focusedIndex=t[0]??-1,this._rerenderMenuItems(),this._scrollFocusedIntoView();break}case`End`:{e.preventDefault();let t=this._selectableIndexes();this.focusedIndex=t[t.length-1]??-1,this._rerenderMenuItems(),this._scrollFocusedIntoView();break}case`Enter`:e.preventDefault(),this._selectFocused();break;case` `:if(this._isSearchFocused())break;e.preventDefault(),this._selectFocused();break;case`Escape`:e.preventDefault(),this._close(!0);break;case`Tab`:this._close(),this.triggerRef.value?.focus();break}}},ut=`quickforge-settings-select`;customElements.get(ut)||customElements.define(ut,lt);var dt=[{value:`off`,label:()=>M(`thinkingOff`)},{value:`low`,label:()=>M(`thinkingLow`)},{value:`medium`,label:()=>M(`thinkingMedium`)},{value:`high`,label:()=>M(`thinkingHigh`)},{value:`xhigh`,label:()=>M(`thinkingXHigh`)}],ft=[{value:`compact`,label:()=>M(`toolDisplayCompact`)},{value:`detailed`,label:()=>M(`toolDisplayDetailed`)}],B=`__custom__`;function pt(e){return(e??``).trim().replace(/\/$/,``)}function V(e){return JSON.stringify([e.provider,e.id,e.api,pt(e.baseUrl)])}function mt(){return`custom_${globalThis.crypto?.randomUUID?.().slice(0,8)||Date.now().toString(36)}`}function ht(e){let t=e.trim(),n=t.split(/[\\/]/).pop()?.replace(/^"|"$/g,``)||t;return/^bash(\.exe)?$/i.test(n)?`Bash`:/^zsh$/i.test(n)?`Zsh`:/^fish$/i.test(n)?`Fish`:/^cmd(\.exe)?$/i.test(n)?`Command Prompt`:/^powershell(\.exe)?$/i.test(n)?`Windows PowerShell`:/^pwsh(\.exe)?$/i.test(n)?`PowerShell 7+`:n||`Custom Shell`}var gt=b`
472
+ <svg class="size-3.5" viewBox="0 0 16 16" fill="none" aria-hidden="true">
473
+ <path d="M4.5 4.5 11.5 11.5M11.5 4.5 4.5 11.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" />
474
+ </svg>
475
+ `,_t=class extends x{models=[];selectedModel;harness=`quickforge`;savedHarness=`quickforge`;defaultOptionsSavePromise=Promise.resolve();thinkingLevel=`off`;toolDisplayMode=`compact`;showContextUsage=!1;autoCompactEnabled=!0;autoCompactRequireConfirmation=!0;autoCompactThresholdPercent=80;autoCompactThresholdPercentInput=`80`;autoCompactKeepRecentTurns=3;autoArchiveEnabled=!1;systemNotificationsEnabled=!1;systemNotificationPermission=`unsupported`;systemNotificationBusy=!1;selectedLanguage=ye();loading=!0;saved=!1;savedMessage=``;error=``;terminalShellConfig={terminalShell:`auto`,defaultProfileId:`auto`,profiles:[]};customShellCommand=``;customShellEditorOpen=!1;networkProxyMode=`direct`;networkProxyUrl=``;savedNetworkProxyConfig={mode:`direct`,proxyUrl:``};networkProxyStatus=null;networkProxySaving=!1;networkProxyLoaded=!1;getTabName(){return M(`defaultOptions`)}connectedCallback(){super.connectedCallback(),this.loadSettings(),window.addEventListener(ve,this.handleCloudStateChanged)}disconnectedCallback(){window.removeEventListener(ve,this.handleCloudStateChanged),super.disconnectedCallback?.()}handleCloudStateChanged=()=>{this.loadSettings()};async loadCloudModels(){try{let e=await pe();return!e.configured||e.enabled===!1||e.mode===`local`||!e.hasSession?[]:await me()}catch(e){return w.warn(`Failed to load QuickForge Cloud models for default options:`,e),[]}}async loadSettings(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=S(),[t,n,r,i,a,o,s]=await Promise.all([Ee(e),de().catch(()=>[]),this.loadCloudModels(),Fe(e),_e(e),tt(e),ot(e)]),c=Re(n.length?n:t,r);this.models=c,this.selectedModel=i.model?c.find(e=>V(e)===V(i.model))??c[0]:c[0],this.thinkingLevel=i.thinkingLevel??ge(this.selectedModel),this.harness=i.harness??`quickforge`,this.savedHarness=this.harness,this.toolDisplayMode=a.toolDisplayMode,this.showContextUsage=a.showContextUsage,this.autoCompactEnabled=o.enabled,this.autoCompactRequireConfirmation=o.requireConfirmation,this.autoCompactThresholdPercent=o.thresholdPercent,this.autoCompactThresholdPercentInput=String(o.thresholdPercent),this.autoCompactKeepRecentTurns=o.keepRecentTurns,this.autoArchiveEnabled=s.enabled,this.systemNotificationsEnabled=be(),this.systemNotificationPermission=await Ae(),this.systemNotificationsEnabled&&this.systemNotificationPermission!==`granted`&&(this.systemNotificationsEnabled=!1,Ce(!1)),await Promise.all([this.loadTerminalShell(),this.loadNetworkProxy()])}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}updateModel(e){let t=this.models.find(t=>V(t)===e);this.selectedModel=t,this.thinkingLevel=ge(t),this.saved=!1,this.requestUpdate(),this.saveDefaultModelOptions()}updateHarness(e){this.harness=e===`opencode`?`opencode`:`quickforge`,this.saved=!1,this.requestUpdate(),this.saveDefaultModelOptions()}updateThinkingLevel(e){this.thinkingLevel=dt.some(t=>t.value===e)?e:`off`,this.saved=!1,this.requestUpdate(),this.saveDefaultModelOptions()}updateLanguage(e){this.selectedLanguage=e===`zh`?`zh`:`en`,this.requestUpdate(),this.applyLanguage()}async applyLanguage(){await Oe(S(),this.selectedLanguage)}updateToolDisplayMode(e){this.toolDisplayMode!==e&&(this.toolDisplayMode=e,this.saved=!1,this.requestUpdate(),this.saveToolDisplayOptions())}updateShowContextUsage(e){this.showContextUsage=e,this.saved=!1,this.requestUpdate(),this.saveToolDisplayOptions()}updateAutoCompactEnabled(e){this.autoCompactEnabled=e,this.saved=!1,this.requestUpdate(),this.saveAutoCompactOptions()}updateAutoCompactRequireConfirmation(e){this.autoCompactRequireConfirmation=e,this.saved=!1,this.requestUpdate(),this.saveAutoCompactOptions()}updateAutoArchiveEnabled(e){this.autoArchiveEnabled=e,this.saved=!1,this.requestUpdate(),this.saveAutoArchiveOptions()}async updateSystemNotifications(e){this.systemNotificationBusy=!0,this.saved=!1,this.error=``,this.requestUpdate();try{if(!e){Ce(!1),this.systemNotificationsEnabled=!1,this.markSaved(M(`systemNotificationsDisabled`));return}let t=await ze();this.systemNotificationPermission=t,this.systemNotificationsEnabled=t===`granted`,t===`granted`?this.markSaved(M(`systemNotificationsEnabled`)):t===`denied`?this.error=M(`systemNotificationsDeniedHelp`):t===`unsupported`&&(this.error=M(`systemNotificationsUnsupported`))}catch(e){this.systemNotificationsEnabled=!1,Ce(!1),this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.systemNotificationBusy=!1,this.requestUpdate()}}async sendTestSystemNotification(){this.systemNotificationBusy=!0,this.error=``,this.requestUpdate();try{await Me({key:`test:${Date.now()}`,title:M(`systemNotificationTestTitle`),status:`idle`,force:!0})||(this.error=M(`systemNotificationTestFailed`))}catch(e){this.error=e instanceof Error?e.message:M(`systemNotificationTestFailed`)}finally{this.systemNotificationBusy=!1,this.requestUpdate()}}systemNotificationStatusText(){return this.systemNotificationPermission===`unsupported`?M(`systemNotificationsUnsupported`):this.systemNotificationPermission===`denied`?M(`systemNotificationsPermissionDenied`):this.systemNotificationPermission===`granted`?M(`systemNotificationsPermissionGranted`):M(`systemNotificationsPermissionPrompt`)}updateAutoCompactThresholdPercent(e){this.autoCompactThresholdPercentInput=e;let t=Number(e);e!==``&&Number.isFinite(t)&&(this.autoCompactThresholdPercent=t),this.saved=!1,this.requestUpdate()}updateAutoCompactKeepRecentTurns(e){this.autoCompactKeepRecentTurns=Number(e)||3,this.saved=!1,this.requestUpdate()}commitAutoCompactThresholdPercent(){let e=Number(this.autoCompactThresholdPercentInput);if(!Number.isFinite(e)){this.autoCompactThresholdPercentInput=String(this.autoCompactThresholdPercent),this.requestUpdate();return}let t=Math.max(50,Math.min(95,Math.round(e)));this.autoCompactThresholdPercent=t,this.autoCompactThresholdPercentInput=String(t),this.requestUpdate(),this.saveAutoCompactOptions()}commitAutoCompactKeepRecentTurns(){let e=Math.max(1,Math.min(20,Math.round(this.autoCompactKeepRecentTurns||3)));this.autoCompactKeepRecentTurns=e,this.requestUpdate(),this.saveAutoCompactOptions()}markSaved(e=M(`defaultOptionsSaved`)){this.saved=!0,this.savedMessage=e,this.error=``,this.requestUpdate()}customShellProfiles(){return this.terminalShellConfig.profiles.filter(e=>!e.builtin)}selectedTerminalShellProfileId(){let e=this.terminalShellConfig.profiles;return e.some(e=>e.id===this.terminalShellConfig.defaultProfileId)?this.terminalShellConfig.defaultProfileId:e[0]?.id||B}updateTerminalShellSelection(e){if(e===B){this.customShellEditorOpen=!0,this.requestUpdate();return}this.customShellEditorOpen=!1,this.requestUpdate(),this.saveTerminalShellConfig(e)}async loadNetworkProxy(){try{let e=await fetch(`/api/system/network-proxy`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||M(`requestFailed`));this.networkProxyMode=t?.config?.mode||`direct`,this.networkProxyUrl=t?.config?.proxyUrl||``,this.savedNetworkProxyConfig={mode:this.networkProxyMode,proxyUrl:this.networkProxyUrl},this.networkProxyStatus=t?.status||null,this.networkProxyLoaded=!0}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}}updateNetworkProxyMode(e){this.networkProxyMode===e||this.networkProxySaving||!this.networkProxyLoaded||e===`pac`&&this.networkProxyStatus?.features?.pacUrl!==!0||(this.networkProxyMode=e,this.saved=!1,this.error=``,this.requestUpdate(),!(e===`manual`||e===`pac`)&&this.saveNetworkProxy())}updateNetworkProxyUrl(e){this.networkProxyUrl=e,this.saved=!1,this.requestUpdate()}networkProxyValidationError(){let e=this.networkProxyUrl.trim(),t=this.networkProxyMode===`pac`;if(!e)return M(t?`networkProxyPacUrlRequired`:`networkProxyAddressRequired`);try{let n=new URL(e);return[`http:`,`https:`].includes(n.protocol)?n.hostname?!t&&!n.port?M(`networkProxyAddressPortError`):n.username||n.password?M(t?`networkProxyPacUrlCredentialsError`:`networkProxyAddressCredentialsError`):t&&n.hash?M(`networkProxyPacUrlFragmentError`):!t&&(n.pathname&&n.pathname!==`/`||n.search||n.hash)?M(`networkProxyAddressPathError`):``:M(t?`networkProxyPacUrlHostError`:`networkProxyAddressPortError`):M(t?`networkProxyPacUrlProtocolError`:`networkProxyAddressProtocolError`)}catch{return M(t?`networkProxyPacUrlInvalid`:`networkProxyAddressInvalid`)}}async saveNetworkProxy(){if(!(this.networkProxySaving||!this.networkProxyLoaded)){if(this.networkProxyMode===`pac`&&this.networkProxyStatus?.features?.pacUrl!==!0){this.saved=!1,this.error=M(`networkProxyPacUnsupported`),this.requestUpdate();return}if(this.networkProxyMode===`manual`||this.networkProxyMode===`pac`){let e=this.networkProxyValidationError();if(e){this.saved=!1,this.error=e,this.requestUpdate();return}}this.networkProxySaving=!0,this.saved=!1,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/system/network-proxy`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({mode:this.networkProxyMode,proxyUrl:this.networkProxyUrl})}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||M(`requestFailed`));this.networkProxyMode=t?.config?.mode||this.networkProxyMode,this.networkProxyUrl=t?.config?.proxyUrl||``,this.savedNetworkProxyConfig={mode:this.networkProxyMode,proxyUrl:this.networkProxyUrl},this.networkProxyStatus=t?.status||null,this.markSaved(M(`networkProxySaved`))}catch(e){this.networkProxyMode=this.savedNetworkProxyConfig.mode,this.networkProxyUrl=this.savedNetworkProxyConfig.proxyUrl,this.saved=!1,this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.networkProxySaving=!1,this.requestUpdate()}}}async refreshNetworkProxy(){if(!(this.networkProxySaving||!this.networkProxyLoaded)){this.networkProxySaving=!0,this.saved=!1,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/system/network-proxy/refresh`,{method:`POST`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||M(`requestFailed`));this.networkProxyStatus=t?.status||null,this.markSaved(M(`networkProxyRefreshed`))}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.networkProxySaving=!1,this.requestUpdate()}}}renderNetworkProxyModeOption(e,t){let n=this.networkProxyMode===e,r=e===`pac`&&this.networkProxyStatus?.features?.pacUrl!==!0;return b`
476
+ <button
477
+ type="button"
478
+ class="quickforge-settings-segmented-option ${n?`quickforge-settings-segmented-option-active`:``}"
479
+ aria-pressed=${n?`true`:`false`}
480
+ title=${r?M(`networkProxyPacUnsupported`):``}
481
+ ?disabled=${this.networkProxySaving||!this.networkProxyLoaded||r}
482
+ @click=${()=>this.updateNetworkProxyMode(e)}
483
+ >
484
+ ${t}
485
+ </button>
486
+ `}networkProxySettings(){let e=this.networkProxyMode===`manual`||this.networkProxyMode===`pac`,t=this.networkProxyMode===`pac`&&this.networkProxyStatus?.features?.pacUrl!==!0,n=e?this.networkProxyValidationError():``,r=e&&(this.networkProxyUrl!==this.savedNetworkProxyConfig.proxyUrl||this.savedNetworkProxyConfig.mode!==this.networkProxyMode),i=this.networkProxyLoaded?t?M(`networkProxyPacUnsupported`):this.networkProxyStatus?.supported===!1?this.networkProxyStatus.error||M(`networkProxyUnsupported`):M(`networkProxyStatus`,{source:this.networkProxyStatus?.source||M(`unknown`),runtime:this.networkProxyStatus?.runtimeKind||M(`unknown`)}):M(`networkProxyLoadFailed`);return b`
487
+ <section class="quickforge-settings-section" aria-label=${M(`networkConnection`)}>
488
+ <div class="quickforge-settings-row">
489
+ <div class="quickforge-settings-row-main">
490
+ <div class="quickforge-settings-row-title">
491
+ ${M(`networkProxyMode`)}
492
+ <quickforge-info-tip .label=${M(`networkProxyDescription`)}></quickforge-info-tip>
493
+ </div>
494
+ <div class="quickforge-settings-row-description">${i}</div>
495
+ </div>
496
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
497
+ <div class="quickforge-settings-segmented quickforge-settings-segmented-wrap" role="group" aria-label=${M(`networkProxyMode`)}>
498
+ ${this.renderNetworkProxyModeOption(`direct`,M(`networkProxyDirect`))}
499
+ ${this.renderNetworkProxyModeOption(`system`,M(`networkProxySystem`))}
500
+ ${this.renderNetworkProxyModeOption(`manual`,M(`networkProxyManual`))}
501
+ ${this.renderNetworkProxyModeOption(`pac`,M(`networkProxyPac`))}
502
+ </div>
503
+ </div>
504
+ </div>
505
+
506
+ ${e?b`
507
+ <div class="quickforge-settings-row">
508
+ <div class="quickforge-settings-row-main">
509
+ <div class="quickforge-settings-row-title">
510
+ ${M(this.networkProxyMode===`pac`?`networkProxyPacUrl`:`networkProxyAddress`)}
511
+ </div>
512
+ <div class="quickforge-settings-row-description">
513
+ ${M(this.networkProxyMode===`pac`?`networkProxyPacUrlDescription`:`networkProxyAddressDescription`)}
514
+ </div>
515
+ </div>
516
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide quickforge-network-proxy-control">
517
+ <input
518
+ id="quickforge-network-proxy-url"
519
+ class="quickforge-settings-input quickforge-settings-mono"
520
+ type="url"
521
+ aria-label=${M(this.networkProxyMode===`pac`?`networkProxyPacUrl`:`networkProxyAddress`)}
522
+ aria-invalid=${r&&n?`true`:`false`}
523
+ .value=${this.networkProxyUrl}
524
+ placeholder=${this.networkProxyMode===`pac`?`https://example.com/proxy.pac`:`http://127.0.0.1:7890`}
525
+ ?disabled=${this.networkProxySaving||!this.networkProxyLoaded||t}
526
+ @input=${e=>this.updateNetworkProxyUrl(e.target.value)}
527
+ @keydown=${e=>{e.key===`Enter`&&this.networkProxyUrl.trim()&&(e.preventDefault(),this.saveNetworkProxy())}}
528
+ />
529
+ <button
530
+ class="quickforge-settings-button quickforge-settings-button-primary"
531
+ type="button"
532
+ ?disabled=${this.networkProxySaving||!this.networkProxyLoaded||t||!!n||!r}
533
+ @click=${()=>this.saveNetworkProxy()}
534
+ >
535
+ ${this.networkProxySaving?M(`saving`):M(`networkProxySave`)}
536
+ </button>
537
+ </div>
538
+ </div>
539
+ `:null}
540
+
541
+ ${this.networkProxyMode===`system`?b`
542
+ <div class="quickforge-settings-row">
543
+ <div class="quickforge-settings-row-main">
544
+ <div class="quickforge-settings-row-title">${M(`networkProxyRefresh`)}</div>
545
+ <div class="quickforge-settings-row-description">${M(`networkProxyRefreshDescription`)}</div>
546
+ </div>
547
+ <div class="quickforge-settings-row-control">
548
+ <button
549
+ class="quickforge-settings-button"
550
+ type="button"
551
+ ?disabled=${this.networkProxySaving||!this.networkProxyLoaded}
552
+ @click=${()=>this.refreshNetworkProxy()}
553
+ >
554
+ ${this.networkProxySaving?M(`saving`):M(`networkProxyRefresh`)}
555
+ </button>
556
+ </div>
557
+ </div>
558
+ `:null}
559
+ </section>
560
+ `}async loadTerminalShell(){try{let e=await fetch(`/api/system/terminal-shell`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||M(`requestFailed`));this.terminalShellConfig={terminalShell:t?.terminalShell||`auto`,defaultProfileId:t?.defaultProfileId||`auto`,profiles:Array.isArray(t?.profiles)?t.profiles:[]}}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}}async saveTerminalShellConfig(e,t=this.customShellProfiles(),n=M(`terminalShellSaved`)){try{let r=await fetch(`/api/system/terminal-shell`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({defaultProfileId:e,profiles:t})}),i=await r.json().catch(()=>null);if(!r.ok)throw Error(i?.error||M(`requestFailed`));this.terminalShellConfig=i,this.markSaved(n)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}}async addCustomTerminalShell(){let e=this.customShellCommand.trim();if(!e){this.error=M(`terminalShellProfileRequired`),this.requestUpdate();return}let t={id:mt(),name:ht(e),command:e,builtin:!1},n=[...this.customShellProfiles(),t];this.customShellCommand=``,this.customShellEditorOpen=!1,await this.saveTerminalShellConfig(t.id,n,M(`terminalShellProfilesSaved`))}async deleteCustomTerminalShell(e){let t=this.terminalShellConfig.profiles.find(t=>t.id===e);if(!t||t.builtin||!await T({description:M(`terminalShellDeleteConfirm`,{name:t.name}),confirmLabel:M(`confirmDelete`),cancelLabel:M(`cancel`),variant:`destructive`}))return;let n=this.customShellProfiles().filter(t=>t.id!==e),r=this.terminalShellConfig.defaultProfileId===e?`auto`:this.terminalShellConfig.defaultProfileId;await this.saveTerminalShellConfig(r,n,M(`terminalShellProfilesSaved`))}async saveDefaultModelOptions(){let e=this.selectedModel,t=e?.reasoning?this.thinkingLevel:`off`,n=this.harness,r=async()=>{try{await xe(S(),{model:e,thinkingLevel:t,harness:n}),this.savedHarness!==n&&(he(n),this.savedHarness=n),this.markSaved()}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}};this.defaultOptionsSavePromise=this.defaultOptionsSavePromise.then(r,r),await this.defaultOptionsSavePromise}async saveToolDisplayOptions(){try{await fe(S(),{toolDisplayMode:this.toolDisplayMode,showContextUsage:this.showContextUsage}),this.markSaved()}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}}async saveAutoCompactOptions(){try{await nt(S(),{enabled:this.autoCompactEnabled,thresholdPercent:this.autoCompactThresholdPercent,keepRecentTurns:this.autoCompactKeepRecentTurns,minSourceChars:1600,requireConfirmation:this.autoCompactRequireConfirmation}),this.markSaved()}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}}async saveAutoArchiveOptions(){try{if(await st(S(),{enabled:this.autoArchiveEnabled}),this.markSaved(M(`autoArchiveSaved`)),typeof BroadcastChannel<`u`)try{let e=new BroadcastChannel(`quickforge-sync`);e.postMessage({type:`settings-changed`,sourceTabId:`default-options-settings-tab`,timestamp:Date.now()}),e.close()}catch{}}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}}modelOptions(){return this.models}languageOptions(){return[{value:`zh`,label:M(`simplifiedChinese`)},{value:`en`,label:M(`english`)}]}harnessOptions(){return[{value:`quickforge`,label:`QuickForge`},{value:`claude-code`,label:M(`claudeCodeHarnessUnavailable`),disabled:!0},{value:`opencode`,label:`OpenCode`}]}modelSelectOptions(){return this.modelOptions().map(e=>({value:V(e),label:ue(e)}))}thinkingOptions(){return dt.map(e=>({value:e.value,label:e.label()}))}terminalShellOptions(){return[...this.terminalShellConfig.profiles.map(e=>({value:e.id,label:e.name})),{value:B,label:M(`terminalShellCustomOption`)}]}terminalShellSettings(){let e=this.terminalShellConfig.profiles,t=this.selectedTerminalShellProfileId(),n=e.find(e=>e.id===t),r=this.customShellEditorOpen||e.length===0;return b`
561
+ <section class="quickforge-settings-section" aria-label=${M(`terminalShell`)}>
562
+ <div class="quickforge-settings-row">
563
+ <div class="quickforge-settings-row-main">
564
+ <div class="quickforge-settings-row-title">
565
+ ${M(`terminalShellDefault`)}
566
+ <quickforge-info-tip .label=${M(`terminalShellDescription`)}></quickforge-info-tip>
567
+ </div>
568
+ <div class="quickforge-settings-row-description quickforge-settings-mono">
569
+ ${n?.command||M(`terminalShellNoDetected`)}
570
+ </div>
571
+ </div>
572
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
573
+ <quickforge-settings-select
574
+ .value=${r?B:t}
575
+ .options=${this.terminalShellOptions()}
576
+ label=${M(`terminalShellDefault`)}
577
+ @change=${e=>this.updateTerminalShellSelection(e.detail)}
578
+ ></quickforge-settings-select>
579
+ ${n&&!n.builtin&&!r?b`
580
+ <button
581
+ class="quickforge-settings-icon-action quickforge-settings-icon-action-danger"
582
+ type="button"
583
+ title=${M(`delete`)}
584
+ aria-label=${M(`delete`)}
585
+ @click=${()=>this.deleteCustomTerminalShell(n.id)}
586
+ >
587
+ ${gt}
588
+ </button>
589
+ `:null}
590
+ </div>
591
+ </div>
592
+
593
+ ${r?b`
594
+ <div class="quickforge-settings-row">
595
+ <div class="quickforge-settings-row-main">
596
+ <div class="quickforge-settings-row-title">${M(`terminalShellCommand`)}</div>
597
+ <div class="quickforge-settings-row-description">${M(`terminalShellCustomDescription`)}</div>
598
+ </div>
599
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide quickforge-terminal-shell-command-control">
600
+ <input
601
+ class="quickforge-settings-input quickforge-settings-mono"
602
+ type="text"
603
+ .value=${this.customShellCommand}
604
+ placeholder=${M(`terminalShellCommandPlaceholder`)}
605
+ @input=${e=>{this.customShellCommand=e.target.value}}
606
+ />
607
+ <button
608
+ class="quickforge-settings-button quickforge-settings-button-primary"
609
+ type="button"
610
+ title=${M(`terminalShellAdd`)}
611
+ aria-label=${M(`terminalShellAdd`)}
612
+ @click=${()=>this.addCustomTerminalShell()}
613
+ >
614
+ ${M(`terminalShellAdd`)}
615
+ </button>
616
+ </div>
617
+ </div>
618
+ `:null}
619
+ </section>
620
+ `}renderToolDisplayModeOption(e){let t=this.toolDisplayMode===e.value;return b`
621
+ <button
622
+ type="button"
623
+ class="quickforge-settings-segmented-option ${t?`quickforge-settings-segmented-option-active`:``}"
624
+ aria-pressed=${t?`true`:`false`}
625
+ @click=${()=>this.updateToolDisplayMode(e.value)}
626
+ >
627
+ ${e.label()}
628
+ </button>
629
+ `}renderSwitch(e,t,n=!1){return b`
630
+ <label class="quickforge-settings-switch" aria-disabled=${n?`true`:`false`}>
631
+ <input
632
+ type="checkbox"
633
+ .checked=${e}
634
+ ?disabled=${n}
635
+ @change=${e=>t(e.target.checked)}
636
+ />
637
+ <span aria-hidden="true"></span>
638
+ </label>
639
+ `}render(){return this.loading?b`<div class="text-sm text-muted-foreground">${M(`loading`)}</div>`:b`
640
+ <div class="quickforge-settings-stack">
641
+ <section class="quickforge-settings-section" aria-label=${M(`defaultOptions`)}>
642
+ <div class="quickforge-settings-row">
643
+ <div class="quickforge-settings-row-main">
644
+ <div class="quickforge-settings-row-title">
645
+ ${M(`language`)}
646
+ <quickforge-info-tip .label=${M(`languageDescription`)}></quickforge-info-tip>
647
+ </div>
648
+ <div class="quickforge-settings-row-description">${M(`displayLanguage`)}</div>
649
+ </div>
650
+ <div class="quickforge-settings-row-control">
651
+ <quickforge-settings-select
652
+ .value=${this.selectedLanguage}
653
+ .options=${this.languageOptions()}
654
+ label=${M(`language`)}
655
+ @change=${e=>this.updateLanguage(e.detail)}
656
+ ></quickforge-settings-select>
657
+ </div>
658
+ </div>
659
+
660
+ <div class="quickforge-settings-row">
661
+ <div class="quickforge-settings-row-main">
662
+ <div class="quickforge-settings-row-title">${M(`defaultHarness`)}</div>
663
+ <div class="quickforge-settings-row-description">${M(`defaultHarnessDescription`)}</div>
664
+ </div>
665
+ <div class="quickforge-settings-row-control">
666
+ <quickforge-settings-select
667
+ .value=${this.harness}
668
+ .options=${this.harnessOptions()}
669
+ label=${M(`defaultHarness`)}
670
+ @change=${e=>this.updateHarness(e.detail)}
671
+ ></quickforge-settings-select>
672
+ </div>
673
+ </div>
674
+
675
+ <div class="quickforge-settings-row">
676
+ <div class="quickforge-settings-row-main">
677
+ <div class="quickforge-settings-row-title">${M(`defaultModel`)}</div>
678
+ <div class="quickforge-settings-row-description">${M(`defaultModelDescription`)}</div>
679
+ </div>
680
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
681
+ <quickforge-settings-select
682
+ .value=${this.selectedModel?V(this.selectedModel):``}
683
+ .options=${this.modelSelectOptions()}
684
+ .disabled=${this.models.length===0}
685
+ searchable
686
+ searchPlaceholder=${M(`search`)}
687
+ noResultsLabel=${M(`noMatchingOptions`)}
688
+ placeholder=${M(`noModelAvailable`)}
689
+ label=${M(`defaultModel`)}
690
+ @change=${e=>this.updateModel(e.detail)}
691
+ ></quickforge-settings-select>
692
+ </div>
693
+ </div>
694
+
695
+ <div class="quickforge-settings-row">
696
+ <div class="quickforge-settings-row-main">
697
+ <div class="quickforge-settings-row-title">${M(`defaultThinkingLevel`)}</div>
698
+ <div class="quickforge-settings-row-description">
699
+ ${this.selectedModel?.reasoning?M(`defaultThinkingLevelDescription`):M(`thinkingRequiresReasoningModel`)}
700
+ </div>
701
+ </div>
702
+ <div class="quickforge-settings-row-control">
703
+ <quickforge-settings-select
704
+ .value=${this.thinkingLevel}
705
+ .options=${this.thinkingOptions()}
706
+ .disabled=${!this.selectedModel?.reasoning}
707
+ label=${M(`defaultThinkingLevel`)}
708
+ @change=${e=>this.updateThinkingLevel(e.detail)}
709
+ ></quickforge-settings-select>
710
+ </div>
711
+ </div>
712
+
713
+ <div class="quickforge-settings-row">
714
+ <div class="quickforge-settings-row-main">
715
+ <div class="quickforge-settings-row-title">
716
+ ${M(`toolDisplay`)}
717
+ <quickforge-info-tip .label=${M(`toolDisplayModeDescription`)}></quickforge-info-tip>
718
+ </div>
719
+ <div class="quickforge-settings-row-description">${M(`toolDisplayModeDescription`)}</div>
720
+ </div>
721
+ <div class="quickforge-settings-row-control">
722
+ <div class="quickforge-settings-segmented" role="group" aria-label=${M(`toolDisplay`)}>
723
+ ${ft.map(e=>this.renderToolDisplayModeOption(e))}
724
+ </div>
725
+ </div>
726
+ </div>
727
+
728
+ <div class="quickforge-settings-row">
729
+ <div class="quickforge-settings-row-main">
730
+ <div class="quickforge-settings-row-title">
731
+ ${M(`systemNotifications`)}
732
+ <quickforge-info-tip .label=${M(`systemNotificationsDescription`)}></quickforge-info-tip>
733
+ </div>
734
+ <div class="quickforge-settings-row-description">${this.systemNotificationStatusText()}</div>
735
+ </div>
736
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
737
+ ${this.systemNotificationsEnabled?b`
738
+ <button
739
+ class="quickforge-settings-button quickforge-settings-button-secondary"
740
+ type="button"
741
+ ?disabled=${this.systemNotificationBusy}
742
+ @click=${()=>this.sendTestSystemNotification()}
743
+ >${M(`systemNotificationsTest`)}</button>
744
+ `:null}
745
+ ${this.renderSwitch(this.systemNotificationsEnabled,e=>{this.updateSystemNotifications(e)},this.systemNotificationBusy||this.systemNotificationPermission===`unsupported`)}
746
+ </div>
747
+ </div>
748
+
749
+ <div class="quickforge-settings-row">
750
+ <div class="quickforge-settings-row-main">
751
+ <div class="quickforge-settings-row-title">
752
+ ${M(`showContextUsage`)}
753
+ <quickforge-info-tip .label=${M(`showContextUsageDescription`)}></quickforge-info-tip>
754
+ </div>
755
+ <div class="quickforge-settings-row-description">${M(`showContextUsageDescription`)}</div>
756
+ </div>
757
+ <div class="quickforge-settings-row-control">
758
+ ${this.renderSwitch(this.showContextUsage,e=>this.updateShowContextUsage(e))}
759
+ </div>
760
+ </div>
761
+
762
+ <div class="quickforge-settings-row">
763
+ <div class="quickforge-settings-row-main">
764
+ <div class="quickforge-settings-row-title">
765
+ ${M(`autoArchiveEnabled`)}
766
+ <quickforge-info-tip .label=${M(`autoArchiveDescription`)}></quickforge-info-tip>
767
+ </div>
768
+ <div class="quickforge-settings-row-description">${M(`autoArchiveTriggerNote`)}</div>
769
+ </div>
770
+ <div class="quickforge-settings-row-control">
771
+ ${this.renderSwitch(this.autoArchiveEnabled,e=>this.updateAutoArchiveEnabled(e))}
772
+ </div>
773
+ </div>
774
+
775
+ <div class="quickforge-settings-row">
776
+ <div class="quickforge-settings-row-main">
777
+ <div class="quickforge-settings-row-title">
778
+ ${M(`autoCompactEnabled`)}
779
+ <quickforge-info-tip .label=${M(`autoCompactDescription`)}></quickforge-info-tip>
780
+ </div>
781
+ <div class="quickforge-settings-row-description">${M(`autoCompactTriggerNote`)}</div>
782
+ </div>
783
+ <div class="quickforge-settings-row-control">
784
+ ${this.renderSwitch(this.autoCompactEnabled,e=>this.updateAutoCompactEnabled(e))}
785
+ </div>
786
+ </div>
787
+
788
+ <div class="quickforge-settings-row">
789
+ <div class="quickforge-settings-row-main">
790
+ <div class="quickforge-settings-row-title">${M(`autoCompactRequireConfirmation`)}</div>
791
+ <div class="quickforge-settings-row-description">${M(`autoCompactRequireConfirmationDescription`)}</div>
792
+ </div>
793
+ <div class="quickforge-settings-row-control">
794
+ ${this.renderSwitch(this.autoCompactRequireConfirmation,e=>this.updateAutoCompactRequireConfirmation(e),!this.autoCompactEnabled)}
795
+ </div>
796
+ </div>
797
+
798
+ <div class="quickforge-settings-row">
799
+ <div class="quickforge-settings-row-main">
800
+ <div class="quickforge-settings-row-title">${M(`autoCompactThresholdPercent`)}</div>
801
+ <div class="quickforge-settings-row-description">${M(`autoCompactThresholdDescription`)}</div>
802
+ </div>
803
+ <div class="quickforge-settings-row-control">
804
+ <input
805
+ class="quickforge-settings-input quickforge-settings-number-input"
806
+ type="number"
807
+ min="50"
808
+ max="95"
809
+ step="1"
810
+ .value=${this.autoCompactThresholdPercentInput}
811
+ ?disabled=${!this.autoCompactEnabled}
812
+ @input=${e=>this.updateAutoCompactThresholdPercent(e.target.value)}
813
+ @change=${()=>this.commitAutoCompactThresholdPercent()}
814
+ @blur=${()=>this.commitAutoCompactThresholdPercent()}
815
+ />
816
+ </div>
817
+ </div>
818
+
819
+ <div class="quickforge-settings-row">
820
+ <div class="quickforge-settings-row-main">
821
+ <div class="quickforge-settings-row-title">
822
+ ${M(`autoCompactKeepRecentTurns`)}
823
+ <quickforge-info-tip .label=${M(`autoCompactHistoryPreserved`)}></quickforge-info-tip>
824
+ </div>
825
+ <div class="quickforge-settings-row-description">${M(`autoCompactKeepRecentTurnsDescription`)}</div>
826
+ </div>
827
+ <div class="quickforge-settings-row-control">
828
+ <input
829
+ class="quickforge-settings-input quickforge-settings-number-input"
830
+ type="number"
831
+ min="1"
832
+ max="20"
833
+ step="1"
834
+ .value=${String(this.autoCompactKeepRecentTurns)}
835
+ ?disabled=${!this.autoCompactEnabled}
836
+ @input=${e=>this.updateAutoCompactKeepRecentTurns(e.target.value)}
837
+ @change=${()=>this.commitAutoCompactKeepRecentTurns()}
838
+ @blur=${()=>this.commitAutoCompactKeepRecentTurns()}
839
+ />
840
+ </div>
841
+ </div>
842
+ </section>
843
+
844
+ ${this.networkProxySettings()}
845
+
846
+ ${this.terminalShellSettings()}
847
+
848
+ ${this.saved?b`<div class="quickforge-settings-message" role="status">${this.savedMessage||M(`defaultOptionsSaved`)}</div>`:null}
849
+ ${this.error?b`<div class="quickforge-settings-alert" role="alert">${this.error}</div>`:null}
850
+ </div>
851
+ `}},H=`quickforge-default-options-settings-tab`;customElements.get(H)||customElements.define(H,_t);function vt(){return document.createElement(H)}var yt=`memory-settings`,bt={enabled:!0};function xt(e){return!e||typeof e!=`object`?{...bt}:{enabled:e.enabled!==!1}}async function St(e){return xt(await e.settings.get(yt))}async function Ct(e,t){await e.settings.set(yt,xt(t))}var wt=class extends x{enabled=!0;loading=!0;saving=!1;loadingDocument=!1;markdown=``;savedMarkdown=``;memoryPath=`~/.quickforge/MEMORY.md`;message=``;error=``;getTabName(){return M(`memory`)}async connectedCallback(){super.connectedCallback(),await this.loadSettings()}async loadSettings(){this.loading=!0,this.error=``,this.requestUpdate();try{let[e]=await Promise.all([St(S()),this.loadDocument()]);this.enabled=e.enabled}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async loadDocument(e=!1){this.loadingDocument=!0,this.error=``,e&&(this.message=``),this.requestUpdate();try{let t=await fetch(`/api/memory`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(!t.ok||!n)throw Error(n?.error||M(`requestFailed`));this.markdown=n.markdown,this.savedMarkdown=n.markdown,this.memoryPath=n.path||this.memoryPath,e&&(this.message=M(`memoryReloaded`))}finally{this.loadingDocument=!1,this.requestUpdate()}}async updateEnabled(e){let t=this.enabled;this.enabled=e,this.saving=!0,this.message=``,this.error=``,this.requestUpdate();try{await Ct(S(),{enabled:e}),this.message=M(e?`memoryEnabledSaved`:`memoryDisabledSaved`)}catch(e){this.enabled=t,this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}async reloadDocument(){try{await this.loadDocument(!0)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}}async saveDocument(){if(!(!this.enabled||this.saving)){this.saving=!0,this.message=``,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/memory`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({markdown:this.markdown})}),t=await e.json().catch(()=>null);if(!e.ok||!t)throw Error(t?.error||M(`requestFailed`));this.markdown=t.markdown,this.savedMarkdown=t.markdown,this.memoryPath=t.path||this.memoryPath,this.message=M(`memoryContentSaved`)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}renderSwitch(){return b`
852
+ <label class="quickforge-settings-switch" aria-disabled=${this.saving?`true`:`false`}>
853
+ <input
854
+ type="checkbox"
855
+ .checked=${this.enabled}
856
+ ?disabled=${this.saving}
857
+ @change=${e=>void this.updateEnabled(e.target.checked)}
858
+ />
859
+ <span aria-hidden="true"></span>
860
+ </label>
861
+ `}render(){if(this.loading)return b`<div class="text-sm text-muted-foreground">${M(`loading`)}</div>`;let e=this.markdown!==this.savedMarkdown,t=this.saving||this.loadingDocument;return b`
862
+ <div class="quickforge-settings-stack">
863
+ <section class="quickforge-settings-section" aria-label=${M(`memory`)}>
864
+ <div class="quickforge-settings-row">
865
+ <div class="quickforge-settings-row-main">
866
+ <div class="quickforge-settings-row-title">
867
+ ${M(`globalMemory`)}
868
+ <quickforge-info-tip .label=${M(`globalMemoryInfo`)}></quickforge-info-tip>
869
+ </div>
870
+ <div class="quickforge-settings-row-description">${M(`globalMemoryDescription`)}</div>
871
+ </div>
872
+ <div class="quickforge-settings-row-control">${this.renderSwitch()}</div>
873
+ </div>
874
+
875
+ <div class="quickforge-settings-row">
876
+ <div class="quickforge-settings-row-main">
877
+ <div class="quickforge-settings-row-title">${M(`memoryFile`)}</div>
878
+ <div class="quickforge-settings-row-description">${M(`memoryFileDescription`)}</div>
879
+ </div>
880
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
881
+ <code class="text-xs text-muted-foreground">${this.memoryPath}</code>
882
+ </div>
883
+ </div>
884
+
885
+ <div class="quickforge-settings-row quickforge-settings-row-align-start quickforge-memory-content-row">
886
+ <div class="quickforge-settings-row-main">
887
+ <div class="quickforge-settings-row-title">${M(`memoryContent`)}</div>
888
+ <div class="quickforge-settings-row-description">${this.enabled?M(`memoryContentDescription`):M(`memoryContentDisabledDescription`)}</div>
889
+ </div>
890
+ <div class="quickforge-memory-editor-control">
891
+ <textarea
892
+ class="quickforge-settings-textarea quickforge-settings-mono quickforge-memory-editor"
893
+ .value=${this.markdown}
894
+ ?disabled=${!this.enabled||t}
895
+ spellcheck="false"
896
+ @input=${e=>{this.markdown=e.target.value,this.message=``,this.requestUpdate()}}
897
+ ></textarea>
898
+ <div class="quickforge-memory-editor-actions">
899
+ <button
900
+ class="quickforge-settings-button quickforge-settings-button-secondary"
901
+ type="button"
902
+ ?disabled=${t}
903
+ @click=${()=>void this.reloadDocument()}
904
+ >${this.loadingDocument?M(`loading`):M(`memoryReload`)}</button>
905
+ <button
906
+ class="quickforge-settings-button quickforge-settings-button-primary"
907
+ type="button"
908
+ ?disabled=${!this.enabled||t||!e}
909
+ @click=${()=>void this.saveDocument()}
910
+ >${this.saving?M(`saving`):M(`memorySave`)}</button>
911
+ </div>
912
+ </div>
913
+ </div>
914
+
915
+ <div class="quickforge-settings-note">${M(`memoryCurrentSessionNote`)}</div>
916
+ </section>
917
+
918
+ ${this.message?b`<div class="quickforge-settings-message">${this.message}</div>`:null}
919
+ ${this.error?b`<div class="quickforge-settings-alert">${this.error}</div>`:null}
920
+ </div>
921
+ `}},U=`quickforge-memory-settings-tab`;customElements.get(U)||customElements.define(U,wt);function Tt(){return document.createElement(U)}var Et=`quickforge-backup`,W=[{id:`settings`,countKey:`settings`,label:()=>M(`restoreSettings`),description:()=>M(`restoreSettingsDescription`)},{id:`mcp`,countKey:`mcp`,label:()=>M(`restoreMcp`),description:()=>M(`restoreMcpDescription`)},{id:`providerKeys`,countKey:`providerKeys`,label:()=>M(`restoreProviderKeys`),description:()=>M(`restoreProviderKeysDescription`)},{id:`customProviders`,countKey:`customProviders`,label:()=>M(`restoreCustomProviders`),description:()=>M(`restoreCustomProvidersDescription`)},{id:`scheduledTasks`,countKey:`scheduledTasks`,label:()=>M(`restoreScheduledTasks`),description:()=>M(`restoreScheduledTasksDescription`)}],Dt=W;function Ot(e,t){let n=new Blob([`${JSON.stringify(t,null,2)}\n`],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=e,document.body.appendChild(i),i.click(),i.remove(),URL.revokeObjectURL(r)}function kt(){return new Date().toISOString().replace(/[:.]/g,`-`)}function At(e){return e?Object.entries(e).map(([e,t])=>`${e}: ${t}`).join(`, `):``}function jt(e){return Dt.filter(t=>(e.sections?.[t.countKey]??0)>0)}function Mt(e){return jt(e).map(e=>e.id)}function Nt(e){return e instanceof RangeError||e instanceof Error&&e.message.includes(`Invalid string length`)}function G(e,t){return Nt(e)?M(`backupStringTooLarge`):e instanceof Error?e.message:t}var Pt=class extends x{exportSections=new Set(W.map(e=>e.id));busy=!1;message=``;error=``;safetyBackupPath=``;pendingImport=null;getTabName(){return M(`backupRestore`)}toggleExportSection(e,t){t?this.exportSections.add(e):this.exportSections.delete(e),this.clearStatus(),this.requestUpdate()}clearStatus(){this.message=``,this.error=``,this.safetyBackupPath=``}async exportBackup(){if(this.exportSections.size===0){this.error=M(`selectAtLeastOneExportSection`),this.requestUpdate();return}this.busy=!0,this.clearStatus(),this.requestUpdate();try{let e=new URLSearchParams({sections:[...this.exportSections].join(`,`)}),t=await fetch(`/api/backup/export?${e.toString()}`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||M(`backupExportFailed`));Ot(`${Et}-settings-${kt()}.json`,n),this.message=M(`backupExported`)}catch(e){this.error=G(e,M(`backupExportFailed`))}finally{this.busy=!1,this.requestUpdate()}}async inspectBackupFile(e){let t=await fetch(`/api/backup/inspect-file`,{method:`POST`,headers:{"content-type":`application/json`},body:e}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||M(`backupInspectFailed`));if(!n)throw Error(M(`backupInspectFailed`));return n}async importBackupFromFile(e){this.busy=!0,this.clearStatus(),this.pendingImport=null,this.requestUpdate();try{let t=await this.inspectBackupFile(e),n=new Set(Mt(t));this.pendingImport={backup:null,importToken:t.importToken,inspect:t,selectedSections:n,mode:`replace`},this.message=t.ignoredConversations?M(`backupInspectedWithIgnoredConversations`):M(`backupInspected`)}catch(e){this.error=G(e,M(`backupImportFailed`))}finally{this.busy=!1,this.requestUpdate()}}togglePendingSection(e,t){this.pendingImport&&(t?this.pendingImport.selectedSections.add(e):this.pendingImport.selectedSections.delete(e),this.message=``,this.error=``,this.requestUpdate())}setRestoreMode(e){this.pendingImport&&(this.pendingImport.mode=e,this.message=``,this.error=``,this.requestUpdate())}cancelPendingImport(){this.pendingImport=null,this.message=``,this.error=``,this.requestUpdate()}async confirmPendingImport(){if(this.pendingImport){if(this.pendingImport.selectedSections.size===0){this.error=M(`selectAtLeastOneRestoreSection`),this.requestUpdate();return}if(await T({description:this.pendingImport.mode===`replace`?M(`backupImportReplaceConfirm`):M(`backupImportMergeConfirm`),confirmLabel:M(`confirmImportSelected`),cancelLabel:M(`cancel`)})){this.busy=!0,this.clearStatus(),this.requestUpdate();try{let e=this.pendingImport.importToken?{importToken:this.pendingImport.importToken,sections:[...this.pendingImport.selectedSections],mode:this.pendingImport.mode}:{backup:this.pendingImport.backup,sections:[...this.pendingImport.selectedSections],mode:this.pendingImport.mode},t=await fetch(`/api/backup/import`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e)}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||M(`backupImportFailed`));let r=At(n?.summary);this.safetyBackupPath=n?.safetyBackupPath||``,this.pendingImport=null,this.message=r?`${M(`backupImported`)} ${r}`:M(`backupImported`),window.setTimeout(()=>window.location.reload(),1500)}catch(e){this.error=G(e,M(`backupImportFailed`))}finally{this.busy=!1,this.requestUpdate()}}}}handleFileChange(e){let t=e.target,n=t.files?.[0];t.value=``,n&&this.importBackupFromFile(n)}renderSwitch(e,t,n=!1){return b`
922
+ <label class="quickforge-settings-switch" aria-disabled=${n?`true`:`false`}>
923
+ <input
924
+ type="checkbox"
925
+ .checked=${e}
926
+ ?disabled=${n}
927
+ @change=${e=>t(e.target.checked)}
928
+ />
929
+ <span aria-hidden="true"></span>
930
+ </label>
931
+ `}renderPendingImport(){if(!this.pendingImport)return null;let{inspect:e,selectedSections:t}=this.pendingImport,n=jt(e);return b`
932
+ <section class="quickforge-settings-section" aria-label=${M(`backupInspectTitle`)}>
933
+ <div class="quickforge-settings-row quickforge-settings-row-top">
934
+ <div class="quickforge-settings-row-main">
935
+ <div class="quickforge-settings-row-title">${M(`backupInspectTitle`)}</div>
936
+ <div class="quickforge-settings-row-description">${M(`backupInspectDescription`)}</div>
937
+ </div>
938
+ </div>
939
+
940
+ <div class="quickforge-settings-nested-list">
941
+ <div class="quickforge-settings-subrow">
942
+ <div class="quickforge-settings-row-main">
943
+ <div class="quickforge-settings-row-title">${M(`backupInspectExportedAt`)}</div>
944
+ </div>
945
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${e.exportedAt||`-`}</div>
946
+ </div>
947
+ <div class="quickforge-settings-subrow">
948
+ <div class="quickforge-settings-row-main">
949
+ <div class="quickforge-settings-row-title">${M(`backupInspectVersion`)}</div>
950
+ </div>
951
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${e.version??`-`}</div>
952
+ </div>
953
+ <div class="quickforge-settings-subrow">
954
+ <div class="quickforge-settings-row-main">
955
+ <div class="quickforge-settings-row-title">${M(`backupInspectScope`)}</div>
956
+ </div>
957
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${e.scope||`-`}</div>
958
+ </div>
959
+ <div class="quickforge-settings-subrow">
960
+ <div class="quickforge-settings-row-main">
961
+ <div class="quickforge-settings-row-title">${M(`backupInspectSecrets`)}</div>
962
+ </div>
963
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${e.includeSecrets?M(`yes`):M(`no`)}</div>
964
+ </div>
965
+ </div>
966
+
967
+ ${e.warnings?.length?b`
968
+ <div class="quickforge-settings-warning quickforge-settings-warning-attached">
969
+ ${e.warnings.map(e=>b`<div>⚠ ${e}</div>`)}
970
+ </div>
971
+ `:null}
972
+
973
+ ${e.invalidSections&&Object.keys(e.invalidSections).length?b`
974
+ <div class="quickforge-settings-warning quickforge-settings-warning-attached">
975
+ <div>${M(`backupInvalidSections`)}</div>
976
+ ${Object.entries(e.invalidSections).map(([e,t])=>b`<div>${e}: ${t}</div>`)}
977
+ </div>
978
+ `:null}
979
+
980
+ <div class="quickforge-settings-row">
981
+ <div class="quickforge-settings-row-main">
982
+ <div class="quickforge-settings-row-title">${M(`restoreMode`)}</div>
983
+ <div class="quickforge-settings-row-description">${M(`restoreModeDescription`)}</div>
984
+ </div>
985
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
986
+ <div class="quickforge-settings-segmented" role="group" aria-label=${M(`restoreMode`)}>
987
+ <button
988
+ type="button"
989
+ class="quickforge-settings-segmented-option ${this.pendingImport.mode===`replace`?`quickforge-settings-segmented-option-active`:``}"
990
+ ?disabled=${this.busy}
991
+ @click=${()=>this.setRestoreMode(`replace`)}
992
+ >
993
+ ${M(`restoreModeReplace`)}
994
+ </button>
995
+ <button
996
+ type="button"
997
+ class="quickforge-settings-segmented-option ${this.pendingImport.mode===`merge`?`quickforge-settings-segmented-option-active`:``}"
998
+ ?disabled=${this.busy}
999
+ @click=${()=>this.setRestoreMode(`merge`)}
1000
+ >
1001
+ ${M(`restoreModeMerge`)}
1002
+ </button>
1003
+ </div>
1004
+ </div>
1005
+ </div>
1006
+
1007
+ <div class="quickforge-settings-row quickforge-settings-row-top">
1008
+ <div class="quickforge-settings-row-main">
1009
+ <div class="quickforge-settings-row-title">${M(`selectRestoreSections`)}</div>
1010
+ <div class="quickforge-settings-row-description">
1011
+ ${this.pendingImport.mode===`replace`?M(`restoreModeReplaceDescription`):M(`restoreModeMergeDescription`)}
1012
+ </div>
1013
+ </div>
1014
+ </div>
1015
+ <div class="quickforge-settings-nested-list">
1016
+ ${n.map(n=>b`
1017
+ <div class="quickforge-settings-subrow">
1018
+ <div class="quickforge-settings-row-main">
1019
+ <div class="quickforge-settings-row-title">${n.label()} (${e.sections?.[n.countKey]??0})</div>
1020
+ <div class="quickforge-settings-row-description">${n.description()}</div>
1021
+ </div>
1022
+ <div class="quickforge-settings-row-control">
1023
+ ${this.renderSwitch(t.has(n.id),e=>this.togglePendingSection(n.id,e),this.busy)}
1024
+ </div>
1025
+ </div>
1026
+ `)}
1027
+ </div>
1028
+
1029
+ <div class="quickforge-settings-row">
1030
+ <div class="quickforge-settings-row-main">
1031
+ <div class="quickforge-settings-row-title">${M(`backupImportActions`)}</div>
1032
+ <div class="quickforge-settings-row-description">${M(`backupImportActionsDescription`)}</div>
1033
+ </div>
1034
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1035
+ <button
1036
+ class="quickforge-settings-button quickforge-settings-button-primary"
1037
+ type="button"
1038
+ ?disabled=${this.busy||t.size===0}
1039
+ @click=${()=>this.confirmPendingImport()}
1040
+ >
1041
+ ${this.busy?M(`loading`):M(`confirmImportSelected`)}
1042
+ </button>
1043
+ <button
1044
+ class="quickforge-settings-button quickforge-settings-button-secondary"
1045
+ type="button"
1046
+ ?disabled=${this.busy}
1047
+ @click=${()=>this.cancelPendingImport()}
1048
+ >
1049
+ ${M(`cancel`)}
1050
+ </button>
1051
+ </div>
1052
+ </div>
1053
+ </section>
1054
+ `}render(){return b`
1055
+ <div class="quickforge-settings-stack">
1056
+ <section class="quickforge-settings-section" aria-label=${M(`exportData`)}>
1057
+ <div class="quickforge-settings-row quickforge-settings-row-top">
1058
+ <div class="quickforge-settings-row-main">
1059
+ <div class="quickforge-settings-row-title">
1060
+ ${M(`selectExportSections`)}
1061
+ <quickforge-info-tip .label=${M(`exportDataDescription`)}></quickforge-info-tip>
1062
+ </div>
1063
+ <div class="quickforge-settings-row-description">${M(`selectExportSectionsDescription`)}</div>
1064
+ </div>
1065
+ </div>
1066
+
1067
+ <div class="quickforge-settings-nested-list">
1068
+ ${W.map(e=>b`
1069
+ <div class="quickforge-settings-subrow">
1070
+ <div class="quickforge-settings-row-main">
1071
+ <div class="quickforge-settings-row-title">${e.label()}</div>
1072
+ <div class="quickforge-settings-row-description">${e.description()}</div>
1073
+ </div>
1074
+ <div class="quickforge-settings-row-control">
1075
+ ${this.renderSwitch(this.exportSections.has(e.id),t=>this.toggleExportSection(e.id,t),this.busy)}
1076
+ </div>
1077
+ </div>
1078
+ `)}
1079
+ </div>
1080
+
1081
+ <div class="quickforge-settings-note">${M(`conversationBackupExcluded`)}</div>
1082
+
1083
+ <div class="quickforge-settings-row">
1084
+ <div class="quickforge-settings-row-main">
1085
+ <div class="quickforge-settings-row-title">${M(`exportBackup`)}</div>
1086
+ <div class="quickforge-settings-row-description">${M(`exportBackupDescription`)}</div>
1087
+ </div>
1088
+ <div class="quickforge-settings-row-control">
1089
+ <button
1090
+ class="quickforge-settings-button quickforge-settings-button-primary"
1091
+ type="button"
1092
+ ?disabled=${this.busy||this.exportSections.size===0}
1093
+ @click=${()=>this.exportBackup()}
1094
+ >
1095
+ ${this.busy?M(`loading`):M(`exportBackup`)}
1096
+ </button>
1097
+ </div>
1098
+ </div>
1099
+ </section>
1100
+
1101
+ <section class="quickforge-settings-section" aria-label=${M(`importData`)}>
1102
+ <div class="quickforge-settings-row">
1103
+ <div class="quickforge-settings-row-main">
1104
+ <div class="quickforge-settings-row-title">
1105
+ ${M(`importBackup`)}
1106
+ <quickforge-info-tip .label=${M(`importDataDescription`)}></quickforge-info-tip>
1107
+ </div>
1108
+ <div class="quickforge-settings-row-description">${M(`importDataDescription`)}</div>
1109
+ </div>
1110
+ <div class="quickforge-settings-row-control">
1111
+ <label class="quickforge-settings-button quickforge-settings-button-secondary ${this.busy?`pointer-events-none opacity-60`:``}">
1112
+ <input
1113
+ class="hidden"
1114
+ type="file"
1115
+ accept="application/json,.json"
1116
+ ?disabled=${this.busy}
1117
+ @change=${e=>this.handleFileChange(e)}
1118
+ />
1119
+ ${M(`importBackup`)}
1120
+ </label>
1121
+ </div>
1122
+ </div>
1123
+ </section>
1124
+
1125
+ ${this.renderPendingImport()}
1126
+ ${this.message?b`<div class="quickforge-settings-message">${this.message}</div>`:null}
1127
+ ${this.safetyBackupPath?b`<div class="quickforge-settings-note">${M(`backupSafetyBackupPath`)}: <code>${this.safetyBackupPath}</code></div>`:null}
1128
+ ${this.error?b`<div class="quickforge-settings-alert">${this.error}</div>`:null}
1129
+ </div>
1130
+ `}},K=`quickforge-backup-settings-tab`;customElements.get(K)||customElements.define(K,Pt);function Ft(){return document.createElement(K)}function It(e){if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString(A())}function Lt(e){let t={...e};return delete t.archivedAt,t}function q(){if(!(typeof BroadcastChannel>`u`))try{let e=new BroadcastChannel(`quickforge-sync`);e.postMessage({type:`sessions-changed`,sourceTabId:`archived-conversations-settings-tab`,timestamp:Date.now()}),e.close()}catch{}}var Rt=class extends x{sessions=[];projects=[];loading=!0;busySessionId=``;query=``;projectFilter=`all`;message=``;error=``;getTabName(){return M(`archivedConversations`)}async connectedCallback(){super.connectedCallback(),await this.loadData()}get projectNameById(){return new Map(this.projects.map(e=>[e.id,e.name]))}async loadData(){this.loading=!0,this.error=``,this.requestUpdate();try{let[e,t]=await Promise.all([fetch(`/api/storage/sessions-metadata/index/lastModified?direction=desc&limit=1000&offset=0&archived=only`,{cache:`no-store`}),fetch(`/api/project`,{cache:`no-store`}).catch(()=>null)]),n=await e.json().catch(()=>null);if(!e.ok)throw Error(n?.error||M(`requestFailed`));if(this.sessions=Array.isArray(n?.values)?n.values:[],t?.ok){let e=await t.json().catch(()=>null);this.projects=Array.isArray(e?.projects)?e.projects:[]}}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}filteredSessions(){let e=this.query.trim().toLowerCase();return this.sessions.filter(t=>{if(this.projectFilter!==`all`&&(this.projectFilter===`global`&&t.scope===`project`||this.projectFilter!==`global`&&t.projectId!==this.projectFilter))return!1;if(!e)return!0;let n=t.projectId&&this.projectNameById.get(t.projectId)||``;return`${Ie(t.title,t.channelName)} ${n}`.toLowerCase().includes(e)})}groupedSessions(){let e=new Map;for(let t of this.filteredSessions()){let n=t.scope===`project`&&t.projectId?t.projectId:`global`;e.set(n,[...e.get(n)??[],t])}return[...e.entries()]}projectLabel(e){return e===`global`?M(`normalChat`):this.projectNameById.get(e)||M(`unknownProject`)}async restoreSession(e){if(!this.busySessionId){this.busySessionId=e,this.message=``,this.error=``,this.requestUpdate();try{let t=S(),n=await t.sessions.get(e),r=await t.sessions.getMetadata(e);if(!n||!r)throw Error(M(`sessionNotFound`));await t.sessions.save(Lt(n),Lt(r)),this.sessions=this.sessions.filter(t=>t.id!==e),this.message=M(`sessionRestored`),q()}catch(e){this.error=e instanceof Error?e.message:M(`restoreSessionFailed`)}finally{this.busySessionId=``,this.requestUpdate()}}}async deleteSession(e){if(!this.busySessionId&&await T({description:M(`deleteArchivedSessionConfirm`,{title:Ie(e.title)}),confirmLabel:M(`confirmDelete`),cancelLabel:M(`cancel`),variant:`destructive`})){this.busySessionId=e.id,this.message=``,this.error=``,this.requestUpdate();try{await S().sessions.delete(e.id),this.sessions=this.sessions.filter(t=>t.id!==e.id),this.message=M(`archivedSessionDeleted`),q()}catch(e){this.error=e instanceof Error?e.message:M(`deleteSessionFailed`)}finally{this.busySessionId=``,this.requestUpdate()}}}async deleteAllArchivedSessions(){if(!(this.busySessionId||this.sessions.length===0)&&await T({description:M(`deleteAllArchivedSessionsConfirm`),confirmLabel:M(`confirmDelete`),cancelLabel:M(`cancel`),variant:`destructive`})){this.busySessionId=`__all__`,this.message=``,this.error=``,this.requestUpdate();try{let e=S();await Promise.all(this.sessions.map(t=>e.sessions.delete(t.id))),this.sessions=[],this.message=M(`archivedSessionsDeleted`),q()}catch(e){this.error=e instanceof Error?e.message:M(`deleteSessionFailed`)}finally{this.busySessionId=``,this.requestUpdate()}}}renderSession(e){let t=this.busySessionId===e.id||this.busySessionId===`__all__`;return b`
1131
+ <div class="border-t border-border px-4 py-3 first:border-t-0">
1132
+ <div class="flex flex-wrap items-start justify-between gap-x-3 gap-y-2">
1133
+ <div class="min-w-0 flex-1">
1134
+ <div class="truncate text-sm font-medium text-foreground">${Ie(e.title,e.channelName)}</div>
1135
+ <div class="mt-1 text-xs text-muted-foreground">
1136
+ ${M(`lastModified`)}: ${It(e.lastModified)} · ${M(`archivedAt`)}: ${It(e.archivedAt)}
1137
+ </div>
1138
+ </div>
1139
+ <div class="flex w-full shrink-0 items-center justify-end gap-2 sm:w-auto">
1140
+ <button
1141
+ class="rounded-md border border-input px-2.5 py-1 text-xs hover:bg-muted/60 disabled:opacity-60"
1142
+ type="button"
1143
+ ?disabled=${t}
1144
+ @click=${()=>this.restoreSession(e.id)}
1145
+ >
1146
+ ${M(`restoreSession`)}
1147
+ </button>
1148
+ <button
1149
+ class="rounded-md px-2.5 py-1 text-xs text-destructive hover:bg-destructive/10 disabled:opacity-60"
1150
+ type="button"
1151
+ ?disabled=${t}
1152
+ @click=${()=>this.deleteSession(e)}
1153
+ >
1154
+ ${M(`deletePermanently`)}
1155
+ </button>
1156
+ </div>
1157
+ </div>
1158
+ </div>
1159
+ `}render(){let e=this.groupedSessions();return b`
1160
+ <div class="flex flex-col gap-4">
1161
+ <div class="flex justify-end">
1162
+ <button
1163
+ class="rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive hover:bg-destructive/15 disabled:opacity-60"
1164
+ type="button"
1165
+ ?disabled=${!!this.busySessionId||this.sessions.length===0}
1166
+ @click=${()=>this.deleteAllArchivedSessions()}
1167
+ >
1168
+ ${M(`deleteAll`)}
1169
+ </button>
1170
+ </div>
1171
+
1172
+ <section class="rounded-lg border border-border">
1173
+ <div class="grid gap-2 border-b border-border p-3 sm:grid-cols-[minmax(0,1fr)_12rem]">
1174
+ <input
1175
+ class="rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-ring/30"
1176
+ type="search"
1177
+ .value=${this.query}
1178
+ placeholder=${M(`searchArchivedConversations`)}
1179
+ @input=${e=>{this.query=e.target.value,this.requestUpdate()}}
1180
+ />
1181
+ <select
1182
+ class="rounded-md border border-input bg-background px-3 py-2 text-sm"
1183
+ .value=${this.projectFilter}
1184
+ @change=${e=>{this.projectFilter=e.target.value,this.requestUpdate()}}
1185
+ >
1186
+ <option value="all">${M(`allProjects`)}</option>
1187
+ <option value="global">${M(`normalChat`)}</option>
1188
+ ${this.projects.map(e=>b`<option value=${e.id}>${e.name}</option>`)}
1189
+ </select>
1190
+ </div>
1191
+
1192
+ ${this.loading?b`
1193
+ <div class="px-4 py-8 text-center text-sm text-muted-foreground">${M(`loading`)}</div>
1194
+ `:e.length===0?b`
1195
+ <div class="px-4 py-8 text-center text-sm text-muted-foreground">${M(`noArchivedConversations`)}</div>
1196
+ `:b`
1197
+ <div>
1198
+ ${e.map(([e,t])=>b`
1199
+ <div class="border-b border-border last:border-b-0">
1200
+ <div class="flex items-center justify-between gap-3 bg-muted/20 px-4 py-2 text-sm text-muted-foreground">
1201
+ <div class="truncate">${this.projectLabel(e)}</div>
1202
+ <div class="shrink-0">${M(`conversationCount`,{count:t.length})}</div>
1203
+ </div>
1204
+ ${t.map(e=>this.renderSession(e))}
1205
+ </div>
1206
+ `)}
1207
+ </div>
1208
+ `}
1209
+ </section>
1210
+
1211
+ ${this.message?b`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
1212
+ ${this.error?b`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
1213
+ </div>
1214
+ `}},zt=`quickforge-archived-conversations-settings-tab`;customElements.get(zt)||customElements.define(zt,Rt);function Bt(){return document.createElement(zt)}function Vt(){return Array.from({length:16},()=>`ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%^&*`[Math.floor(Math.random()*65)]).join(``)}function Ht(e){if(!e)return M(`lanAccessUnknownDevice`);let t=e.includes(`Edg/`)?`Edge`:e.includes(`Firefox/`)?`Firefox`:e.includes(`Chrome/`)?`Chrome`:e.includes(`Safari/`)?`Safari`:M(`lanAccessBrowser`),n=/Android/i.test(e)?`Android`:/iPhone|iPad|iPod/i.test(e)?`iOS`:/Windows/i.test(e)?`Windows`:/Macintosh|Mac OS X/i.test(e)?`macOS`:/Linux/i.test(e)?`Linux`:``;return n?`${t} · ${n}`:t}function Ut(e){if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?`-`:new Intl.DateTimeFormat(A(),{dateStyle:`medium`,timeStyle:`short`}).format(t)}var Wt=class extends x{loading=!0;saving=!1;enabled=!1;hasPassword=!1;password=``;passwordVisible=!1;sessionTtlHours=12;activeTokenCount=0;activeDevices=[];lanUrls=[];error=``;message=``;getTabName(){return M(`lanAccess`)}async connectedCallback(){super.connectedCallback(),await this.loadStatus()}async request(e,t){let n=await fetch(e,{...t,cache:`no-store`,headers:{...t?.body?{"content-type":`application/json`}:void 0,...t?.headers}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||M(`requestFailed`));return r}applyStatus(e){this.enabled=!!e.enabled,this.hasPassword=!!e.hasPassword,this.sessionTtlHours=Number(e.sessionTtlHours||12),this.activeTokenCount=Number(e.activeTokenCount||0),this.activeDevices=Array.isArray(e.activeDevices)?e.activeDevices:[],this.lanUrls=Array.isArray(e.lanUrls)?e.lanUrls:[]}async loadStatus(){this.loading=!0,this.error=``,this.requestUpdate();try{this.applyStatus(await this.request(`/api/lan-access/status`))}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}updatePassword(e){this.password=e,this.requestUpdate()}togglePasswordVisibility(){this.passwordVisible=!this.passwordVisible,this.requestUpdate()}updateEnabled(e){this.enabled=e,this.requestUpdate()}updateTtl(e){this.sessionTtlHours=Number(e)||12,this.requestUpdate()}async saveSettings(){if(!this.saving){if(this.enabled&&!this.hasPassword&&!this.password.trim()){this.error=M(`lanAccessPasswordRequired`),this.requestUpdate();return}if(this.password.trim()&&this.password.trim().length<8){this.error=M(`lanAccessPasswordTooShort`),this.requestUpdate();return}if(!(this.enabled&&!await T({description:M(`lanAccessEnableConfirm`),confirmLabel:M(`enabled`),cancelLabel:M(`cancel`)}))){this.saving=!0,this.error=``,this.message=``,this.requestUpdate();try{let e=await this.request(`/api/lan-access/settings`,{method:`PUT`,body:JSON.stringify({enabled:this.enabled,password:this.password.trim()||void 0,sessionTtlHours:this.sessionTtlHours})});this.applyStatus(e),this.password=``,this.passwordVisible=!1,this.message=M(`lanAccessSaved`)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}}async revokeDevice(e){if(await T({description:M(`lanAccessRevokeDeviceConfirm`,{device:Ht(e.userAgent)}),confirmLabel:M(`lanAccessRevokeDevice`),cancelLabel:M(`cancel`),variant:`destructive`})){this.saving=!0,this.error=``,this.message=``,this.requestUpdate();try{let t=await this.request(`/api/lan-access/revoke`,{method:`POST`,body:JSON.stringify({id:e.id})});this.applyStatus(t),this.message=M(`lanAccessDeviceRevoked`)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}async revokeAll(){if(await T({description:M(`lanAccessRevokeAllConfirm`),confirmLabel:M(`lanAccessRevokeAll`),cancelLabel:M(`cancel`),variant:`destructive`})){this.saving=!0,this.error=``,this.message=``,this.requestUpdate();try{let e=await this.request(`/api/lan-access/revoke-all`,{method:`POST`});this.applyStatus(e),this.message=M(`lanAccessRevoked`)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}renderSwitch(e,t,n=!1){return b`
1215
+ <label class="quickforge-settings-switch" aria-disabled=${n?`true`:`false`}>
1216
+ <input
1217
+ type="checkbox"
1218
+ .checked=${e}
1219
+ ?disabled=${n}
1220
+ @change=${e=>t(e.target.checked)}
1221
+ />
1222
+ <span aria-hidden="true"></span>
1223
+ </label>
1224
+ `}render(){return this.loading?b`<div class="text-sm text-muted-foreground">${M(`loading`)}</div>`:b`
1225
+ <div class="quickforge-settings-stack">
1226
+ <div class="quickforge-settings-warning">${M(`lanAccessRiskWarning`)}</div>
1227
+
1228
+ <section class="quickforge-settings-section" aria-label=${M(`lanAccessStatus`)}>
1229
+ <div class="quickforge-settings-row">
1230
+ <div class="quickforge-settings-row-main">
1231
+ <div class="quickforge-settings-row-title">${M(`lanAccessEnabled`)}</div>
1232
+ <div class="quickforge-settings-row-description">${M(`lanAccessEnabledDescription`)}</div>
1233
+ </div>
1234
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${this.enabled?M(`enabled`):M(`disabled`)}</div>
1235
+ </div>
1236
+ <div class="quickforge-settings-row">
1237
+ <div class="quickforge-settings-row-main">
1238
+ <div class="quickforge-settings-row-title">${M(`lanAccessPassword`)}</div>
1239
+ <div class="quickforge-settings-row-description">${M(`lanAccessPasswordStatusDescription`)}</div>
1240
+ </div>
1241
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${this.hasPassword?M(`configured`):M(`notConfigured`)}</div>
1242
+ </div>
1243
+ <div class="quickforge-settings-row quickforge-settings-row-top">
1244
+ <div class="quickforge-settings-row-main">
1245
+ <div class="quickforge-settings-row-title">${M(`lanAccessActiveDevices`,{count:this.activeTokenCount})}</div>
1246
+ <div class="quickforge-settings-row-description">${M(`lanAccessActiveDevicesDescription`)}</div>
1247
+ </div>
1248
+ </div>
1249
+ <div class="quickforge-settings-nested-list quickforge-lan-device-list">
1250
+ ${this.activeDevices.length?this.activeDevices.map(e=>b`
1251
+ <div class="quickforge-settings-subrow">
1252
+ <div class="quickforge-settings-list-item-main">
1253
+ <div class="quickforge-settings-row-title">${Ht(e.userAgent)}</div>
1254
+ <div class="quickforge-settings-row-description quickforge-lan-device-meta">
1255
+ <span>${e.address||M(`lanAccessUnknownAddress`)}</span>
1256
+ <span>${M(`lanAccessSignedInAt`,{time:Ut(e.issuedAt)})}</span>
1257
+ <span>${M(`lanAccessExpiresAt`,{time:Ut(e.expiresAt)})}</span>
1258
+ </div>
1259
+ </div>
1260
+ <div class="quickforge-settings-list-item-actions">
1261
+ <button
1262
+ class="quickforge-settings-button quickforge-settings-button-danger quickforge-settings-button-compact"
1263
+ type="button"
1264
+ ?disabled=${this.saving}
1265
+ @click=${()=>this.revokeDevice(e)}
1266
+ >
1267
+ ${M(`lanAccessRevokeDevice`)}
1268
+ </button>
1269
+ </div>
1270
+ </div>
1271
+ `):b`<div class="quickforge-settings-empty-row">${M(`lanAccessNoActiveDevices`)}</div>`}
1272
+ </div>
1273
+ <div class="quickforge-settings-row">
1274
+ <div class="quickforge-settings-row-main">
1275
+ <div class="quickforge-settings-row-title">${M(`lanAccessUrls`)}</div>
1276
+ <div class="quickforge-settings-row-description">${M(`lanAccessUrlsDescription`)}</div>
1277
+ </div>
1278
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide quickforge-settings-readonly-value">
1279
+ ${this.lanUrls.length?this.lanUrls.map(e=>b`<div>${e}</div>`):`-`}
1280
+ </div>
1281
+ </div>
1282
+ </section>
1283
+
1284
+ <section class="quickforge-settings-section" aria-label=${M(`lanAccess`)}>
1285
+ <div class="quickforge-settings-row">
1286
+ <div class="quickforge-settings-row-main">
1287
+ <div class="quickforge-settings-row-title">${M(`lanAccessAllowFull`)}</div>
1288
+ <div class="quickforge-settings-row-description">${M(`lanAccessAllowFullDescription`)}</div>
1289
+ </div>
1290
+ <div class="quickforge-settings-row-control">
1291
+ ${this.renderSwitch(this.enabled,e=>this.updateEnabled(e),this.saving)}
1292
+ </div>
1293
+ </div>
1294
+
1295
+ <div class="quickforge-settings-row">
1296
+ <div class="quickforge-settings-row-main">
1297
+ <div class="quickforge-settings-row-title">${M(`lanAccessPassword`)}</div>
1298
+ <div class="quickforge-settings-row-description">${this.hasPassword?M(`lanAccessPasswordPlaceholderConfigured`):M(`lanAccessPasswordPlaceholder`)}</div>
1299
+ </div>
1300
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide quickforge-lan-password-control">
1301
+ <div class="quickforge-lan-password-input-wrap">
1302
+ <input
1303
+ class="quickforge-settings-input"
1304
+ type=${this.passwordVisible?`text`:`password`}
1305
+ .value=${this.password}
1306
+ @input=${e=>this.updatePassword(e.target.value)}
1307
+ placeholder=${this.hasPassword?M(`lanAccessPasswordPlaceholderConfigured`):M(`lanAccessPasswordPlaceholder`)}
1308
+ />
1309
+ <button
1310
+ class="quickforge-lan-password-toggle"
1311
+ type="button"
1312
+ aria-label=${this.passwordVisible?M(`hidePassword`):M(`showPassword`)}
1313
+ title=${this.passwordVisible?M(`hidePassword`):M(`showPassword`)}
1314
+ aria-pressed=${this.passwordVisible?`true`:`false`}
1315
+ @click=${()=>this.togglePasswordVisibility()}
1316
+ >
1317
+ ${this.passwordVisible?b`
1318
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true">
1319
+ <path d="m3 3 18 18" stroke-linecap="round"></path>
1320
+ <path d="M10.6 10.7a2 2 0 0 0 2.7 2.7"></path>
1321
+ <path d="M9.9 4.3A10.9 10.9 0 0 1 12 4c5.5 0 9 5.3 9 8a7.3 7.3 0 0 1-1.5 3.2"></path>
1322
+ <path d="M6.6 6.6C4.3 8.1 3 10.4 3 12c0 2.7 3.5 8 9 8 1.5 0 2.8-.4 4-1"></path>
1323
+ </svg>
1324
+ `:b`
1325
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true">
1326
+ <path d="M3 12c0-2.7 3.5-8 9-8s9 5.3 9 8-3.5 8-9 8-9-5.3-9-8Z"></path>
1327
+ <circle cx="12" cy="12" r="2.5"></circle>
1328
+ </svg>
1329
+ `}
1330
+ </button>
1331
+ </div>
1332
+ <button
1333
+ class="quickforge-settings-button quickforge-settings-button-secondary"
1334
+ type="button"
1335
+ @click=${()=>this.updatePassword(Vt())}
1336
+ >
1337
+ ${M(`generatePassword`)}
1338
+ </button>
1339
+ </div>
1340
+ </div>
1341
+
1342
+ <div class="quickforge-settings-row">
1343
+ <div class="quickforge-settings-row-main">
1344
+ <div class="quickforge-settings-row-title">${M(`lanAccessSessionTtl`)}</div>
1345
+ <div class="quickforge-settings-row-description">${M(`lanAccessSessionTtlDescription`)}</div>
1346
+ </div>
1347
+ <div class="quickforge-settings-row-control">
1348
+ <select class="quickforge-settings-select" .value=${String(this.sessionTtlHours)} @change=${e=>this.updateTtl(e.target.value)}>
1349
+ <option value="1">1 ${M(`hour`)}</option>
1350
+ <option value="12">12 ${M(`hours`)}</option>
1351
+ <option value="24">24 ${M(`hours`)}</option>
1352
+ <option value="168">7 ${M(`days`)}</option>
1353
+ </select>
1354
+ </div>
1355
+ </div>
1356
+
1357
+ <div class="quickforge-settings-row">
1358
+ <div class="quickforge-settings-row-main">
1359
+ <div class="quickforge-settings-row-title">${M(`lanAccessActions`)}</div>
1360
+ <div class="quickforge-settings-row-description">${M(`lanAccessActionsDescription`)}</div>
1361
+ </div>
1362
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1363
+ <button class="quickforge-settings-button quickforge-settings-button-primary" type="button" ?disabled=${this.saving} @click=${()=>this.saveSettings()}>
1364
+ ${this.saving?M(`saving`):M(`save`)}
1365
+ </button>
1366
+ <button class="quickforge-settings-button quickforge-settings-button-danger" type="button" ?disabled=${this.saving} @click=${()=>this.revokeAll()}>
1367
+ ${M(`lanAccessRevokeAll`)}
1368
+ </button>
1369
+ </div>
1370
+ </div>
1371
+ </section>
1372
+
1373
+ ${this.message?b`<div class="quickforge-settings-message">${this.message}</div>`:null}
1374
+ ${this.error?b`<div class="quickforge-settings-alert">${this.error}</div>`:null}
1375
+ </div>
1376
+ `}},Gt=`quickforge-lan-access-settings-tab`;customElements.get(Gt)||customElements.define(Gt,Wt);function Kt(){return document.createElement(Gt)}var qt=18e4,Jt=3e4,Yt=1e3,Xt=`https://github.com/shawnstack/quickforge/releases/latest`;function Zt(){if(typeof document>`u`)return!1;let e=window;return document.body.classList.contains(`quickforge-desktop-app`)||e.__quickforgeDesktopApp===!0}function Qt(e){return new Promise(t=>window.setTimeout(t,e))}function $t(e,t){return e?.code===`system_restart_requires_auth`?M(`systemRestartRequiresAuth`):e?.code===`system_update_requires_auth`?M(`systemUpdateRequiresAuth`):e?.error||t}var en=[{value:`startup`,label:()=>M(`frequencyStartup`)},{value:`daily`,label:()=>M(`frequencyDaily`)},{value:`weekly`,label:()=>M(`frequencyWeekly`)},{value:`off`,label:()=>M(`frequencyOff`)}],tn=class extends x{about;updateInfo;loading=!0;checking=!1;updating=!1;restarting=!1;message=``;error=``;frequency=Le.frequency;lastCheckAt=null;serviceStatus;getTabName(){return M(`about`)}async connectedCallback(){super.connectedCallback(),await this.loadAbout()}async loadAbout(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/system/about`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||M(`requestFailed`));this.about=t;try{let[e,t]=await Promise.all([Ve(S()),this.loadServiceStatus()]);this.frequency=e.frequency,this.lastCheckAt=e.lastCheckAt,this.serviceStatus=t}catch{}}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async loadServiceStatus(){let e=await fetch(`/api/health`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||M(`requestFailed`));return t}async checkUpdate(){if(!(this.checking||this.updating)){if(Zt()){window.open(Xt,`_blank`,`noopener,noreferrer`),this.message=M(`desktopUpdateHint`),this.error=``,this.requestUpdate();return}this.checking=!0,this.message=``,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/system/update/check`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||M(`updateCheckFailed`));this.updateInfo=t,this.about=t,this.updateInfo.updateAvailable?this.message=M(`updateAvailableMessage`,{current:this.updateInfo.currentVersion,latest:this.updateInfo.latestVersion}):this.updateInfo.localVersionIsNewer?this.message=M(`localVersionNewerMessage`,{current:this.updateInfo.currentVersion,latest:this.updateInfo.latestVersion}):this.message=M(`alreadyLatestVersion`,{version:this.updateInfo.currentVersion})}catch(e){this.error=e instanceof Error?e.message:M(`updateCheckFailed`)}finally{this.checking=!1,this.requestUpdate()}}}async pollUntilUpdated(e){let t=Date.now();for(;Date.now()-t<qt;){await Qt(Yt);try{let t=await fetch(`/api/health?updatePoll=${Date.now()}`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(t.ok&&n?.ok&&n.bootId&&n.bootId!==e){this.message=M(`updateRestarted`),this.requestUpdate(),window.setTimeout(()=>window.location.reload(),300);return}}catch{}}throw Error(M(`updateRestartTimeout`))}async pollUntilRestarted(e){let t=Date.now();for(;Date.now()-t<Jt;){await Qt(Yt);try{let t=await fetch(`/api/health?restartPoll=${Date.now()}`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(t.ok&&n?.ok&&n.bootId&&n.bootId!==e){this.message=M(`backendRestarted`),this.requestUpdate(),window.setTimeout(()=>window.location.reload(),300);return}}catch{}}throw Error(M(`backendRestartTimeout`))}async restartService(){if(!this.serviceStatus||this.restarting||!await T({description:M(`restartBackendConfirm`),confirmLabel:M(`restartBackendService`),cancelLabel:M(`cancel`)}))return;this.restarting=!0,this.message=M(`backendRestarting`),this.error=``,this.requestUpdate();let e=this.serviceStatus.bootId;try{let t=await fetch(`/api/system/restart`,{method:`POST`,headers:{"x-quickforge-action":`restart`}}),n=await t.json().catch(()=>null);if(!t.ok)throw Error($t(n,M(`backendRestartFailed`)));await this.pollUntilRestarted(e)}catch(e){this.error=e instanceof Error?e.message:M(`backendRestartFailed`),this.message=``,this.restarting=!1,this.requestUpdate()}}async updateQuickForge(){if(Zt()){window.open(Xt,`_blank`,`noopener,noreferrer`),this.message=M(`desktopUpdateHint`),this.error=``,this.requestUpdate();return}if(!(!this.updateInfo?.updateAvailable||this.updating)&&await T({description:M(`updateConfirm`,{command:this.updateInfo.installCommand}),confirmLabel:M(`updateRuntimeNow`),cancelLabel:M(`cancel`)})){this.updating=!0,this.message=M(`updatingQuickForge`),this.error=``,this.requestUpdate();try{let e=await fetch(`/api/system/update`,{method:`POST`,headers:{"x-quickforge-action":`update`}}),t=await e.json().catch(()=>null);if(!e.ok)throw Error($t(t,M(`updateFailed`)));if(this.updateInfo=t,t?.updateStarted){let e=t.logFile?` ${M(`updateLogFile`,{path:t.logFile})}`:``;this.message=`${M(`updateStarted`)}${e}`,this.requestUpdate(),await this.pollUntilUpdated(t.bootId)}else this.message=t?.updated?M(`updateCompleted`):M(`alreadyLatestVersion`,{version:t?.currentVersion||this.about?.version||`-`}),this.updating=!1}catch(e){this.error=e instanceof Error?e.message:M(`updateFailed`),this.message=``,this.updating=!1}finally{this.requestUpdate()}}}async selectFrequency(e){if(this.frequency!==e){this.frequency=e,this.requestUpdate();try{let t=S();await we(t,{...await Ve(t),frequency:e}),this.error=``}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.requestUpdate()}}}renderFrequencyOption(e){let t=this.frequency===e.value;return b`
1377
+ <button
1378
+ type="button"
1379
+ class="quickforge-settings-segmented-option ${t?`quickforge-settings-segmented-option-active`:``}"
1380
+ aria-pressed=${t?`true`:`false`}
1381
+ @click=${()=>this.selectFrequency(e.value)}
1382
+ >
1383
+ ${e.label()}
1384
+ </button>
1385
+ `}infoRows(){let e=this.about;return e?b`
1386
+ <div class="quickforge-settings-row">
1387
+ <div class="quickforge-settings-row-main">
1388
+ <div class="quickforge-settings-row-title">${M(`packageName`)}</div>
1389
+ <div class="quickforge-settings-row-description">${M(`packageNameDescription`)}</div>
1390
+ </div>
1391
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${e.name}</div>
1392
+ </div>
1393
+ <div class="quickforge-settings-row">
1394
+ <div class="quickforge-settings-row-main">
1395
+ <div class="quickforge-settings-row-title">${M(`currentVersion`)}</div>
1396
+ <div class="quickforge-settings-row-description">${M(`currentVersionDescription`)}</div>
1397
+ </div>
1398
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${e.version}</div>
1399
+ </div>
1400
+ <div class="quickforge-settings-row">
1401
+ <div class="quickforge-settings-row-main">
1402
+ <div class="quickforge-settings-row-title">${M(`github`)}</div>
1403
+ <div class="quickforge-settings-row-description">${M(`githubDescription`)}</div>
1404
+ </div>
1405
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide quickforge-settings-readonly-value">
1406
+ <a class="quickforge-settings-link" href=${e.repositoryUrl} target="_blank" rel="noreferrer">
1407
+ ${e.repositoryUrl}
1408
+ </a>
1409
+ </div>
1410
+ </div>
1411
+ `:null}updateStatus(){return this.updateInfo?b`
1412
+ <div class="quickforge-settings-row">
1413
+ <div class="quickforge-settings-row-main">
1414
+ <div class="quickforge-settings-row-title">${M(`latestVersion`)}</div>
1415
+ <div class="quickforge-settings-row-description">${M(`latestVersionDescription`)}</div>
1416
+ </div>
1417
+ <div class="quickforge-settings-row-control quickforge-settings-readonly-value">${this.updateInfo.latestVersion}</div>
1418
+ </div>
1419
+ ${this.updateInfo.logFile?b`
1420
+ <div class="quickforge-settings-row">
1421
+ <div class="quickforge-settings-row-main">
1422
+ <div class="quickforge-settings-row-title">${M(`updateLog`)}</div>
1423
+ <div class="quickforge-settings-row-description">${M(`updateLogDescription`)}</div>
1424
+ </div>
1425
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide quickforge-settings-readonly-value">
1426
+ <code>${this.updateInfo.logFile}</code>
1427
+ </div>
1428
+ </div>
1429
+ `:null}
1430
+ `:null}restartSection(){let e=this.serviceStatus?.restartUnsupportedReason||M(`backendRestartUnsupported`),t=this.restarting||!this.serviceStatus?.restartSupported;return b`
1431
+ <section class="quickforge-settings-section" aria-label=${M(`restartBackendService`)}>
1432
+ <div class="quickforge-settings-row">
1433
+ <div class="quickforge-settings-row-main">
1434
+ <div class="quickforge-settings-row-title">
1435
+ ${M(`restartBackendService`)}
1436
+ <quickforge-info-tip .label=${M(`restartBackendServiceDescription`)}></quickforge-info-tip>
1437
+ </div>
1438
+ <div class="quickforge-settings-row-description">
1439
+ ${this.serviceStatus?.restartSupported?M(`restartBackendServiceDescription`):e}
1440
+ </div>
1441
+ </div>
1442
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1443
+ <button
1444
+ class="quickforge-settings-button quickforge-settings-button-danger"
1445
+ type="button"
1446
+ ?disabled=${t}
1447
+ @click=${()=>this.restartService()}
1448
+ >
1449
+ ${this.restarting?M(`backendRestarting`):M(`restartBackendService`)}
1450
+ </button>
1451
+ </div>
1452
+ </div>
1453
+ </section>
1454
+ `}render(){if(this.loading)return b`<div class="text-sm text-muted-foreground">${M(`loading`)}</div>`;let e=this.checking||this.updating||!this.updateInfo?.updateAvailable,t=Zt();return b`
1455
+ <div class="quickforge-settings-stack">
1456
+ <section class="quickforge-settings-section" aria-label=${M(`projectInfo`)}>
1457
+ ${this.infoRows()}
1458
+ </section>
1459
+
1460
+ <section class="quickforge-settings-section" aria-label=${M(t?`desktopUpdates`:`runtimeUpdates`)}>
1461
+ ${t?null:b`
1462
+ <div class="quickforge-settings-row">
1463
+ <div class="quickforge-settings-row-main">
1464
+ <div class="quickforge-settings-row-title">
1465
+ ${M(`updateFrequencySection`)}
1466
+ <quickforge-info-tip .label=${M(`updateFrequencyDescription`)}></quickforge-info-tip>
1467
+ </div>
1468
+ <div class="quickforge-settings-row-description">
1469
+ ${this.lastCheckAt?M(`lastCheckedAt`,{time:new Date(this.lastCheckAt).toLocaleString(A())}):M(`lastCheckedNever`)}
1470
+ </div>
1471
+ </div>
1472
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1473
+ <div class="quickforge-settings-segmented quickforge-settings-segmented-wrap" role="group" aria-label=${M(`updateFrequencySection`)}>
1474
+ ${en.map(e=>this.renderFrequencyOption(e))}
1475
+ </div>
1476
+ </div>
1477
+ </div>
1478
+
1479
+ ${this.updateStatus()}
1480
+ `}
1481
+
1482
+ <div class="quickforge-settings-row">
1483
+ <div class="quickforge-settings-row-main">
1484
+ <div class="quickforge-settings-row-title">
1485
+ ${M(t?`desktopUpdates`:`runtimeUpdates`)}
1486
+ <quickforge-info-tip .label=${M(t?`desktopUpdatesDescription`:`runtimeUpdatesDescription`)}></quickforge-info-tip>
1487
+ </div>
1488
+ <div class="quickforge-settings-row-description">
1489
+ ${M(t?`desktopUpdatesDescription`:`runtimeUpdatesDescription`)}
1490
+ </div>
1491
+ </div>
1492
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1493
+ <button
1494
+ class="quickforge-settings-button quickforge-settings-button-secondary"
1495
+ type="button"
1496
+ ?disabled=${this.checking||this.updating}
1497
+ @click=${()=>this.checkUpdate()}
1498
+ >
1499
+ ${this.checking?M(`checkingUpdate`):M(t?`openDesktopReleases`:`checkRuntimeUpdate`)}
1500
+ </button>
1501
+ ${t?null:b`
1502
+ <button
1503
+ class="quickforge-settings-button quickforge-settings-button-primary"
1504
+ type="button"
1505
+ ?disabled=${e}
1506
+ @click=${()=>this.updateQuickForge()}
1507
+ >
1508
+ ${this.updating?M(`updatingQuickForge`):M(`updateRuntimeNow`)}
1509
+ </button>
1510
+ `}
1511
+ </div>
1512
+ </div>
1513
+ </section>
1514
+
1515
+ ${this.restartSection()}
1516
+
1517
+ ${this.message?b`<div class="quickforge-settings-message">${this.message}</div>`:null}
1518
+ ${this.error?b`<div class="quickforge-settings-alert">${this.error}</div>`:null}
1519
+ </div>
1520
+ `}},J=`quickforge-about-settings-tab`;customElements.get(J)||customElements.define(J,tn);function nn(){return document.createElement(J)}var rn=class extends x{loading=!0;saving=!1;saved=!1;error=``;message=``;projects=[];project;commandDir=``;commands=[];loadingCommands=!1;saveTimer=null;lastSavedCommandDir=``;pendingSaveAfterCurrent=!1;getTabName(){return M(`projectCommands`)}async connectedCallback(){super.connectedCallback(),await this.loadProjects()}async request(e,t){let n=await fetch(e,{...t,cache:`no-store`,headers:{...t?.body?{"content-type":`application/json`}:void 0,...t?.headers}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||M(`requestFailed`));return r}async loadProjects(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await this.request(`/api/project`);this.projects=e?.projects??(e?.project?[e.project]:[]),this.project=e?.project??this.projects[0],this.commandDir=typeof this.project?.commandDir==`string`?this.project.commandDir:``,this.lastSavedCommandDir=this.commandDir,await this.loadCommands()}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}selectProject(e){this.clearSaveTimer();let t=e.target,n=this.projects.find(e=>e.id===t.value);n&&(this.project=n,this.commandDir=typeof n.commandDir==`string`?n.commandDir:``,this.lastSavedCommandDir=this.commandDir,this.saved=!1,this.message=``,this.error=``,this.commands=[],this.requestUpdate(),this.loadCommands())}async loadCommands(){if(this.project?.id){this.loadingCommands=!0,this.requestUpdate();try{let e=await this.request(`/api/project/commands?projectId=${encodeURIComponent(this.project.id)}`);this.commands=e?.commands??[]}catch{this.commands=[]}finally{this.loadingCommands=!1,this.requestUpdate()}}}updateCommandDir(e){this.commandDir=e,this.saved=!1,this.message=``,this.scheduleSave(),this.requestUpdate()}clearSaveTimer(){this.saveTimer!==null&&(window.clearTimeout(this.saveTimer),this.saveTimer=null)}scheduleSave(){this.clearSaveTimer(),this.saveTimer=window.setTimeout(()=>{this.saveTimer=null,this.save()},800)}disconnectedCallback(){this.clearSaveTimer(),super.disconnectedCallback()}async save(){if(!this.project)return;if(this.saving){this.pendingSaveAfterCurrent=!0;return}let e=this.project.id,t=this.commandDir;if(t!==this.lastSavedCommandDir){this.saving=!0,this.saved=!1,this.error=``,this.message=``,this.requestUpdate();try{let n=await this.request(`/api/project/${encodeURIComponent(e)}/command-dir`,{method:`PUT`,body:JSON.stringify({commandDir:t})});if(this.project?.id===e){if(this.project=n?.project??this.project,this.project){let e=this.projects.findIndex(e=>e.id===this.project.id);e>=0&&(this.projects[e]=this.project)}this.commandDir=typeof this.project?.commandDir==`string`?this.project.commandDir:t,this.lastSavedCommandDir=this.commandDir,this.saved=!0,await this.loadCommands()}}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.saving=!1,this.pendingSaveAfterCurrent&&(this.pendingSaveAfterCurrent=!1,this.scheduleSave()),this.requestUpdate()}}}async openCommandDir(){if(this.project){this.error=``,this.message=``,this.requestUpdate();try{await this.request(`/api/project/open-path`,{method:`POST`,body:JSON.stringify({path:`.ai/commands`,projectId:this.project.id})})}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`),this.requestUpdate()}}}async createCommand(){if(!this.project)return;let e=window.prompt(M(`newCommandPrompt`));if(e?.trim()){this.error=``,this.message=``,this.requestUpdate();try{let t=await this.request(`/api/project/command`,{method:`POST`,body:JSON.stringify({name:e.trim(),projectId:this.project.id})});t.ok?(this.message=M(`commandCreated`,{name:t.name??e.trim()}),await this.loadCommands()):t.reason===`exists`?this.error=M(`commandAlreadyExists`,{name:t.name??e.trim()}):this.error=M(`invalidCommandName`)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.requestUpdate()}}}render(){return this.loading?b`<div class="quickforge-settings-note">${M(`loading`)}</div>`:this.projects.length===0?b`
1521
+ <div class="quickforge-settings-stack">
1522
+ <div class="quickforge-settings-note">${M(`selectProjectForCommands`)}</div>
1523
+ ${this.error?b`<div class="quickforge-settings-alert">${this.error}</div>`:null}
1524
+ </div>
1525
+ `:b`
1526
+ <div class="quickforge-settings-stack">
1527
+ <section class="quickforge-settings-section" aria-label=${M(`projectCommands`)}>
1528
+ <div class="quickforge-settings-row">
1529
+ <div class="quickforge-settings-row-main">
1530
+ <div class="quickforge-settings-row-title">${M(`project`)}</div>
1531
+ <div class="quickforge-settings-row-description">
1532
+ ${this.project?.path?this.project.path:M(`projectCommandsProjectDescription`)}
1533
+ </div>
1534
+ </div>
1535
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1536
+ <select
1537
+ class="quickforge-settings-select"
1538
+ .value=${this.project?.id??``}
1539
+ @change=${e=>this.selectProject(e)}
1540
+ >
1541
+ ${this.projects.map(e=>b`<option value=${e.id} ?selected=${e.id===this.project?.id}>${e.name}</option>`)}
1542
+ </select>
1543
+ </div>
1544
+ </div>
1545
+
1546
+ <div class="quickforge-settings-row quickforge-settings-row-align-start">
1547
+ <div class="quickforge-settings-row-main">
1548
+ <div class="quickforge-settings-row-title">
1549
+ ${M(`commandDirectories`)}
1550
+ <quickforge-info-tip .label=${M(`commandDirectoryHelp`)}></quickforge-info-tip>
1551
+ </div>
1552
+ <div class="quickforge-settings-row-description">${M(`commandDirectoriesDescription`)}</div>
1553
+ </div>
1554
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1555
+ <textarea
1556
+ class="quickforge-settings-textarea quickforge-settings-mono"
1557
+ .value=${this.commandDir}
1558
+ placeholder=${M(`commandDirectoryPlaceholder`)}
1559
+ @input=${e=>this.updateCommandDir(e.target.value)}
1560
+ ></textarea>
1561
+ </div>
1562
+ </div>
1563
+
1564
+ <div class="quickforge-settings-row quickforge-settings-row-align-start">
1565
+ <div class="quickforge-settings-row-main">
1566
+ <div class="quickforge-settings-row-title">${M(`commandDirectoryExamples`)}</div>
1567
+ <div class="quickforge-settings-row-description">${M(`commandDirectoryExamplesDescription`)}</div>
1568
+ </div>
1569
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide quickforge-settings-code-list">
1570
+ <code>.ai/commands</code>
1571
+ <code>.claude/commands</code>
1572
+ <code>.opencode/commands</code>
1573
+ <code>D:\shared\ai-commands</code>
1574
+ </div>
1575
+ </div>
1576
+ </section>
1577
+
1578
+ <section class="quickforge-settings-section" aria-label=${M(`loadedCommands`,{count:this.commands.length})}>
1579
+ <div class="quickforge-settings-row">
1580
+ <div class="quickforge-settings-row-main">
1581
+ <div class="quickforge-settings-row-title">${M(`loadedCommands`,{count:this.commands.length})}</div>
1582
+ <div class="quickforge-settings-row-description">${M(`loadedCommandsDescription`)}</div>
1583
+ </div>
1584
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1585
+ <button
1586
+ class="quickforge-settings-button quickforge-settings-button-secondary"
1587
+ type="button"
1588
+ ?disabled=${this.loadingCommands}
1589
+ @click=${()=>this.openCommandDir()}
1590
+ >
1591
+ ${M(`openCommandDir`)}
1592
+ </button>
1593
+ <button
1594
+ class="quickforge-settings-button quickforge-settings-button-primary"
1595
+ type="button"
1596
+ ?disabled=${this.loadingCommands}
1597
+ @click=${()=>this.createCommand()}
1598
+ >
1599
+ ${M(`createCommand`)}
1600
+ </button>
1601
+ </div>
1602
+ </div>
1603
+
1604
+ <div class="quickforge-settings-nested-list">
1605
+ ${this.loadingCommands?b`<div class="quickforge-settings-empty-row">${M(`loading`)}</div>`:this.commands.length===0?b`<div class="quickforge-settings-empty-row">${M(`noCommandsLoaded`)}</div>`:this.commands.map(e=>{let t=e.argumentHint?` ${e.argumentHint}`:``;return b`
1606
+ <div class="quickforge-settings-subrow">
1607
+ <div class="quickforge-settings-row-main">
1608
+ <div class="quickforge-settings-row-title">
1609
+ <code class="quickforge-settings-command-name">/${e.name}${t}</code>
1610
+ </div>
1611
+ <div class="quickforge-settings-row-description">
1612
+ ${e.description||M(`noDescription`)}
1613
+ </div>
1614
+ </div>
1615
+ ${e.relativePath?b`<div class="quickforge-settings-row-control quickforge-settings-row-control-wide quickforge-settings-readonly-value">${e.relativePath}</div>`:null}
1616
+ </div>
1617
+ `})}
1618
+ </div>
1619
+ </section>
1620
+
1621
+ ${this.saving?b`<div class="quickforge-settings-note">${M(`saving`)}</div>`:null}
1622
+ ${this.saved?b`<div class="quickforge-settings-message">${M(`projectCommandsSaved`)}</div>`:null}
1623
+ ${this.message?b`<div class="quickforge-settings-message">${this.message}</div>`:null}
1624
+ ${this.error?b`<div class="quickforge-settings-alert">${this.error}</div>`:null}
1625
+ </div>
1626
+ `}},an=`quickforge-project-commands-settings-tab`;customElements.get(an)||customElements.define(an,rn);function on(){return document.createElement(an)}var Y={"x-quickforge-action":`channel-action`};function sn(e){switch(e){case`running`:return`quickforge-settings-badge-success`;case`waiting_scan`:case`starting`:case`stopping`:return`quickforge-settings-badge-warning`;case`error`:return`quickforge-settings-badge-danger`;default:return`quickforge-settings-badge-muted`}}function cn(e){switch(e){case`starting`:return M(`channelStatusStarting`);case`waiting_scan`:return M(`channelStatusWaitingScan`);case`running`:return M(`channelStatusRunning`);case`stopping`:return M(`channelStatusStopping`);case`error`:return M(`channelStatusError`);default:return M(`channelStatusStopped`)}}var ln=class extends x{loading=!0;channels=[];workspaces=[];selectedWorkspaceIdByChannel={};error=``;message=``;eventSource;busyChannelId=``;openingLogsChannelId=``;getTabName(){return M(`channels`)}async connectedCallback(){super.connectedCallback(),await Promise.all([this.loadChannels(),this.loadWorkspaces()]),this.connectEvents()}disconnectedCallback(){this.eventSource?.close(),this.eventSource=void 0,super.disconnectedCallback()}async request(e,t){let n=await fetch(e,{...t,cache:`no-store`,headers:{...t?.headers||{}}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||M(`requestFailed`));return r}async loadChannels(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await this.request(`/api/channels`);this.channels=Array.isArray(e.channels)?e.channels:[],this.ensureWorkspaceSelections()}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async loadWorkspaces(){try{let e=await this.request(`/api/project`),t=e.defaultWorkspaceRoot||``,n=t?[{id:`default`,name:M(`channelDefaultWorkspace`),path:t,kind:`default`}]:[],r=(Array.isArray(e.projects)?e.projects:[]).map(e=>({id:e.id,name:e.name,path:e.path,kind:`project`}));this.workspaces=[...n,...r],this.ensureWorkspaceSelections()}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.requestUpdate()}}ensureWorkspaceSelections(){let e=new Set(this.workspaces.map(e=>e.id)),t={...this.selectedWorkspaceIdByChannel};for(let n of this.channels){if(!n.supportsWorkspaceSelection)continue;let r=t[n.id],i=n.launchWorkspace?.id,a=n.status!==`stopped`&&n.status!==`error`;if(i&&e.has(i)&&a){t[n.id]=i;continue}r&&e.has(r)||(t[n.id]=i&&e.has(i)?i:`default`)}this.selectedWorkspaceIdByChannel=t}connectEvents(){this.eventSource?.close();let e=new EventSource(`/api/channels/events`);this.eventSource=e;let t=e=>{try{let t=JSON.parse(e.data);this.applyChannelEvent(t)}catch{}};e.addEventListener(`snapshot`,t),e.addEventListener(`status`,t),e.addEventListener(`log`,t),e.addEventListener(`qrcode`,t),e.addEventListener(`error`,()=>{})}applyChannelEvent(e){if(Array.isArray(e.channels)){this.channels=e.channels,this.ensureWorkspaceSelections(),this.requestUpdate();return}if(e.snapshot){this.upsertChannel(e.snapshot);return}}upsertChannel(e){let t=this.channels.findIndex(t=>t.id===e.id);t>=0?this.channels=[...this.channels.slice(0,t),e,...this.channels.slice(t+1)]:this.channels=[...this.channels,e],this.ensureWorkspaceSelections(),this.requestUpdate()}selectedWorkspaceId(e){return this.selectedWorkspaceIdByChannel[e.id]||e.launchWorkspace?.id||`default`}handleWorkspaceChange(e,t){let n=t.currentTarget;n&&(this.selectedWorkspaceIdByChannel={...this.selectedWorkspaceIdByChannel,[e.id]:n.value||`default`},this.requestUpdate())}startOptions(e){return e.supportsWorkspaceSelection?{projectId:this.selectedWorkspaceId(e)}:void 0}async invoke(e,t){if(!this.busyChannelId&&!(t===`restart`&&!await T({description:M(`channelRestartConfirm`,{name:e.name}),confirmLabel:M(`restart`),cancelLabel:M(`cancel`)}))){this.busyChannelId=e.id,this.error=``,this.message=``,this.requestUpdate();try{let n=t===`start`||t===`restart`?this.startOptions(e):void 0,r=await this.request(`/api/channels/${encodeURIComponent(e.id)}/${t}`,{method:`POST`,headers:n?{...Y,"content-type":`application/json`}:Y,body:n?JSON.stringify(n):void 0});this.upsertChannel(r)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.busyChannelId=``,this.requestUpdate()}}}async invokeAction(e,t){if(!this.busyChannelId&&!((t.destructive||t.id===`relogin`)&&!await T({description:t.id===`relogin`?M(`channelReloginConfirm`,{name:e.name}):M(`channelLogoutConfirm`,{name:e.name}),confirmLabel:t.label,cancelLabel:M(`cancel`),variant:t.destructive?`destructive`:void 0}))){this.busyChannelId=e.id,this.error=``,this.message=``,this.requestUpdate();try{let n=t.id===`relogin`?this.startOptions(e):void 0,r=await this.request(`/api/channels/${encodeURIComponent(e.id)}/actions/${encodeURIComponent(t.id)}`,{method:`POST`,headers:n?{...Y,"content-type":`application/json`}:Y,body:n?JSON.stringify(n):void 0});this.upsertChannel(r)}catch(e){this.error=e instanceof Error?e.message:M(`requestFailed`)}finally{this.busyChannelId=``,this.requestUpdate()}}}async openLogs(e){if(!this.openingLogsChannelId){this.openingLogsChannelId=e.id,this.error=``,this.message=``,this.requestUpdate();try{await this.request(`/api/channels/${encodeURIComponent(e.id)}/open-logs`,{method:`POST`,headers:Y})}catch(e){this.error=e instanceof Error?e.message:M(`channelOpenLogsFailed`)}finally{this.openingLogsChannelId=``,this.requestUpdate()}}}workspaceSection(e,t){if(!e.supportsWorkspaceSelection)return null;let n=this.selectedWorkspaceId(e);return b`
1627
+ <div class="quickforge-settings-row quickforge-settings-row-align-start">
1628
+ <div class="quickforge-settings-row-main">
1629
+ <div class="quickforge-settings-row-title">
1630
+ ${M(`channelWorkspace`)}
1631
+ <quickforge-info-tip .label=${M(`channelWorkspaceDescription`)}></quickforge-info-tip>
1632
+ </div>
1633
+ <div class="quickforge-settings-row-description">${M(`channelWorkspaceDescription`)}</div>
1634
+ </div>
1635
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1636
+ <select
1637
+ class="quickforge-settings-select"
1638
+ ?disabled=${t}
1639
+ .value=${n}
1640
+ @change=${t=>this.handleWorkspaceChange(e,t)}
1641
+ >
1642
+ ${this.workspaces.map(e=>b`
1643
+ <option value=${e.id}>${e.kind===`default`?M(`channelDefaultWorkspace`):e.name}</option>
1644
+ `)}
1645
+ </select>
1646
+ </div>
1647
+ </div>
1648
+ `}qrSection(e){return e.qrCodeText?b`
1649
+ <div class="quickforge-settings-row quickforge-settings-row-align-start">
1650
+ <div class="quickforge-settings-row-main">
1651
+ <div class="quickforge-settings-row-title">
1652
+ ${M(`channelQrTitle`)}
1653
+ <quickforge-info-tip .label=${M(`channelQrDescription`)}></quickforge-info-tip>
1654
+ </div>
1655
+ <div class="quickforge-settings-row-description">${M(`channelQrDescription`)}</div>
1656
+ </div>
1657
+ <pre class="quickforge-channel-qr-text">${e.qrCodeText}</pre>
1658
+ </div>
1659
+ `:null}channelCard(e){let t=this.busyChannelId===e.id||!!e.activeAction,n=this.openingLogsChannelId===e.id,r=e.status===`running`||e.status===`waiting_scan`||e.status===`starting`,i=e.status===`stopping`,a=!!(e.supportsWorkspaceSelection&&this.workspaces.length===0);return b`
1660
+ <section class="quickforge-settings-section" aria-label=${e.name}>
1661
+ <div class="quickforge-settings-row quickforge-settings-row-top">
1662
+ <div class="quickforge-settings-row-main">
1663
+ <div class="quickforge-settings-row-title">
1664
+ ${e.name}
1665
+ <span class="quickforge-settings-badge ${sn(e.status)}">${cn(e.status)}</span>
1666
+ </div>
1667
+ <div class="quickforge-settings-row-description">${e.description}</div>
1668
+ </div>
1669
+ <div class="quickforge-settings-row-control quickforge-settings-row-control-wide">
1670
+ <button class="quickforge-settings-button quickforge-settings-button-primary" type="button" ?disabled=${t||r||i||a} @click=${()=>this.invoke(e,`start`)}>${M(`start`)}</button>
1671
+ <button class="quickforge-settings-button quickforge-settings-button-secondary" type="button" ?disabled=${t||!r||i} @click=${()=>this.invoke(e,`stop`)}>${M(`stop`)}</button>
1672
+ <button class="quickforge-settings-button quickforge-settings-button-secondary" type="button" ?disabled=${t||i||a} @click=${()=>this.invoke(e,`restart`)}>${M(`restart`)}</button>
1673
+ ${e.actions?.map(n=>b`
1674
+ <button class="quickforge-settings-button ${n.destructive?`quickforge-settings-button-danger`:`quickforge-settings-button-secondary`}" type="button" ?disabled=${t} @click=${()=>this.invokeAction(e,n)}>${n.label}</button>
1675
+ `)}
1676
+ <button class="quickforge-settings-button quickforge-settings-button-secondary" type="button" ?disabled=${!!this.openingLogsChannelId} @click=${()=>this.openLogs(e)}>${M(n?`channelOpeningLogs`:`channelOpenLogs`)}</button>
1677
+ </div>
1678
+ </div>
1679
+
1680
+ ${this.workspaceSection(e,t||r||i)}
1681
+ ${a?b`<div class="quickforge-settings-alert quickforge-settings-warning-attached">${M(`channelNoWorkspaces`)}</div>`:null}
1682
+ ${e.error?b`<div class="quickforge-settings-alert quickforge-settings-warning-attached">${e.error}</div>`:null}
1683
+ ${this.qrSection(e)}
1684
+ </section>
1685
+ `}render(){return this.loading?b`<div class="quickforge-settings-note">${M(`loading`)}</div>`:b`
1686
+ <div class="quickforge-settings-stack">
1687
+ <div class="quickforge-settings-note">
1688
+ ${M(`channelsSecurityWarning`)}
1689
+ </div>
1690
+
1691
+ ${this.channels.length?b`${this.channels.map(e=>this.channelCard(e))}`:b`<div class="quickforge-settings-note">${M(`channelsEmpty`)}</div>`}
1692
+
1693
+ ${this.message?b`<div class="quickforge-settings-message">${this.message}</div>`:null}
1694
+ ${this.error?b`<div class="quickforge-settings-alert">${this.error}</div>`:null}
1695
+ </div>
1696
+ `}},un=`quickforge-channels-settings-tab`;customElements.get(un)||customElements.define(un,ln);function dn(){return document.createElement(un)}var fn=ie(),X=y(),pn=(0,N.lazy)(()=>C(()=>import(`./AgentProfilesPage-Dl5Peqov.js`).then(e=>({default:e.AgentProfilesPage})),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]))),mn=(0,N.lazy)(()=>C(()=>import(`./mcp-servers-dialog-BEV4_TXC.js`).then(e=>({default:e.McpServersPanel})),__vite__mapDeps([15,1,2,3,4,5,6,7,8,9,10,11,12,13]))),hn=(0,N.lazy)(()=>C(()=>import(`./skills-dialog-BTJ7mzk_.js`).then(e=>e.n).then(e=>({default:e.SkillsManagerPanel})),__vite__mapDeps([10,1,2,3,4,5,6,7,8,9,11,12,13]))),gn=(0,N.lazy)(()=>C(()=>import(`./PluginsPage-BDKYfLna.js`).then(e=>({default:e.PluginsPage})),__vite__mapDeps([16,1,2,3,4,5,6,7,8,9,10,11,12,13,17]))),_n=(0,N.lazy)(()=>C(()=>import(`./ScheduledTasksPage--GAki3lB.js`).then(e=>({default:e.ScheduledTasksPage})),__vite__mapDeps([18,1,2,3,4,5,6,7,8,9,10,11,12,13,14]))),vn=(0,N.lazy)(()=>C(()=>import(`./ShareLinksSettingsPage-BQQMsvJo.js`).then(e=>({default:e.ShareLinksSettingsPage})),__vite__mapDeps([19,1,2,3,4,5,6,7,8,9,10,11,12,13]))),yn=(0,N.lazy)(()=>C(()=>import(`./CloudAccountSettingsPage-BG5Nn3bq.js`).then(e=>({default:e.CloudAccountSettingsPage})),__vite__mapDeps([20,1,2,3,4,5,6,7,8,9,10,11,12,13]))),bn=class extends x{tabName=``;renderReact;root;getTabName(){return this.tabName}connectedCallback(){super.connectedCallback(),this.updateComplete.then(()=>this.mountReact())}disconnectedCallback(){this.root?.unmount(),this.root=void 0,super.disconnectedCallback()}render(){return b`<div class="quickforge-react-settings-tab h-full min-h-0"></div>`}mountReact(){let e=this.querySelector(`.quickforge-react-settings-tab`);!e||!this.renderReact||(this.root??=(0,fn.createRoot)(e),this.root.render(this.renderReact()))}},xn=`quickforge-react-settings-tab`;customElements.get(xn)||customElements.define(xn,bn);function Z(e,t){let n=document.createElement(xn);return n.tabName=e,n.renderReact=t,n}function Q({children:e}){return(0,X.jsx)(`div`,{className:`quickforge-settings-stack h-full min-h-[30rem]`,children:(0,X.jsx)(N.Suspense,{fallback:(0,X.jsx)(`div`,{className:`quickforge-settings-note`,children:M(`loading`)}),children:e})})}function Sn(e){window.dispatchEvent(new CustomEvent(`quickforge:open-session-from-settings`,{detail:{sessionId:e}}))}function Cn(){return Z(M(`agentsTab`),()=>(0,X.jsx)(Q,{children:(0,X.jsx)(pn,{})}))}function wn(){return Z(M(`skills`),()=>(0,X.jsx)(Q,{children:(0,X.jsx)(hn,{active:!0,scope:`global`,embedded:!0,onSaved:()=>void 0})}))}function Tn(){return Z(M(`mcpServers`),()=>(0,X.jsx)(Q,{children:(0,X.jsx)(mn,{active:!0})}))}function En(){return Z(M(`plugins`),()=>(0,X.jsx)(Q,{children:(0,X.jsx)(gn,{})}))}function Dn(){return Z(M(`scheduledTasks`),()=>(0,X.jsx)(Q,{children:(0,X.jsx)(_n,{onOpenSession:Sn})}))}function On(){return Z(M(`cloudAccount`),()=>(0,X.jsx)(Q,{children:(0,X.jsx)(yn,{})}))}function kn(){return Z(M(`shareLinks`),()=>(0,X.jsx)(Q,{children:(0,X.jsx)(vn,{})}))}function An(e){let t=[{key:`appearance`,tab:Qe(),getDescription:()=>M(`appearanceDescription`)},{key:`cloudAccount`,tab:On(),getDescription:()=>M(`cloudAccountDescription`)},{key:`defaults`,tab:vt(),getDescription:()=>M(`defaultOptionsDescription`)},{key:`memory`,tab:Tt(),getDescription:()=>M(`memoryDescription`)},{key:`customModels`,tab:Ye(e),getDescription:()=>M(`customModelsDescription`)},{key:`agents`,tab:Cn(),getDescription:()=>M(`agentsDescription`)},{key:`skills`,tab:wn(),getDescription:()=>M(`globalSkillsDescription`)},{key:`mcp`,tab:Tn(),getDescription:void 0},{key:`plugins`,tab:En(),getDescription:()=>M(`pluginsDescription`)},{key:`scheduledTasks`,tab:Dn(),getDescription:()=>M(`scheduledTasksDescription`)},{key:`projectCommands`,tab:on(),getDescription:()=>M(`projectCommandsDescription`)},{key:`backup`,tab:Ft(),getDescription:()=>M(`backupRestoreDescription`)},{key:`archivedConversations`,tab:Bt(),getDescription:()=>M(`archivedConversationsDescription`)},{key:`shareLinks`,tab:kn(),getDescription:()=>M(`shareLinksDescription`)},{key:`channels`,tab:dn(),getDescription:()=>M(`channelsDescription`)},{key:`lanAccess`,tab:Kt(),getDescription:()=>M(`lanAccessDescription`)},{key:`about`,tab:nn(),getDescription:()=>M(`aboutQuickForgeDescription`)}];return{items:[...t],tabs:t.map(e=>e.tab),indexOf:e=>t.findIndex(t=>t.key===e)}}var $={appearance:a,cloudAccount:_,defaults:te,memory:i,customModels:d,agents:s,skills:v,mcp:u,plugins:g,scheduledTasks:r,projectCommands:h,backup:t,archivedConversations:n,shareLinks:l,channels:p,lanAccess:f,about:o};function jn({tab:e}){let t=(0,N.useRef)(null);return(0,N.useEffect)(()=>{let n=t.current;if(n)return n.replaceChildren(e),()=>{e.parentNode===n&&n.removeChild(e)}},[e]),(0,X.jsx)(`div`,{ref:t,className:`quickforge-settings-tab-host min-h-0 flex-1`})}function Mn({initialTab:e,customProvider:t,onBack:n}){let r=(0,N.useMemo)(()=>An(t),[t]),i=Math.max(0,r.indexOf(e)),[a,o]=(0,N.useState)(),[s,l]=(0,N.useState)(null),u=a??i,[d,f]=(0,N.useState)(``),p=d.trim().toLowerCase(),m=(0,N.useMemo)(()=>r.items.map((e,t)=>({item:e,index:t})).filter(({item:e})=>p?[e.key,e.tab.getTabName(),e.getDescription?.()??``].join(` `).toLowerCase().includes(p):!0),[r.items,p]),h=(0,N.useMemo)(()=>{if(!p)return u;let e=m[0];return e?m.some(({index:e})=>e===u)?u:e.index:u},[u,m,p]),g=r.items[h]??r.items[0],_=g?.getDescription?.(),v=g?$[g.key]:void 0,y=(0,N.useRef)(null),[ie,ae]=(0,N.useState)(!1);return(0,N.useEffect)(()=>{y.current?.scrollTo({top:0})},[h,s]),(0,X.jsxs)(`div`,{className:`flex h-screen min-h-0 supports-[height:100dvh]:h-dvh bg-[var(--quickforge-sidebar-bg)] text-foreground`,children:[(0,X.jsxs)(`aside`,{className:`relative z-10 hidden w-80 shrink-0 overflow-hidden bg-[var(--quickforge-sidebar-bg)] md:flex md:min-h-0 md:flex-col`,children:[(0,X.jsxs)(`div`,{className:`shrink-0 px-3 pb-2 pt-3`,children:[(0,X.jsxs)(`button`,{type:`button`,className:`group relative flex w-full items-center gap-2 overflow-hidden rounded-lg px-2 py-1.5 text-left text-muted-foreground/72 transition-[background-color,color,box-shadow] duration-160 ease-out hover:bg-[var(--quickforge-sidebar-hover-bg)] hover:text-foreground/86 hover:shadow-[0_8px_20px_-18px_rgb(15_23_42_/_0.35)]`,onClick:n,"aria-label":`返回工作区`,children:[(0,X.jsx)(`span`,{className:`inline-flex size-6 shrink-0 items-center justify-center rounded-full text-muted-foreground/55 transition-colors group-hover:text-foreground/70`,children:(0,X.jsx)(ee,{className:`size-4`})}),(0,X.jsx)(`span`,{className:`truncate text-sm leading-5`,children:`返回工作区`})]}),(0,X.jsxs)(`div`,{className:`quickforge-settings-inline-field mt-3`,children:[(0,X.jsx)(re,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground/60`,"aria-hidden":`true`}),(0,X.jsx)(`input`,{value:d,onChange:e=>f(e.target.value),placeholder:M(`searchSettings`),"aria-label":M(`searchSettings`),className:`quickforge-settings-input`})]})]}),(0,X.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-3 pb-4 pt-4`,children:(0,X.jsxs)(`nav`,{className:`space-y-1`,"aria-label":M(`settings`),children:[m.map(({item:e,index:t})=>{let n=t===h,r=$[e.key];return(0,X.jsxs)(`button`,{type:`button`,className:O(`group relative flex w-full items-center gap-2.5 overflow-hidden rounded-lg px-2 py-1.5 text-left text-sm leading-5 transition-[background-color,color,box-shadow] duration-160 ease-out`,n?`bg-[var(--quickforge-sidebar-active-bg)] font-medium text-foreground/92 shadow-[0_8px_22px_-20px_rgb(15_23_42_/_0.32)]`:`text-muted-foreground/76 hover:bg-[var(--quickforge-sidebar-hover-bg)] hover:text-foreground/90 hover:shadow-[0_8px_20px_-18px_rgb(15_23_42_/_0.35)]`),onClick:()=>o(t),"aria-current":n?`page`:void 0,children:[(0,X.jsx)(`span`,{className:O(`inline-flex size-5 shrink-0 items-center justify-center transition-colors`,n?`text-foreground/72`:`text-muted-foreground/52 group-hover:text-foreground/68`),children:(0,X.jsx)(r,{className:`size-4`,"aria-hidden":`true`})}),(0,X.jsx)(`span`,{className:`truncate`,children:e.tab.getTabName()})]},e.key)}),m.length===0?(0,X.jsx)(`div`,{className:`px-2 py-3 text-sm text-muted-foreground/70`,children:M(`noSettingsResults`)}):null]})})]}),(0,X.jsxs)(`main`,{className:`relative flex min-w-0 flex-1 flex-col bg-[var(--quickforge-main-bg)] md:overflow-hidden md:rounded-tl-2xl`,children:[(0,X.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-3 pr-4 md:px-5`,children:[(0,X.jsx)(Pe,{variant:`ghost`,size:`icon`,className:`md:hidden`,onClick:s===null?n:()=>l(null),"aria-label":s===null?`返回工作区`:`返回设置`,children:(0,X.jsx)(ee,{className:`size-4`})}),(0,X.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,X.jsxs)(`div`,{className:O(`flex min-w-0 items-center gap-2`,s===null?`md:hidden`:`hidden`),children:[(0,X.jsx)(te,{className:`size-4 shrink-0 text-muted-foreground/65`,"aria-hidden":`true`}),(0,X.jsx)(`div`,{className:`min-w-0 truncate text-sm font-medium text-foreground/90`,children:M(`settings`)})]}),(0,X.jsxs)(`div`,{className:O(`flex min-w-0 items-center gap-2`,s===null&&`hidden md:flex`),children:[v?(0,X.jsx)(v,{className:`size-4 shrink-0 text-muted-foreground/65`,"aria-hidden":`true`}):null,(0,X.jsx)(`div`,{className:`min-w-0 truncate text-sm font-medium text-foreground/90`,children:g?.tab.getTabName()}),_?(0,X.jsx)(De,{label:_}):null]})]})]}),(0,X.jsxs)(`div`,{className:O(`flex min-h-0 flex-1 flex-col md:hidden`,s!==null&&`hidden`),children:[(0,X.jsx)(`div`,{className:`shrink-0 border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_30%,transparent)] px-3 py-2`,children:(0,X.jsxs)(`div`,{className:`quickforge-settings-inline-field`,children:[(0,X.jsx)(re,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground/60`,"aria-hidden":`true`}),(0,X.jsx)(`input`,{value:d,onChange:e=>f(e.target.value),placeholder:M(`searchSettings`),"aria-label":M(`searchSettings`),className:`quickforge-settings-input`})]})}),(0,X.jsx)(`nav`,{className:`quickforge-settings-mobile-list`,"aria-label":M(`settings`),children:(0,X.jsxs)(`div`,{className:`quickforge-settings-mobile-list-card`,children:[m.map(({item:e,index:t})=>{let n=$[e.key];return(0,X.jsxs)(`button`,{type:`button`,className:`quickforge-settings-mobile-list-item`,onClick:()=>{o(t),l(t)},children:[(0,X.jsx)(`span`,{className:`quickforge-settings-mobile-list-icon`,children:(0,X.jsx)(n,{className:`size-4 shrink-0`,"aria-hidden":`true`})}),(0,X.jsx)(`span`,{className:`quickforge-settings-mobile-list-label`,children:e.tab.getTabName()}),(0,X.jsx)(ne,{className:`quickforge-settings-mobile-list-chevron size-4 shrink-0`,"aria-hidden":`true`})]},e.key)}),m.length===0?(0,X.jsx)(`div`,{className:`px-2 py-8 text-center text-sm text-muted-foreground/70`,children:M(`noSettingsResults`)}):null]})})]}),(0,X.jsx)(`section`,{ref:y,onScroll:()=>ae((y.current?.scrollTop??0)>160),className:O(`min-h-0 flex-1 overflow-y-auto px-4 py-5 md:px-8 md:py-7`,s===null&&`hidden md:block`),children:(0,X.jsx)(`div`,{className:`mx-auto flex min-h-full w-full max-w-5xl flex-col`,children:m.length===0?(0,X.jsx)(`div`,{className:`rounded-xl border border-dashed border-[color-mix(in_oklab,var(--border)_70%,transparent)] p-8 text-center text-sm text-muted-foreground/70`,children:M(`noSettingsResults`)}):g?(0,X.jsx)(jn,{tab:g.tab}):null})}),(0,X.jsx)(`button`,{type:`button`,onClick:()=>y.current?.scrollTo({top:0,behavior:`smooth`}),"aria-label":`返回顶部`,className:O(`absolute bottom-5 right-4 z-20 flex size-9 items-center justify-center rounded-[10px] border-[0.5px] border-[color-mix(in_oklab,var(--border)_65%,transparent)] bg-[var(--background)] text-muted-foreground/85 shadow-[0_10px_24px_-16px_rgb(15_23_42_/_0.55)] transition-opacity duration-160 md:hidden`,ie?`opacity-100`:`pointer-events-none opacity-0`,s===null&&`hidden`),children:(0,X.jsx)(c,{className:`size-4`})})]})]})}export{Mn as SettingsWorkspacePage};