cli-jaw 1.4.11 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +56 -26
- package/README.md +30 -24
- package/README.zh-CN.md +56 -26
- package/dist/bin/commands/browser.js +3 -1
- package/dist/bin/commands/browser.js.map +1 -1
- package/dist/bin/commands/chat.js +358 -9
- package/dist/bin/commands/chat.js.map +1 -1
- package/dist/bin/commands/doctor.js +80 -2
- package/dist/bin/commands/doctor.js.map +1 -1
- package/dist/bin/commands/init.js +88 -6
- package/dist/bin/commands/init.js.map +1 -1
- package/dist/bin/commands/serve.js +1 -0
- package/dist/bin/commands/serve.js.map +1 -1
- package/dist/lib/mcp-sync.js +101 -51
- package/dist/lib/mcp-sync.js.map +1 -1
- package/dist/lib/quota-copilot.js +4 -0
- package/dist/lib/quota-copilot.js.map +1 -1
- package/dist/server.js +131 -35
- package/dist/server.js.map +1 -1
- package/dist/src/agent/events.js +198 -29
- package/dist/src/agent/events.js.map +1 -1
- package/dist/src/agent/smoke-detector.js +111 -0
- package/dist/src/agent/smoke-detector.js.map +1 -0
- package/dist/src/agent/spawn.js +157 -26
- package/dist/src/agent/spawn.js.map +1 -1
- package/dist/src/browser/connection.js +9 -1
- package/dist/src/browser/connection.js.map +1 -1
- package/dist/src/browser/launch-policy.js +32 -0
- package/dist/src/browser/launch-policy.js.map +1 -0
- package/dist/src/cli/claude-models.js +46 -0
- package/dist/src/cli/claude-models.js.map +1 -0
- package/dist/src/cli/command-context.js +19 -8
- package/dist/src/cli/command-context.js.map +1 -1
- package/dist/src/cli/commands.js +16 -13
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/compact.js +93 -0
- package/dist/src/cli/compact.js.map +1 -0
- package/dist/src/cli/handlers.js +94 -32
- package/dist/src/cli/handlers.js.map +1 -1
- package/dist/src/cli/readiness.js +69 -0
- package/dist/src/cli/readiness.js.map +1 -0
- package/dist/src/cli/registry.js +3 -2
- package/dist/src/cli/registry.js.map +1 -1
- package/dist/src/cli/tui/composer.js +6 -4
- package/dist/src/cli/tui/composer.js.map +1 -1
- package/dist/src/cli/tui/keymap.js +2 -0
- package/dist/src/cli/tui/keymap.js.map +1 -1
- package/dist/src/cli/tui/overlay.js +170 -0
- package/dist/src/cli/tui/overlay.js.map +1 -1
- package/dist/src/cli/tui/store.js +25 -0
- package/dist/src/cli/tui/store.js.map +1 -1
- package/dist/src/cli/tui/transcript.js +46 -0
- package/dist/src/cli/tui/transcript.js.map +1 -0
- package/dist/src/command-contract/catalog.js +8 -4
- package/dist/src/command-contract/catalog.js.map +1 -1
- package/dist/src/core/bus.js +1 -0
- package/dist/src/core/bus.js.map +1 -1
- package/dist/src/core/compact.js +70 -0
- package/dist/src/core/compact.js.map +1 -0
- package/dist/src/core/config.js +109 -3
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/db.js +13 -4
- package/dist/src/core/db.js.map +1 -1
- package/dist/src/core/main-session.js +15 -0
- package/dist/src/core/main-session.js.map +1 -1
- package/dist/src/core/runtime-settings.js +19 -4
- package/dist/src/core/runtime-settings.js.map +1 -1
- package/dist/src/core/settings-merge.js +1 -1
- package/dist/src/core/settings-merge.js.map +1 -1
- package/dist/src/discord/bot.js +274 -0
- package/dist/src/discord/bot.js.map +1 -0
- package/dist/src/discord/commands.js +103 -0
- package/dist/src/discord/commands.js.map +1 -0
- package/dist/src/discord/discord-file.js +43 -0
- package/dist/src/discord/discord-file.js.map +1 -0
- package/dist/src/discord/forwarder.js +45 -0
- package/dist/src/discord/forwarder.js.map +1 -0
- package/dist/src/memory/bootstrap.js +341 -0
- package/dist/src/memory/bootstrap.js.map +1 -0
- package/dist/src/memory/heartbeat.js +11 -22
- package/dist/src/memory/heartbeat.js.map +1 -1
- package/dist/src/memory/indexing.js +329 -0
- package/dist/src/memory/indexing.js.map +1 -0
- package/dist/src/memory/keyword-expand.js +247 -0
- package/dist/src/memory/keyword-expand.js.map +1 -0
- package/dist/src/memory/runtime.js +56 -1090
- package/dist/src/memory/runtime.js.map +1 -1
- package/dist/src/memory/shared.js +167 -0
- package/dist/src/memory/shared.js.map +1 -0
- package/dist/src/messaging/runtime.js +122 -0
- package/dist/src/messaging/runtime.js.map +1 -0
- package/dist/src/messaging/send.js +120 -0
- package/dist/src/messaging/send.js.map +1 -0
- package/dist/src/messaging/session-key.js +25 -0
- package/dist/src/messaging/session-key.js.map +1 -0
- package/dist/src/messaging/types.js +6 -0
- package/dist/src/messaging/types.js.map +1 -0
- package/dist/src/orchestrator/collect.js +5 -0
- package/dist/src/orchestrator/collect.js.map +1 -1
- package/dist/src/orchestrator/distribute.js +34 -8
- package/dist/src/orchestrator/distribute.js.map +1 -1
- package/dist/src/orchestrator/gateway.js +18 -12
- package/dist/src/orchestrator/gateway.js.map +1 -1
- package/dist/src/orchestrator/parser.js +0 -28
- package/dist/src/orchestrator/parser.js.map +1 -1
- package/dist/src/orchestrator/pipeline.js +94 -75
- package/dist/src/orchestrator/pipeline.js.map +1 -1
- package/dist/src/orchestrator/state-machine.js +23 -20
- package/dist/src/orchestrator/state-machine.js.map +1 -1
- package/dist/src/orchestrator/worker-monitor.js +50 -0
- package/dist/src/orchestrator/worker-monitor.js.map +1 -0
- package/dist/src/orchestrator/worker-registry.js +107 -0
- package/dist/src/orchestrator/worker-registry.js.map +1 -0
- package/dist/src/prompt/builder.js +78 -6
- package/dist/src/prompt/builder.js.map +1 -1
- package/dist/src/prompt/templates/a1-system.md +52 -10
- package/dist/src/prompt/templates/employee.md +17 -5
- package/dist/src/prompt/templates/orchestration.md +11 -10
- package/dist/src/prompt/templates/research-worker.md +1 -1
- package/dist/src/prompt/templates/worker-context.md +4 -4
- package/dist/src/routes/browser.js +14 -3
- package/dist/src/routes/browser.js.map +1 -1
- package/dist/src/telegram/bot.js +92 -8
- package/dist/src/telegram/bot.js.map +1 -1
- package/dist/src/types/agent.js +4 -0
- package/dist/src/types/agent.js.map +1 -0
- package/package.json +27 -15
- package/public/css/chat.css +365 -127
- package/public/css/layout.css +67 -10
- package/public/css/markdown.css +219 -54
- package/public/css/modals.css +35 -15
- package/public/css/orc-state.css +16 -16
- package/public/css/sidebar.css +12 -12
- package/public/css/tool-ui.css +483 -0
- package/public/css/variables.css +334 -6
- package/public/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/public/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/public/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/public/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/public/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/public/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/public/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/public/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/public/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/public/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/public/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/public/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/public/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/public/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/public/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/public/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/public/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/public/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/public/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/public/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/public/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/public/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/public/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/public/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/public/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/public/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/public/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/public/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/public/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/public/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/public/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/public/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/public/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/public/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/public/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/public/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/public/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/public/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/public/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/public/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/public/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/public/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/public/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/public/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/public/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/public/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/public/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/public/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/public/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/public/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/public/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/public/dist/assets/api-B8XKQ4OT.js +1 -0
- package/public/dist/assets/api-BlPw3bUI.js +1 -0
- package/public/dist/assets/architecture-YZFGNWBL-BkS7SZQi.js +1 -0
- package/public/dist/assets/architectureDiagram-Q4EWVU46-Dl3iBKeR.js +1 -0
- package/public/dist/assets/blockDiagram-DXYQGD6D-DPr4D17p.js +1 -0
- package/public/dist/assets/c4Diagram-AHTNJAMY-CfoxJtDk.js +1 -0
- package/public/dist/assets/classDiagram-6PBFFD2Q-BOAdHnnB.js +1 -0
- package/public/dist/assets/classDiagram-v2-HSJHXN6E-B2QCJXWC.js +1 -0
- package/public/dist/assets/constants-DshMUJbo.js +1 -0
- package/public/dist/assets/cose-bilkent-S5V4N54A-CA14jk7w.js +1 -0
- package/public/dist/assets/dagre-KV5264BT-BVwNaSwC.js +1 -0
- package/public/dist/assets/diagram-5BDNPKRD-CHqIAvdc.js +1 -0
- package/public/dist/assets/diagram-G4DWMVQ6-DxvsCvTP.js +1 -0
- package/public/dist/assets/diagram-MMDJMWI5-DqOPO7dl.js +1 -0
- package/public/dist/assets/diagram-TYMM5635-C9xMWPQn.js +1 -0
- package/public/dist/assets/employees-CFRlsbHm.js +39 -0
- package/public/dist/assets/erDiagram-SMLLAGMA-BTmpfRkm.js +1 -0
- package/public/dist/assets/flowDiagram-DWJPFMVM-DZBSQAKA.js +1 -0
- package/public/dist/assets/ganttDiagram-T4ZO3ILL-TAEMCRbT.js +1 -0
- package/public/dist/assets/gitGraph-7Q5UKJZL-bbxndRNA.js +1 -0
- package/public/dist/assets/gitGraphDiagram-UUTBAWPF-CBxtx0MB.js +1 -0
- package/public/dist/assets/icon-192-CwXPIYF5.png +0 -0
- package/public/dist/assets/index-1Gg-6jeC.css +1 -0
- package/public/dist/assets/index-CQHqXjrK.js +49 -0
- package/public/dist/assets/info-OMHHGYJF-DRXq_Ywr.js +1 -0
- package/public/dist/assets/infoDiagram-42DDH7IO-C7FFwX4m.js +1 -0
- package/public/dist/assets/ishikawaDiagram-UXIWVN3A-DEZJE79j.js +1 -0
- package/public/dist/assets/journeyDiagram-VCZTEJTY-ZHLiY6GV.js +1 -0
- package/public/dist/assets/kanban-definition-6JOO6SKY-NP7pY7ML.js +1 -0
- package/public/dist/assets/katex-DZLS_HFU.js +1 -0
- package/public/dist/assets/locale-BjoAcbis.js +1 -0
- package/public/dist/assets/manifest-Bw-LRm-c.json +20 -0
- package/public/dist/assets/mermaid.core-CHuluSlD.js +1 -0
- package/public/dist/assets/mindmap-definition-QFDTVHPH-Bd1OgfN_.js +1 -0
- package/public/dist/assets/packet-4T2RLAQJ-CGu8ST97.js +1 -0
- package/public/dist/assets/pie-ZZUOXDRM-CDG65mhS.js +1 -0
- package/public/dist/assets/pieDiagram-DEJITSTG-BbMBHLDM.js +1 -0
- package/public/dist/assets/quadrantDiagram-34T5L4WZ-CDCDgI1e.js +1 -0
- package/public/dist/assets/radar-PYXPWWZC-1gS-6ylu.js +1 -0
- package/public/dist/assets/render-YHvL5VM_.js +6 -0
- package/public/dist/assets/requirementDiagram-MS252O5E-DkmvOtYz.js +1 -0
- package/public/dist/assets/rolldown-runtime-FhOqtrmT.js +1 -0
- package/public/dist/assets/sankeyDiagram-XADWPNL6-GNcXIYsL.js +1 -0
- package/public/dist/assets/sequenceDiagram-FGHM5R23-BFrw2n6x.js +1 -0
- package/public/dist/assets/settings-BQF_u5px.js +37 -0
- package/public/dist/assets/settings-C5Q9IPjJ.js +1 -0
- package/public/dist/assets/shark-sprite-B3AAuERd.png +0 -0
- package/public/dist/assets/skills-9Pd2rOw-.js +1 -0
- package/public/dist/assets/skills-BI7sQAdk.js +12 -0
- package/public/dist/assets/slash-commands-DMsE88bu.js +14 -0
- package/public/dist/assets/slash-commands-FMpJzlDB.js +1 -0
- package/public/dist/assets/state-O6NVkWcL.js +1 -0
- package/public/dist/assets/stateDiagram-FHFEXIEX-BLgKnllT.js +1 -0
- package/public/dist/assets/stateDiagram-v2-QKLJ7IA2-CbzuWsSa.js +1 -0
- package/public/dist/assets/timeline-definition-GMOUNBTQ-CcZTJ3gL.js +1 -0
- package/public/dist/assets/treeView-SZITEDCU-BDqBsaH1.js +1 -0
- package/public/dist/assets/treemap-W4RFUUIX-BaWHA3Di.js +1 -0
- package/public/dist/assets/ui-BukgLHuh.js +29 -0
- package/public/dist/assets/ui-Bvz1JfTE.js +1 -0
- package/public/dist/assets/vendor-mermaid-COidH9HB.js +2934 -0
- package/public/dist/assets/vendor-render-Bjnw0wQ6.css +1 -0
- package/public/dist/assets/vendor-render-D2YP6GiF.js +322 -0
- package/public/dist/assets/vennDiagram-DHZGUBPP-BWV_j1bh.js +1 -0
- package/public/dist/assets/wardley-RL74JXVD-C7gKA3d7.js +1 -0
- package/public/dist/assets/wardleyDiagram-NUSXRM2D-BUoq_wug.js +1 -0
- package/public/dist/assets/ws-S_AZgx7L.js +2 -0
- package/public/dist/assets/xychartDiagram-5P7HB3ND-PvT5Ec82.js +1 -0
- package/public/dist/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/public/dist/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/public/dist/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/public/dist/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/public/dist/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/public/dist/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/public/dist/dist/assets/api-B8XKQ4OT.js +1 -0
- package/public/dist/dist/assets/api-BlPw3bUI.js +1 -0
- package/public/dist/dist/assets/architecture-YZFGNWBL-BkS7SZQi.js +1 -0
- package/public/dist/dist/assets/architectureDiagram-Q4EWVU46-Dl3iBKeR.js +1 -0
- package/public/dist/dist/assets/blockDiagram-DXYQGD6D-DPr4D17p.js +1 -0
- package/public/dist/dist/assets/c4Diagram-AHTNJAMY-CfoxJtDk.js +1 -0
- package/public/dist/dist/assets/classDiagram-6PBFFD2Q-BOAdHnnB.js +1 -0
- package/public/dist/dist/assets/classDiagram-v2-HSJHXN6E-B2QCJXWC.js +1 -0
- package/public/dist/dist/assets/constants-DshMUJbo.js +1 -0
- package/public/dist/dist/assets/cose-bilkent-S5V4N54A-CA14jk7w.js +1 -0
- package/public/dist/dist/assets/dagre-KV5264BT-BVwNaSwC.js +1 -0
- package/public/dist/dist/assets/diagram-5BDNPKRD-CHqIAvdc.js +1 -0
- package/public/dist/dist/assets/diagram-G4DWMVQ6-DxvsCvTP.js +1 -0
- package/public/dist/dist/assets/diagram-MMDJMWI5-DqOPO7dl.js +1 -0
- package/public/dist/dist/assets/diagram-TYMM5635-C9xMWPQn.js +1 -0
- package/public/dist/dist/assets/employees-CFRlsbHm.js +39 -0
- package/public/dist/dist/assets/erDiagram-SMLLAGMA-BTmpfRkm.js +1 -0
- package/public/dist/dist/assets/flowDiagram-DWJPFMVM-DZBSQAKA.js +1 -0
- package/public/dist/dist/assets/ganttDiagram-T4ZO3ILL-TAEMCRbT.js +1 -0
- package/public/dist/dist/assets/gitGraph-7Q5UKJZL-bbxndRNA.js +1 -0
- package/public/dist/dist/assets/gitGraphDiagram-UUTBAWPF-CBxtx0MB.js +1 -0
- package/public/dist/dist/assets/icon-192-CwXPIYF5.png +0 -0
- package/public/dist/dist/assets/index-1Gg-6jeC.css +1 -0
- package/public/dist/dist/assets/index-CQHqXjrK.js +49 -0
- package/public/dist/dist/assets/info-OMHHGYJF-DRXq_Ywr.js +1 -0
- package/public/dist/dist/assets/infoDiagram-42DDH7IO-C7FFwX4m.js +1 -0
- package/public/dist/dist/assets/ishikawaDiagram-UXIWVN3A-DEZJE79j.js +1 -0
- package/public/dist/dist/assets/journeyDiagram-VCZTEJTY-ZHLiY6GV.js +1 -0
- package/public/dist/dist/assets/kanban-definition-6JOO6SKY-NP7pY7ML.js +1 -0
- package/public/dist/dist/assets/katex-DZLS_HFU.js +1 -0
- package/public/dist/dist/assets/locale-BjoAcbis.js +1 -0
- package/public/dist/dist/assets/manifest-Bw-LRm-c.json +20 -0
- package/public/dist/dist/assets/mermaid.core-CHuluSlD.js +1 -0
- package/public/dist/dist/assets/mindmap-definition-QFDTVHPH-Bd1OgfN_.js +1 -0
- package/public/dist/dist/assets/packet-4T2RLAQJ-CGu8ST97.js +1 -0
- package/public/dist/dist/assets/pie-ZZUOXDRM-CDG65mhS.js +1 -0
- package/public/dist/dist/assets/pieDiagram-DEJITSTG-BbMBHLDM.js +1 -0
- package/public/dist/dist/assets/quadrantDiagram-34T5L4WZ-CDCDgI1e.js +1 -0
- package/public/dist/dist/assets/radar-PYXPWWZC-1gS-6ylu.js +1 -0
- package/public/dist/dist/assets/render-YHvL5VM_.js +6 -0
- package/public/dist/dist/assets/requirementDiagram-MS252O5E-DkmvOtYz.js +1 -0
- package/public/dist/dist/assets/rolldown-runtime-FhOqtrmT.js +1 -0
- package/public/dist/dist/assets/sankeyDiagram-XADWPNL6-GNcXIYsL.js +1 -0
- package/public/dist/dist/assets/sequenceDiagram-FGHM5R23-BFrw2n6x.js +1 -0
- package/public/dist/dist/assets/settings-BQF_u5px.js +37 -0
- package/public/dist/dist/assets/settings-C5Q9IPjJ.js +1 -0
- package/public/dist/dist/assets/shark-sprite-B3AAuERd.png +0 -0
- package/public/dist/dist/assets/skills-9Pd2rOw-.js +1 -0
- package/public/dist/dist/assets/skills-BI7sQAdk.js +12 -0
- package/public/dist/dist/assets/slash-commands-DMsE88bu.js +14 -0
- package/public/dist/dist/assets/slash-commands-FMpJzlDB.js +1 -0
- package/public/dist/dist/assets/state-O6NVkWcL.js +1 -0
- package/public/dist/dist/assets/stateDiagram-FHFEXIEX-BLgKnllT.js +1 -0
- package/public/dist/dist/assets/stateDiagram-v2-QKLJ7IA2-CbzuWsSa.js +1 -0
- package/public/dist/dist/assets/timeline-definition-GMOUNBTQ-CcZTJ3gL.js +1 -0
- package/public/dist/dist/assets/treeView-SZITEDCU-BDqBsaH1.js +1 -0
- package/public/dist/dist/assets/treemap-W4RFUUIX-BaWHA3Di.js +1 -0
- package/public/dist/dist/assets/ui-BukgLHuh.js +29 -0
- package/public/dist/dist/assets/ui-Bvz1JfTE.js +1 -0
- package/public/dist/dist/assets/vendor-mermaid-COidH9HB.js +2934 -0
- package/public/dist/dist/assets/vendor-render-Bjnw0wQ6.css +1 -0
- package/public/dist/dist/assets/vendor-render-D2YP6GiF.js +322 -0
- package/public/dist/dist/assets/vennDiagram-DHZGUBPP-BWV_j1bh.js +1 -0
- package/public/dist/dist/assets/wardley-RL74JXVD-C7gKA3d7.js +1 -0
- package/public/dist/dist/assets/wardleyDiagram-NUSXRM2D-BUoq_wug.js +1 -0
- package/public/dist/dist/assets/ws-S_AZgx7L.js +2 -0
- package/public/dist/dist/assets/xychartDiagram-5P7HB3ND-PvT5Ec82.js +1 -0
- package/public/dist/dist/index.html +708 -0
- package/public/dist/index.html +708 -0
- package/public/icons/icon-192.png +0 -0
- package/public/icons/icon-512-maskable.png +0 -0
- package/public/icons/icon-512.png +0 -0
- package/public/index.html +178 -125
- package/public/js/constants.ts +6 -6
- package/public/js/features/chat.ts +23 -3
- package/public/js/features/employees.ts +12 -12
- package/public/js/features/gesture.ts +61 -0
- package/public/js/features/heartbeat.ts +1 -1
- package/public/js/features/idb-cache.ts +89 -0
- package/public/js/features/memory.ts +4 -1
- package/public/js/features/process-block.ts +236 -0
- package/public/js/features/settings-channel.ts +53 -0
- package/public/js/features/settings-cli-status.ts +164 -0
- package/public/js/features/settings-core.ts +357 -0
- package/public/js/features/settings-discord.ts +52 -0
- package/public/js/features/settings-mcp.ts +54 -0
- package/public/js/features/settings-stt.ts +78 -0
- package/public/js/features/settings-telegram.ts +40 -0
- package/public/js/features/settings-templates.ts +129 -0
- package/public/js/features/settings-types.ts +24 -0
- package/public/js/features/settings.ts +9 -815
- package/public/js/features/sidebar.ts +4 -2
- package/public/js/features/skills.ts +5 -4
- package/public/js/features/slash-commands.ts +1 -8
- package/public/js/features/theme.ts +16 -10
- package/public/js/features/tool-ui.ts +113 -0
- package/public/js/main.ts +67 -8
- package/public/js/render.ts +128 -90
- package/public/js/state.ts +4 -0
- package/public/js/streaming-render.ts +55 -0
- package/public/js/ui.ts +289 -46
- package/public/js/virtual-scroll.ts +189 -0
- package/public/js/ws.ts +175 -112
- package/public/locales/en.json +6 -1
- package/public/locales/ko.json +6 -1
- package/public/manifest.json +20 -0
- package/public/public/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/public/public/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/public/public/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/public/public/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/public/public/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/public/public/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/public/public/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/public/public/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/public/public/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/public/public/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/public/public/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/public/public/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/public/public/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/public/public/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/public/public/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/public/public/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/public/public/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/public/public/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/public/public/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/public/public/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/public/public/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/public/public/dist/assets/api-B8XKQ4OT.js +1 -0
- package/public/public/dist/assets/api-BlPw3bUI.js +1 -0
- package/public/public/dist/assets/architecture-YZFGNWBL-BkS7SZQi.js +1 -0
- package/public/public/dist/assets/architectureDiagram-Q4EWVU46-Dl3iBKeR.js +1 -0
- package/public/public/dist/assets/blockDiagram-DXYQGD6D-DPr4D17p.js +1 -0
- package/public/public/dist/assets/c4Diagram-AHTNJAMY-CfoxJtDk.js +1 -0
- package/public/public/dist/assets/classDiagram-6PBFFD2Q-BOAdHnnB.js +1 -0
- package/public/public/dist/assets/classDiagram-v2-HSJHXN6E-B2QCJXWC.js +1 -0
- package/public/public/dist/assets/constants-DshMUJbo.js +1 -0
- package/public/public/dist/assets/cose-bilkent-S5V4N54A-CA14jk7w.js +1 -0
- package/public/public/dist/assets/dagre-KV5264BT-BVwNaSwC.js +1 -0
- package/public/public/dist/assets/diagram-5BDNPKRD-CHqIAvdc.js +1 -0
- package/public/public/dist/assets/diagram-G4DWMVQ6-DxvsCvTP.js +1 -0
- package/public/public/dist/assets/diagram-MMDJMWI5-DqOPO7dl.js +1 -0
- package/public/public/dist/assets/diagram-TYMM5635-C9xMWPQn.js +1 -0
- package/public/public/dist/assets/employees-CFRlsbHm.js +39 -0
- package/public/public/dist/assets/erDiagram-SMLLAGMA-BTmpfRkm.js +1 -0
- package/public/public/dist/assets/flowDiagram-DWJPFMVM-DZBSQAKA.js +1 -0
- package/public/public/dist/assets/ganttDiagram-T4ZO3ILL-TAEMCRbT.js +1 -0
- package/public/public/dist/assets/gitGraph-7Q5UKJZL-bbxndRNA.js +1 -0
- package/public/public/dist/assets/gitGraphDiagram-UUTBAWPF-CBxtx0MB.js +1 -0
- package/public/public/dist/assets/icon-192-CwXPIYF5.png +0 -0
- package/public/public/dist/assets/index-1Gg-6jeC.css +1 -0
- package/public/public/dist/assets/index-CQHqXjrK.js +49 -0
- package/public/public/dist/assets/info-OMHHGYJF-DRXq_Ywr.js +1 -0
- package/public/public/dist/assets/infoDiagram-42DDH7IO-C7FFwX4m.js +1 -0
- package/public/public/dist/assets/ishikawaDiagram-UXIWVN3A-DEZJE79j.js +1 -0
- package/public/public/dist/assets/journeyDiagram-VCZTEJTY-ZHLiY6GV.js +1 -0
- package/public/public/dist/assets/kanban-definition-6JOO6SKY-NP7pY7ML.js +1 -0
- package/public/public/dist/assets/katex-DZLS_HFU.js +1 -0
- package/public/public/dist/assets/locale-BjoAcbis.js +1 -0
- package/public/public/dist/assets/manifest-Bw-LRm-c.json +20 -0
- package/public/public/dist/assets/mermaid.core-CHuluSlD.js +1 -0
- package/public/public/dist/assets/mindmap-definition-QFDTVHPH-Bd1OgfN_.js +1 -0
- package/public/public/dist/assets/packet-4T2RLAQJ-CGu8ST97.js +1 -0
- package/public/public/dist/assets/pie-ZZUOXDRM-CDG65mhS.js +1 -0
- package/public/public/dist/assets/pieDiagram-DEJITSTG-BbMBHLDM.js +1 -0
- package/public/public/dist/assets/quadrantDiagram-34T5L4WZ-CDCDgI1e.js +1 -0
- package/public/public/dist/assets/radar-PYXPWWZC-1gS-6ylu.js +1 -0
- package/public/public/dist/assets/render-YHvL5VM_.js +6 -0
- package/public/public/dist/assets/requirementDiagram-MS252O5E-DkmvOtYz.js +1 -0
- package/public/public/dist/assets/rolldown-runtime-FhOqtrmT.js +1 -0
- package/public/public/dist/assets/sankeyDiagram-XADWPNL6-GNcXIYsL.js +1 -0
- package/public/public/dist/assets/sequenceDiagram-FGHM5R23-BFrw2n6x.js +1 -0
- package/public/public/dist/assets/settings-BQF_u5px.js +37 -0
- package/public/public/dist/assets/settings-C5Q9IPjJ.js +1 -0
- package/public/public/dist/assets/shark-sprite-B3AAuERd.png +0 -0
- package/public/public/dist/assets/skills-9Pd2rOw-.js +1 -0
- package/public/public/dist/assets/skills-BI7sQAdk.js +12 -0
- package/public/public/dist/assets/slash-commands-DMsE88bu.js +14 -0
- package/public/public/dist/assets/slash-commands-FMpJzlDB.js +1 -0
- package/public/public/dist/assets/state-O6NVkWcL.js +1 -0
- package/public/public/dist/assets/stateDiagram-FHFEXIEX-BLgKnllT.js +1 -0
- package/public/public/dist/assets/stateDiagram-v2-QKLJ7IA2-CbzuWsSa.js +1 -0
- package/public/public/dist/assets/timeline-definition-GMOUNBTQ-CcZTJ3gL.js +1 -0
- package/public/public/dist/assets/treeView-SZITEDCU-BDqBsaH1.js +1 -0
- package/public/public/dist/assets/treemap-W4RFUUIX-BaWHA3Di.js +1 -0
- package/public/public/dist/assets/ui-BukgLHuh.js +29 -0
- package/public/public/dist/assets/ui-Bvz1JfTE.js +1 -0
- package/public/public/dist/assets/vendor-mermaid-COidH9HB.js +2934 -0
- package/public/public/dist/assets/vendor-render-Bjnw0wQ6.css +1 -0
- package/public/public/dist/assets/vendor-render-D2YP6GiF.js +322 -0
- package/public/public/dist/assets/vennDiagram-DHZGUBPP-BWV_j1bh.js +1 -0
- package/public/public/dist/assets/wardley-RL74JXVD-C7gKA3d7.js +1 -0
- package/public/public/dist/assets/wardleyDiagram-NUSXRM2D-BUoq_wug.js +1 -0
- package/public/public/dist/assets/ws-S_AZgx7L.js +2 -0
- package/public/public/dist/assets/xychartDiagram-5P7HB3ND-PvT5Ec82.js +1 -0
- package/public/public/dist/index.html +708 -0
- package/public/sw.js +104 -0
- package/scripts/install-officecli.sh +145 -0
- package/scripts/release-preview.sh +18 -10
- package/scripts/release.sh +3 -3
- package/public/dist/bundle.js +0 -151
- package/public/dist/bundle.js.map +0 -7
|
@@ -1,815 +1,9 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
interface TelegramConfig { enabled?: boolean; token?: string; allowedChatIds?: number[]; forwardAll?: boolean; }
|
|
11
|
-
interface QuotaWindow { label: string; percent: number; resetsAt?: string | number | null; }
|
|
12
|
-
interface QuotaEntry {
|
|
13
|
-
account?: { email?: string; type?: string; plan?: string; tier?: string };
|
|
14
|
-
windows?: QuotaWindow[];
|
|
15
|
-
authenticated?: boolean;
|
|
16
|
-
error?: boolean;
|
|
17
|
-
reason?: string;
|
|
18
|
-
}
|
|
19
|
-
interface SettingsData {
|
|
20
|
-
cli: string; workingDir: string; permissions: string; locale?: string;
|
|
21
|
-
perCli?: Record<string, PerCliConfig>;
|
|
22
|
-
activeOverrides?: Record<string, PerCliConfig>;
|
|
23
|
-
telegram?: TelegramConfig;
|
|
24
|
-
fallbackOrder?: string[];
|
|
25
|
-
memory?: { cli?: string };
|
|
26
|
-
stt?: { engine?: string; geminiKeySet?: boolean; geminiKeyLast4?: string; geminiModel?: string; whisperModel?: string; openaiKeySet?: boolean; openaiKeyLast4?: string };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function toCap(cli: string): string {
|
|
30
|
-
return cli.charAt(0).toUpperCase() + cli.slice(1);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function getModelSelect(cli: string): HTMLSelectElement | null {
|
|
34
|
-
return document.getElementById('model' + toCap(cli)) as HTMLSelectElement | null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function getCustomModelInput(cli: string): HTMLInputElement | null {
|
|
38
|
-
return document.getElementById('customModel' + toCap(cli)) as HTMLInputElement | null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function getEffortSelect(cli: string): HTMLSelectElement | null {
|
|
42
|
-
return document.getElementById('effort' + toCap(cli)) as HTMLSelectElement | null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function setSelectOptions(selectEl: HTMLSelectElement | null, values: string[], { includeCustom = false, includeDefault = false, selected = '' } = {}): void {
|
|
46
|
-
if (!selectEl) return;
|
|
47
|
-
const defaultHtml = includeDefault ? '<option value="default">default</option>' : '';
|
|
48
|
-
const customHtml = includeCustom ? `<option value="__custom__">${t('model.customOption')}</option>` : '';
|
|
49
|
-
const opts = (values || []).map(v => `<option value="${escapeHtml(v)}">${escapeHtml(v)}</option>`).join('');
|
|
50
|
-
selectEl.innerHTML = defaultHtml + opts + customHtml;
|
|
51
|
-
|
|
52
|
-
if (selected && Array.from(selectEl.options).some(o => o.value === selected)) {
|
|
53
|
-
selectEl.value = selected;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function appendCustomOption(selectEl: HTMLSelectElement | null, value: string): void {
|
|
58
|
-
if (!selectEl || !value) return;
|
|
59
|
-
if (Array.from(selectEl.options).some(o => o.value === value)) return;
|
|
60
|
-
const opt = document.createElement('option');
|
|
61
|
-
opt.value = value;
|
|
62
|
-
opt.textContent = value;
|
|
63
|
-
const customOpt = selectEl.querySelector('option[value="__custom__"]');
|
|
64
|
-
if (customOpt) selectEl.insertBefore(opt, customOpt);
|
|
65
|
-
else selectEl.appendChild(opt);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function syncCliOptionSelects(settings: SettingsData | null = null): void {
|
|
69
|
-
const cliKeys = getCliKeys();
|
|
70
|
-
|
|
71
|
-
const selCli = document.getElementById('selCli') as HTMLSelectElement | null;
|
|
72
|
-
if (selCli) {
|
|
73
|
-
const current = settings?.cli || selCli.value || cliKeys[0] || 'claude';
|
|
74
|
-
selCli.innerHTML = cliKeys.map(cli => {
|
|
75
|
-
const label = getCliMeta(cli)?.label || cli;
|
|
76
|
-
return `<option value="${escapeHtml(cli)}">${escapeHtml(label)}</option>`;
|
|
77
|
-
}).join('');
|
|
78
|
-
if (Array.from(selCli.options).some(o => o.value === current)) selCli.value = current;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const memCli = document.getElementById('memCli') as HTMLSelectElement | null;
|
|
82
|
-
if (memCli) {
|
|
83
|
-
const current = settings?.memory?.cli || memCli.value || '';
|
|
84
|
-
memCli.innerHTML = '<option value="">(active CLI)</option>' +
|
|
85
|
-
cliKeys.map(cli => `<option value="${escapeHtml(cli)}">${escapeHtml(cli)}</option>`).join('');
|
|
86
|
-
if (Array.from(memCli.options).some(o => o.value === current)) memCli.value = current;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function syncPerCliModelAndEffortControls(settings: SettingsData | null = null): void {
|
|
91
|
-
for (const cli of getCliKeys()) {
|
|
92
|
-
const modelSel = getModelSelect(cli);
|
|
93
|
-
if (modelSel) {
|
|
94
|
-
const selected = settings?.perCli?.[cli]?.model || modelSel.value || '';
|
|
95
|
-
setSelectOptions(modelSel, MODEL_MAP[cli] || [], { includeCustom: true, selected });
|
|
96
|
-
if (selected && !Array.from(modelSel.options).some(o => o.value === selected)) {
|
|
97
|
-
appendCustomOption(modelSel, selected);
|
|
98
|
-
modelSel.value = selected;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const effortSel = getEffortSelect(cli);
|
|
103
|
-
if (effortSel) {
|
|
104
|
-
const meta = getCliMeta(cli);
|
|
105
|
-
const options = [''].concat(meta?.efforts || []);
|
|
106
|
-
const selected = settings?.perCli?.[cli]?.effort || effortSel.value || '';
|
|
107
|
-
const unique = [...new Set(options)];
|
|
108
|
-
const noneLabel = (meta?.efforts?.length === 0 && meta?.effortNote) ? meta.effortNote : '— none';
|
|
109
|
-
effortSel.innerHTML = unique.map(v => {
|
|
110
|
-
if (!v) return `<option value="">${escapeHtml(noneLabel)}</option>`;
|
|
111
|
-
return `<option value="${escapeHtml(v)}">${escapeHtml(v)}</option>`;
|
|
112
|
-
}).join('');
|
|
113
|
-
if (meta?.effortNote) effortSel.title = meta.effortNote;
|
|
114
|
-
effortSel.disabled = (meta?.efforts?.length === 0 && !!meta?.effortNote);
|
|
115
|
-
if (Array.from(effortSel.options).some(o => o.value === selected)) effortSel.value = selected;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function syncActiveEffortOptions(cli: string, selected = ''): void {
|
|
121
|
-
const selEffort = document.getElementById('selEffort') as HTMLSelectElement | null;
|
|
122
|
-
if (!selEffort) return;
|
|
123
|
-
const meta = getCliMeta(cli);
|
|
124
|
-
if (meta?.effortNote) {
|
|
125
|
-
// Effort managed externally (e.g. Copilot config.json) — show hint, disable
|
|
126
|
-
selEffort.innerHTML = `<option value="">${escapeHtml(meta.effortNote)}</option>`;
|
|
127
|
-
selEffort.title = meta.effortNote;
|
|
128
|
-
selEffort.disabled = true;
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const efforts = [''].concat(meta?.efforts || []);
|
|
132
|
-
const unique = [...new Set(efforts)];
|
|
133
|
-
selEffort.innerHTML = unique.map(v => {
|
|
134
|
-
if (!v) return '<option value="">— none</option>';
|
|
135
|
-
return `<option value="${escapeHtml(v)}">${escapeHtml(v)}</option>`;
|
|
136
|
-
}).join('');
|
|
137
|
-
selEffort.disabled = false;
|
|
138
|
-
selEffort.title = '';
|
|
139
|
-
if (Array.from(selEffort.options).some(o => o.value === selected)) selEffort.value = selected;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export async function loadSettings(): Promise<void> {
|
|
143
|
-
await loadCliRegistry();
|
|
144
|
-
const s = await api<SettingsData>('/api/settings');
|
|
145
|
-
if (!s) return;
|
|
146
|
-
syncStoredLocale(s.locale ?? '');
|
|
147
|
-
syncCliOptionSelects(s);
|
|
148
|
-
syncPerCliModelAndEffortControls(s);
|
|
149
|
-
|
|
150
|
-
const selCli = document.getElementById('selCli') as HTMLSelectElement | null;
|
|
151
|
-
if (selCli && Array.from(selCli.options).some(o => o.value === s.cli)) {
|
|
152
|
-
selCli.value = s.cli;
|
|
153
|
-
}
|
|
154
|
-
const cwdEl = document.getElementById('inpCwd');
|
|
155
|
-
if (cwdEl) cwdEl.textContent = s.workingDir;
|
|
156
|
-
const headerEl = document.getElementById('headerCli');
|
|
157
|
-
if (headerEl) headerEl.textContent = s.cli;
|
|
158
|
-
setPerm(s.permissions, false);
|
|
159
|
-
|
|
160
|
-
if (s.perCli) {
|
|
161
|
-
for (const [cli, cfg] of Object.entries(s.perCli) as [string, PerCliConfig][]) {
|
|
162
|
-
const modelEl = getModelSelect(cli);
|
|
163
|
-
const effortEl = getEffortSelect(cli);
|
|
164
|
-
if (modelEl && cfg.model) {
|
|
165
|
-
appendCustomOption(modelEl, cfg.model);
|
|
166
|
-
modelEl.value = cfg.model;
|
|
167
|
-
}
|
|
168
|
-
if (effortEl) effortEl.value = cfg.effort || '';
|
|
169
|
-
// Restore Codex fast mode toggle
|
|
170
|
-
if (cli === 'codex' && cfg.fastMode !== undefined) {
|
|
171
|
-
document.getElementById('codexFastOn')?.classList.toggle('active', cfg.fastMode);
|
|
172
|
-
document.getElementById('codexFastOff')?.classList.toggle('active', !cfg.fastMode);
|
|
173
|
-
}
|
|
174
|
-
// Restore Codex context window toggle + values
|
|
175
|
-
if (cli === 'codex') {
|
|
176
|
-
const ctxOn = !!cfg.contextWindow;
|
|
177
|
-
document.getElementById('codexCtxOn')?.classList.toggle('active', ctxOn);
|
|
178
|
-
document.getElementById('codexCtxOff')?.classList.toggle('active', !ctxOn);
|
|
179
|
-
const valDiv = document.getElementById('codexCtxValues');
|
|
180
|
-
if (valDiv) valDiv.style.display = ctxOn ? '' : 'none';
|
|
181
|
-
const winInput = document.getElementById('codexCtxWindow') as HTMLInputElement | null;
|
|
182
|
-
const compInput = document.getElementById('codexCtxCompact') as HTMLInputElement | null;
|
|
183
|
-
if (winInput && cfg.contextWindowSize) winInput.value = String(cfg.contextWindowSize);
|
|
184
|
-
if (compInput && cfg.contextCompactLimit) compInput.value = String(cfg.contextCompactLimit);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
onCliChange(false);
|
|
190
|
-
const ao = s.activeOverrides?.[s.cli] || {};
|
|
191
|
-
const pc = s.perCli?.[s.cli] || {};
|
|
192
|
-
const activeModel = ao.model || pc.model;
|
|
193
|
-
const activeEffort = ao.effort || pc.effort || '';
|
|
194
|
-
const selModel = document.getElementById('selModel') as HTMLSelectElement | null;
|
|
195
|
-
if (activeModel && selModel) selModel.value = activeModel;
|
|
196
|
-
syncActiveEffortOptions(s.cli, activeEffort);
|
|
197
|
-
|
|
198
|
-
loadTelegramSettings(s);
|
|
199
|
-
loadFallbackOrder(s);
|
|
200
|
-
loadMcpServers();
|
|
201
|
-
initSttSettings(s.stt || {});
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// ── STT Settings ──
|
|
205
|
-
function initSttSettings(sttConfig: Record<string, any>): void {
|
|
206
|
-
const engine = document.getElementById('sttEngine') as HTMLSelectElement | null;
|
|
207
|
-
const geminiKey = document.getElementById('sttGeminiKey') as HTMLInputElement | null;
|
|
208
|
-
const geminiModel = document.getElementById('sttGeminiModel') as HTMLSelectElement | null;
|
|
209
|
-
const geminiModelCustom = document.getElementById('sttGeminiModelCustom') as HTMLInputElement | null;
|
|
210
|
-
const whisperModel = document.getElementById('sttWhisperModel') as HTMLInputElement | null;
|
|
211
|
-
const openaiBaseUrl = document.getElementById('sttOpenaiBaseUrl') as HTMLInputElement | null;
|
|
212
|
-
const openaiKey = document.getElementById('sttOpenaiKey') as HTMLInputElement | null;
|
|
213
|
-
const openaiModel = document.getElementById('sttOpenaiModel') as HTMLInputElement | null;
|
|
214
|
-
const vertexJson = document.getElementById('sttVertexJson') as HTMLTextAreaElement | null;
|
|
215
|
-
|
|
216
|
-
if (engine) engine.value = sttConfig.engine || 'auto';
|
|
217
|
-
if (geminiKey) geminiKey.placeholder = sttConfig.geminiKeySet ? `✅ 입력됨 ····${sttConfig.geminiKeyLast4 || ''}` : 'AIza...';
|
|
218
|
-
if (geminiModel) {
|
|
219
|
-
const saved = sttConfig.geminiModel || 'gemini-2.5-flash-lite';
|
|
220
|
-
const hasOption = Array.from(geminiModel.options).some(o => o.value === saved);
|
|
221
|
-
if (hasOption) { geminiModel.value = saved; }
|
|
222
|
-
else { geminiModel.value = '__custom__'; if (geminiModelCustom) { geminiModelCustom.value = saved; geminiModelCustom.style.display = ''; } }
|
|
223
|
-
}
|
|
224
|
-
if (whisperModel) whisperModel.value = sttConfig.whisperModel || 'mlx-community/whisper-large-v3-turbo';
|
|
225
|
-
if (openaiBaseUrl) openaiBaseUrl.value = sttConfig.openaiBaseUrl || '';
|
|
226
|
-
if (openaiKey) openaiKey.placeholder = sttConfig.openaiKeySet ? `✅ 입력됨 ····${sttConfig.openaiKeyLast4 || ''}` : 'sk-...';
|
|
227
|
-
if (openaiModel) openaiModel.value = sttConfig.openaiModel || '';
|
|
228
|
-
if (vertexJson) vertexJson.value = sttConfig.vertexConfig || '';
|
|
229
|
-
|
|
230
|
-
function toggleProviderFields() {
|
|
231
|
-
const v = engine?.value || 'auto';
|
|
232
|
-
const showGemini = v === 'auto' || v === 'gemini';
|
|
233
|
-
const showOpenai = v === 'openai';
|
|
234
|
-
const showVertex = v === 'vertex';
|
|
235
|
-
const showWhisper = v === 'auto' || v === 'whisper';
|
|
236
|
-
document.querySelectorAll('.stt-gemini').forEach(el => (el as HTMLElement).style.display = showGemini ? '' : 'none');
|
|
237
|
-
document.querySelectorAll('.stt-openai').forEach(el => (el as HTMLElement).style.display = showOpenai ? '' : 'none');
|
|
238
|
-
document.querySelectorAll('.stt-vertex').forEach(el => (el as HTMLElement).style.display = showVertex ? '' : 'none');
|
|
239
|
-
document.querySelectorAll('.stt-whisper').forEach(el => (el as HTMLElement).style.display = showWhisper ? '' : 'none');
|
|
240
|
-
}
|
|
241
|
-
toggleProviderFields();
|
|
242
|
-
|
|
243
|
-
async function saveStt() {
|
|
244
|
-
const patch: Record<string, any> = {
|
|
245
|
-
stt: {
|
|
246
|
-
engine: engine?.value || 'auto',
|
|
247
|
-
geminiModel: (geminiModel?.value === '__custom__' ? geminiModelCustom?.value : geminiModel?.value) || 'gemini-2.5-flash-lite',
|
|
248
|
-
whisperModel: whisperModel?.value || '',
|
|
249
|
-
openaiBaseUrl: openaiBaseUrl?.value || '',
|
|
250
|
-
openaiModel: openaiModel?.value || '',
|
|
251
|
-
vertexConfig: vertexJson?.value || '',
|
|
252
|
-
},
|
|
253
|
-
};
|
|
254
|
-
if (geminiKey?.value) patch.stt.geminiApiKey = geminiKey.value;
|
|
255
|
-
if (openaiKey?.value) patch.stt.openaiApiKey = openaiKey.value;
|
|
256
|
-
console.log('[stt] saving:', { engine: patch.stt.engine, hasGeminiKey: !!patch.stt.geminiApiKey, hasOpenaiKey: !!patch.stt.openaiApiKey });
|
|
257
|
-
try {
|
|
258
|
-
await apiJson('/api/settings', 'PUT', patch);
|
|
259
|
-
if (geminiKey?.value) { const l4 = geminiKey.value.slice(-4); geminiKey.value = ''; geminiKey.placeholder = `✅ 입력됨 ····${l4}`; }
|
|
260
|
-
if (openaiKey?.value) { const l4 = openaiKey.value.slice(-4); openaiKey.value = ''; openaiKey.placeholder = `✅ 입력됨 ····${l4}`; }
|
|
261
|
-
} catch (e) {
|
|
262
|
-
console.error('[stt] save failed:', e);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Auto-save on change (selects) and blur (text/password inputs)
|
|
267
|
-
engine?.addEventListener('change', () => { toggleProviderFields(); saveStt(); });
|
|
268
|
-
geminiModel?.addEventListener('change', () => {
|
|
269
|
-
if (geminiModelCustom) geminiModelCustom.style.display = geminiModel.value === '__custom__' ? '' : 'none';
|
|
270
|
-
if (geminiModel.value !== '__custom__') saveStt();
|
|
271
|
-
});
|
|
272
|
-
geminiModelCustom?.addEventListener('blur', saveStt);
|
|
273
|
-
geminiKey?.addEventListener('blur', () => { if (geminiKey.value) saveStt(); });
|
|
274
|
-
openaiKey?.addEventListener('blur', () => { if (openaiKey.value) saveStt(); });
|
|
275
|
-
openaiBaseUrl?.addEventListener('blur', saveStt);
|
|
276
|
-
openaiModel?.addEventListener('blur', saveStt);
|
|
277
|
-
whisperModel?.addEventListener('blur', saveStt);
|
|
278
|
-
vertexJson?.addEventListener('blur', saveStt);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
interface McpData { servers: Record<string, { command: string; args?: string[] }>; }
|
|
282
|
-
interface McpSyncResult { results: Record<string, boolean>; }
|
|
283
|
-
interface McpInstallEntry { status: string; bin?: string; }
|
|
284
|
-
interface McpInstallResult { results: Record<string, McpInstallEntry>; }
|
|
285
|
-
|
|
286
|
-
export async function loadMcpServers(): Promise<void> {
|
|
287
|
-
try {
|
|
288
|
-
const d = await api<McpData>('/api/mcp');
|
|
289
|
-
if (!d) return;
|
|
290
|
-
const el = document.getElementById('mcpServerList');
|
|
291
|
-
if (!el) return;
|
|
292
|
-
const names = Object.entries(d.servers || {});
|
|
293
|
-
if (!names.length) { el.textContent = t('mcp.noServers'); return; }
|
|
294
|
-
el.innerHTML = names.map(([n, s]) =>
|
|
295
|
-
`<div style="padding:2px 0">• <b>${n}</b> <span style="opacity:.6">${s.command} ${(s.args || []).slice(0, 2).join(' ')}</span></div>`
|
|
296
|
-
).join('');
|
|
297
|
-
} catch { }
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
export async function syncMcpServers(): Promise<void> {
|
|
301
|
-
const resultEl = document.getElementById('mcpSyncResult');
|
|
302
|
-
if (!resultEl) return;
|
|
303
|
-
resultEl.style.display = 'block';
|
|
304
|
-
resultEl.textContent = t('mcp.syncing');
|
|
305
|
-
try {
|
|
306
|
-
const d = await apiJson('/api/mcp/sync', 'POST', {}) as McpSyncResult | null;
|
|
307
|
-
if (!d) { resultEl.textContent = '❌ sync failed'; return; }
|
|
308
|
-
const r = d.results || {};
|
|
309
|
-
resultEl.innerHTML = Object.entries(r).map(([k, v]) =>
|
|
310
|
-
`${v ? '✅' : '⏭️'} ${k}`
|
|
311
|
-
).join(' ');
|
|
312
|
-
} catch (e) { resultEl.textContent = '❌ ' + (e as Error).message; }
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
export async function installMcpGlobal(): Promise<void> {
|
|
316
|
-
const resultEl = document.getElementById('mcpSyncResult');
|
|
317
|
-
if (!resultEl) return;
|
|
318
|
-
resultEl.style.display = 'block';
|
|
319
|
-
resultEl.textContent = t('mcp.installing');
|
|
320
|
-
try {
|
|
321
|
-
const d = await apiJson('/api/mcp/install', 'POST', {}) as McpInstallResult | null;
|
|
322
|
-
if (!d) { resultEl.textContent = '❌ install failed'; return; }
|
|
323
|
-
resultEl.innerHTML = Object.entries(d.results || {}).map(([k, v]) => {
|
|
324
|
-
const icon = v.status === 'installed' ? '✅' : v.status === 'skip' ? '⏭️' : '❌';
|
|
325
|
-
return `${icon} <b>${k}</b>: ${v.status}${v.bin ? ' → ' + v.bin : ''}`;
|
|
326
|
-
}).join('<br>');
|
|
327
|
-
loadMcpServers();
|
|
328
|
-
} catch (e) { resultEl.textContent = '❌ ' + (e as Error).message; }
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
export async function updateSettings(): Promise<void> {
|
|
332
|
-
const s = {
|
|
333
|
-
cli: (document.getElementById('selCli') as HTMLSelectElement)?.value || 'claude',
|
|
334
|
-
};
|
|
335
|
-
const hdr = document.getElementById('headerCli');
|
|
336
|
-
if (hdr) hdr.textContent = s.cli;
|
|
337
|
-
await apiJson('/api/settings', 'PUT', s);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export function setPerm(_p: string, save = true): void {
|
|
341
|
-
// Auto-fixed since Phase 3.1 — no UI toggle, just persist
|
|
342
|
-
if (save) apiFire('/api/settings', 'PUT', { permissions: 'auto' });
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
export function getModelValue(cli: string): string {
|
|
346
|
-
const sel = getModelSelect(cli);
|
|
347
|
-
if (!sel) return 'default';
|
|
348
|
-
if (sel.value === '__custom__') {
|
|
349
|
-
const inp = getCustomModelInput(cli);
|
|
350
|
-
return inp?.value?.trim() || sel.options[0]?.value || 'default';
|
|
351
|
-
}
|
|
352
|
-
return sel.value;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
export function handleModelSelect(cli: string, selectEl: HTMLSelectElement): void {
|
|
356
|
-
const customInput = getCustomModelInput(cli);
|
|
357
|
-
if (!customInput) return;
|
|
358
|
-
if (selectEl.value === '__custom__') {
|
|
359
|
-
customInput.style.display = 'block';
|
|
360
|
-
customInput.focus();
|
|
361
|
-
} else {
|
|
362
|
-
customInput.style.display = 'none';
|
|
363
|
-
savePerCli();
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
export function applyCustomModel(cli: string, inputEl: HTMLInputElement): void {
|
|
368
|
-
const val = inputEl.value.trim();
|
|
369
|
-
if (!val) return;
|
|
370
|
-
const select = getModelSelect(cli);
|
|
371
|
-
if (!select) return;
|
|
372
|
-
appendCustomOption(select, val);
|
|
373
|
-
select.value = val;
|
|
374
|
-
inputEl.style.display = 'none';
|
|
375
|
-
savePerCli();
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
export async function savePerCli(): Promise<void> {
|
|
379
|
-
const perCli: Record<string, PerCliConfig> = {};
|
|
380
|
-
for (const cli of getCliKeys()) {
|
|
381
|
-
const modelEl = getModelSelect(cli);
|
|
382
|
-
if (!modelEl) continue;
|
|
383
|
-
const effortEl = getEffortSelect(cli);
|
|
384
|
-
const entry: PerCliConfig = {
|
|
385
|
-
model: getModelValue(cli),
|
|
386
|
-
effort: effortEl ? effortEl.value : '',
|
|
387
|
-
};
|
|
388
|
-
// Codex fast mode toggle
|
|
389
|
-
if (cli === 'codex') {
|
|
390
|
-
const onBtn = document.getElementById('codexFastOn');
|
|
391
|
-
entry.fastMode = onBtn?.classList.contains('active') ?? false;
|
|
392
|
-
// Context window toggle + values
|
|
393
|
-
const ctxOn = document.getElementById('codexCtxOn');
|
|
394
|
-
entry.contextWindow = ctxOn?.classList.contains('active') ?? false;
|
|
395
|
-
const winInput = document.getElementById('codexCtxWindow') as HTMLInputElement | null;
|
|
396
|
-
const compInput = document.getElementById('codexCtxCompact') as HTMLInputElement | null;
|
|
397
|
-
entry.contextWindowSize = parseInt(winInput?.value || '1000000', 10);
|
|
398
|
-
entry.contextCompactLimit = parseInt(compInput?.value || '900000', 10);
|
|
399
|
-
}
|
|
400
|
-
perCli[cli] = entry;
|
|
401
|
-
}
|
|
402
|
-
await apiJson('/api/settings', 'PUT', { perCli });
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
export function onCliChange(save = true): void {
|
|
406
|
-
const cli = (document.getElementById('selCli') as HTMLSelectElement)?.value || 'claude';
|
|
407
|
-
const models = MODEL_MAP[cli] || [];
|
|
408
|
-
const modelSel = document.getElementById('selModel') as HTMLSelectElement | null;
|
|
409
|
-
setSelectOptions(modelSel, models, { includeCustom: true, includeDefault: true });
|
|
410
|
-
const hdrCli = document.getElementById('headerCli');
|
|
411
|
-
if (hdrCli) hdrCli.textContent = cli;
|
|
412
|
-
syncActiveEffortOptions(cli);
|
|
413
|
-
|
|
414
|
-
const oldInput = document.getElementById('selModelCustom');
|
|
415
|
-
if (oldInput) oldInput.remove();
|
|
416
|
-
const inp = document.createElement('input');
|
|
417
|
-
inp.type = 'text'; inp.id = 'selModelCustom';
|
|
418
|
-
inp.className = 'custom-model-input';
|
|
419
|
-
inp.placeholder = t('model.placeholder');
|
|
420
|
-
inp.style.display = 'none';
|
|
421
|
-
inp.onchange = function () {
|
|
422
|
-
const val = (this as HTMLInputElement).value.trim();
|
|
423
|
-
if (!val || !modelSel) return;
|
|
424
|
-
appendCustomOption(modelSel, val);
|
|
425
|
-
modelSel.value = val;
|
|
426
|
-
(this as HTMLInputElement).style.display = 'none';
|
|
427
|
-
saveActiveCliSettings();
|
|
428
|
-
};
|
|
429
|
-
if (!modelSel) { if (save) updateSettings(); return; }
|
|
430
|
-
modelSel.parentElement?.appendChild(inp);
|
|
431
|
-
modelSel.onchange = function () {
|
|
432
|
-
if ((this as HTMLSelectElement).value === '__custom__') {
|
|
433
|
-
inp.style.display = 'block';
|
|
434
|
-
inp.focus();
|
|
435
|
-
} else {
|
|
436
|
-
inp.style.display = 'none';
|
|
437
|
-
saveActiveCliSettings();
|
|
438
|
-
}
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
api<SettingsData>('/api/settings').then(s => {
|
|
442
|
-
if (!s) return;
|
|
443
|
-
const ao = s.activeOverrides?.[cli] || {};
|
|
444
|
-
const pc = s.perCli?.[cli] || {};
|
|
445
|
-
const model = ao.model || pc.model;
|
|
446
|
-
const effort = ao.effort || pc.effort || '';
|
|
447
|
-
if (model && modelSel) {
|
|
448
|
-
appendCustomOption(modelSel, model);
|
|
449
|
-
modelSel.value = model;
|
|
450
|
-
}
|
|
451
|
-
syncActiveEffortOptions(cli, effort);
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
if (save) updateSettings();
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
export async function saveActiveCliSettings(): Promise<void> {
|
|
458
|
-
const cli = (document.getElementById('selCli') as HTMLSelectElement)?.value || 'claude';
|
|
459
|
-
const modelSel = document.getElementById('selModel') as HTMLSelectElement | null;
|
|
460
|
-
let model = modelSel?.value || 'default';
|
|
461
|
-
if (model === '__custom__') {
|
|
462
|
-
model = (document.getElementById('selModelCustom') as HTMLInputElement | null)?.value?.trim() || 'default';
|
|
463
|
-
}
|
|
464
|
-
const effortEl = document.getElementById('selEffort') as HTMLSelectElement | null;
|
|
465
|
-
const overrides: Record<string, PerCliConfig> = {};
|
|
466
|
-
overrides[cli] = { model };
|
|
467
|
-
if (effortEl && !effortEl.disabled) overrides[cli].effort = effortEl.value || '';
|
|
468
|
-
await apiJson('/api/settings', 'PUT', { activeOverrides: overrides });
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// ── Telegram ──
|
|
472
|
-
export async function saveTelegramSettings(): Promise<void> {
|
|
473
|
-
const token = (document.getElementById('tgToken') as HTMLInputElement)?.value.trim() || '';
|
|
474
|
-
const chatIdsRaw = (document.getElementById('tgChatIds') as HTMLInputElement)?.value.trim() || '';
|
|
475
|
-
const allowedChatIds = chatIdsRaw
|
|
476
|
-
? chatIdsRaw.split(',').map(s => parseInt(s.trim(), 10)).filter(n => !isNaN(n))
|
|
477
|
-
: [];
|
|
478
|
-
await apiJson('/api/settings', 'PUT', { telegram: { token, allowedChatIds } });
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
export async function setTelegram(enabled: boolean): Promise<void> {
|
|
482
|
-
document.getElementById('tgOn')?.classList.toggle('active', enabled);
|
|
483
|
-
document.getElementById('tgOff')?.classList.toggle('active', !enabled);
|
|
484
|
-
await apiJson('/api/settings', 'PUT', { telegram: { enabled } });
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
export async function setForwardAll(enabled: boolean): Promise<void> {
|
|
488
|
-
document.getElementById('tgForwardOn')?.classList.toggle('active', enabled);
|
|
489
|
-
document.getElementById('tgForwardOff')?.classList.toggle('active', !enabled);
|
|
490
|
-
await apiJson('/api/settings', 'PUT', { telegram: { forwardAll: enabled } });
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
function loadTelegramSettings(s: SettingsData): void {
|
|
494
|
-
if (!s.telegram) return;
|
|
495
|
-
const tg = s.telegram;
|
|
496
|
-
document.getElementById('tgOn')?.classList.toggle('active', !!tg.enabled);
|
|
497
|
-
document.getElementById('tgOff')?.classList.toggle('active', !tg.enabled);
|
|
498
|
-
const tgToken = document.getElementById('tgToken') as HTMLInputElement | null;
|
|
499
|
-
if (tg.token && tgToken) tgToken.value = tg.token;
|
|
500
|
-
const tgChatIds = document.getElementById('tgChatIds') as HTMLInputElement | null;
|
|
501
|
-
if (tg.allowedChatIds?.length && tgChatIds) {
|
|
502
|
-
tgChatIds.value = tg.allowedChatIds.join(', ');
|
|
503
|
-
}
|
|
504
|
-
const fwdOn = tg.forwardAll !== false;
|
|
505
|
-
document.getElementById('tgForwardOn')?.classList.toggle('active', fwdOn);
|
|
506
|
-
document.getElementById('tgForwardOff')?.classList.toggle('active', !fwdOn);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
// ── Fallback Order ──
|
|
510
|
-
export function loadFallbackOrder(s: SettingsData): void {
|
|
511
|
-
const container = document.getElementById('fallbackOrderList');
|
|
512
|
-
if (!container) return;
|
|
513
|
-
const allClis = Object.keys(s.perCli || {});
|
|
514
|
-
const active = s.fallbackOrder || [];
|
|
515
|
-
const slotCount = Math.min(allClis.length - 1, 3);
|
|
516
|
-
|
|
517
|
-
let html = '';
|
|
518
|
-
for (let i = 0; i < slotCount; i++) {
|
|
519
|
-
const current = active[i] || '';
|
|
520
|
-
const opts = allClis.map(cli =>
|
|
521
|
-
`<option value="${cli}" ${cli === current ? 'selected' : ''}>${cli}</option>`
|
|
522
|
-
).join('');
|
|
523
|
-
html += `
|
|
524
|
-
<div class="settings-row sub-row">
|
|
525
|
-
<label style="min-width:60px">Fallback ${i + 1}</label>
|
|
526
|
-
<select id="fallback${i}"
|
|
527
|
-
style="font-size:11px;padding:4px;background:var(--surface);color:var(--text);border:1px solid var(--border);border-radius:4px;flex:1">
|
|
528
|
-
<option value="">${t('settings.none')}</option>
|
|
529
|
-
${opts}
|
|
530
|
-
</select>
|
|
531
|
-
</div>`;
|
|
532
|
-
}
|
|
533
|
-
container.innerHTML = html;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
export async function saveFallbackOrder(): Promise<void> {
|
|
537
|
-
const selects = document.querySelectorAll<HTMLSelectElement>('#fallbackOrderList select');
|
|
538
|
-
const fallbackOrder = [...selects].map(s => s.value).filter(Boolean);
|
|
539
|
-
await apiJson('/api/settings', 'PUT', { fallbackOrder });
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// ── CLI Status ──
|
|
543
|
-
import { state } from '../state.js';
|
|
544
|
-
|
|
545
|
-
export async function loadCliStatus(force = false): Promise<void> {
|
|
546
|
-
const interval = Number(localStorage.getItem('cliStatusInterval') || 300);
|
|
547
|
-
if (!force && state.cliStatusCache && interval > 0 && (Date.now() - state.cliStatusTs) < interval * 1000) {
|
|
548
|
-
renderCliStatus({ cliStatus: (state.cliStatusCache as Record<string, unknown>)?.cliStatus as Record<string, { available: boolean }> | null, quota: (state.cliStatusCache as Record<string, unknown>)?.quota as Record<string, QuotaEntry> | null });
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
const el = document.getElementById('cliStatusList');
|
|
553
|
-
if (el) el.innerHTML = '<div style="color:var(--text-dim);font-size:11px">Loading...</div>';
|
|
554
|
-
|
|
555
|
-
const [cliStatus, quota] = await Promise.all([
|
|
556
|
-
api<Record<string, { available: boolean }>>('/api/cli-status'),
|
|
557
|
-
api<Record<string, QuotaEntry>>('/api/quota'),
|
|
558
|
-
]);
|
|
559
|
-
|
|
560
|
-
state.cliStatusCache = { cliStatus, quota } as Record<string, unknown>;
|
|
561
|
-
state.cliStatusTs = Date.now();
|
|
562
|
-
renderCliStatus({ cliStatus, quota });
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
function renderCliStatus(data: { cliStatus: Record<string, { available: boolean }> | null; quota: Record<string, QuotaEntry> | null }): void {
|
|
566
|
-
const { cliStatus, quota } = data;
|
|
567
|
-
const el = document.getElementById('cliStatusList');
|
|
568
|
-
|
|
569
|
-
const AUTH_HINTS: Record<string, { install: string; auth: string }> = {
|
|
570
|
-
claude: { install: 'npm i -g @anthropic-ai/claude-code', auth: 'claude auth' },
|
|
571
|
-
codex: { install: 'npm i -g @openai/codex', auth: 'codex login' },
|
|
572
|
-
gemini: { install: 'npm i -g @google/gemini-cli', auth: `gemini (${t('cli.gemini.auth')})` },
|
|
573
|
-
opencode: { install: 'npm i -g opencode-ai', auth: 'opencode auth' },
|
|
574
|
-
copilot: { install: 'npm i -g copilot', auth: 'copilot login 또는 gh auth login' },
|
|
575
|
-
};
|
|
576
|
-
|
|
577
|
-
let html = '';
|
|
578
|
-
|
|
579
|
-
if (!cliStatus || typeof cliStatus !== 'object') {
|
|
580
|
-
if (el) el.innerHTML = '<div style="color:var(--text-dim);font-size:11px">Failed to load CLI status</div>';
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
for (const [name, info] of Object.entries(cliStatus)) {
|
|
585
|
-
const q = quota?.[name];
|
|
586
|
-
// 3-state: ok (installed+authed), warn (installed+no-auth), missing (not installed)
|
|
587
|
-
let dotClass: string;
|
|
588
|
-
if (!info.available) {
|
|
589
|
-
dotClass = 'missing';
|
|
590
|
-
} else if (!q || q.error) {
|
|
591
|
-
dotClass = 'ok'; // transient error or no data — keep green
|
|
592
|
-
} else if (q.authenticated === false) {
|
|
593
|
-
dotClass = 'warn'; // explicitly unauthenticated
|
|
594
|
-
} else {
|
|
595
|
-
dotClass = 'ok';
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
let accountLine = '';
|
|
599
|
-
if (q?.account) {
|
|
600
|
-
const parts = [];
|
|
601
|
-
if (q.account.email) parts.push(q.account.email);
|
|
602
|
-
if (q.account.type) parts.push(q.account.type);
|
|
603
|
-
if (q.account.plan) parts.push(q.account.plan);
|
|
604
|
-
if (q.account.tier) parts.push(q.account.tier);
|
|
605
|
-
if (parts.length) accountLine = `<div style="font-size:10px;color:var(--text-dim);margin:2px 0 4px 16px">${escapeHtml(parts.join(' · '))}</div>`;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
let authHint = '';
|
|
609
|
-
if (!info.available || dotClass === 'warn') {
|
|
610
|
-
const hint = AUTH_HINTS[name];
|
|
611
|
-
if (hint) {
|
|
612
|
-
const isNotInstalled = !info.available;
|
|
613
|
-
const title = isNotInstalled ? t('cli.authRequired') : t('cli.notAuthenticated');
|
|
614
|
-
const borderColor = isNotInstalled ? '#ef4444' : '#fbbf24';
|
|
615
|
-
authHint = `
|
|
616
|
-
<div style="font-size:10px;margin:4px 0 2px 16px;padding:6px 8px;background:var(--bg-dim, #1e1e2e);border-radius:4px;border-left:2px solid ${borderColor}">
|
|
617
|
-
<div style="color:${borderColor};margin-bottom:3px">${title}</div>
|
|
618
|
-
${isNotInstalled ? `<div style="color:var(--text-dim)"><code style="font-size:10px;background:var(--border);padding:1px 4px;border-radius:2px">${escapeHtml(hint.install)}</code></div>` : ''}
|
|
619
|
-
<div style="color:var(--text-dim)${isNotInstalled ? ';margin-top:2px' : ''}"><code style="font-size:10px;background:var(--border);padding:1px 4px;border-radius:2px">${escapeHtml(hint.auth)}</code></div>
|
|
620
|
-
</div>
|
|
621
|
-
`;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
let windowsHtml = '';
|
|
626
|
-
if (q?.windows?.length) {
|
|
627
|
-
windowsHtml = q.windows.map(w => {
|
|
628
|
-
const pct = Math.round(w.percent);
|
|
629
|
-
const barColor = pct > 80 ? '#ef4444' : pct > 50 ? '#fbbf24' : '#38bdf8';
|
|
630
|
-
const shortLabel = w.label.replace('-hour', 'h').replace('-day', 'd').replace(' Sonnet', '').replace(' Opus', '');
|
|
631
|
-
let resetStr = '';
|
|
632
|
-
if (w.resetsAt) {
|
|
633
|
-
const d = new Date(typeof w.resetsAt === 'number' ? w.resetsAt * 1000 : w.resetsAt);
|
|
634
|
-
const now = new Date();
|
|
635
|
-
if (d.toDateString() === now.toDateString()) {
|
|
636
|
-
resetStr = `${d.getHours()}:${String(d.getMinutes()).padStart(2, '0')}`;
|
|
637
|
-
} else {
|
|
638
|
-
resetStr = `${d.getMonth() + 1}/${d.getDate()}`;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
return `
|
|
642
|
-
<div style="display:flex;align-items:center;gap:4px;margin-left:16px;font-size:10px;color:var(--text-dim)">
|
|
643
|
-
<span style="width:18px">${shortLabel}</span>
|
|
644
|
-
<div style="flex:1;height:4px;background:var(--border);border-radius:2px;overflow:hidden">
|
|
645
|
-
<div style="width:${pct}%;height:100%;background:${barColor};border-radius:2px"></div>
|
|
646
|
-
</div>
|
|
647
|
-
<span style="width:24px;text-align:right">${pct}%</span>
|
|
648
|
-
${resetStr ? `<span style="width:30px;text-align:right;opacity:0.6">${resetStr}</span>` : ''}
|
|
649
|
-
</div>
|
|
650
|
-
`;
|
|
651
|
-
}).join('');
|
|
652
|
-
} else if (q?.error && info.available) {
|
|
653
|
-
const msg = q.reason === 'rate_limited' ? 'Rate limited — retry in a moment' : 'Usage data unavailable';
|
|
654
|
-
windowsHtml = `<div style="font-size:10px;color:var(--text-dim);margin:2px 0 0 16px;opacity:0.7">⚠ ${msg}</div>`;
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
html += `
|
|
658
|
-
<div class="settings-group" style="margin-bottom:6px;padding:8px 10px">
|
|
659
|
-
<div class="cli-status-row">
|
|
660
|
-
<span class="cli-dot ${dotClass}"></span>
|
|
661
|
-
<span class="cli-name" style="font-weight:600">${name}</span>${name === 'copilot' ? `<button id="copilotKeychainBtn" style="font-size:9px;margin-left:6px;padding:1px 5px;background:var(--border);color:var(--text-dim);border:1px solid var(--text-dim);border-radius:3px;cursor:pointer;vertical-align:middle;line-height:1" title="${t('copilot.keychainHint')}">🔑</button>` : ''}
|
|
662
|
-
</div>
|
|
663
|
-
${accountLine}
|
|
664
|
-
${authHint}
|
|
665
|
-
${windowsHtml}
|
|
666
|
-
</div>
|
|
667
|
-
`;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
if (el) el.innerHTML = html;
|
|
671
|
-
|
|
672
|
-
// Copilot keychain refresh handler — shows each token source result
|
|
673
|
-
const kcBtn = document.getElementById('copilotKeychainBtn');
|
|
674
|
-
if (kcBtn) {
|
|
675
|
-
kcBtn.addEventListener('click', async () => {
|
|
676
|
-
const btn = kcBtn as HTMLButtonElement;
|
|
677
|
-
btn.disabled = true;
|
|
678
|
-
btn.textContent = '⏳';
|
|
679
|
-
try {
|
|
680
|
-
const res = await api<{ ok: boolean }>('/api/copilot/refresh', { method: 'POST' });
|
|
681
|
-
btn.textContent = res?.ok ? '✅' : '❌';
|
|
682
|
-
if (res?.ok) await loadCliStatus(true);
|
|
683
|
-
} catch {
|
|
684
|
-
btn.textContent = '❌';
|
|
685
|
-
}
|
|
686
|
-
setTimeout(() => { btn.textContent = '🔑'; btn.disabled = false; }, 2000);
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
// ── Prompt Modal ──
|
|
692
|
-
export function openPromptModal(): void {
|
|
693
|
-
api<{ content?: string }>('/api/prompt').then(data => {
|
|
694
|
-
if (!data) return;
|
|
695
|
-
const editor = document.getElementById('modalPromptEditor') as HTMLTextAreaElement | null;
|
|
696
|
-
if (editor) editor.value = data.content || '';
|
|
697
|
-
document.getElementById('promptModal')?.classList.add('open');
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
export function closePromptModal(e?: Event): void {
|
|
702
|
-
if (e && e.target !== e.currentTarget) return;
|
|
703
|
-
document.getElementById('promptModal')?.classList.remove('open');
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
export async function savePromptFromModal(): Promise<void> {
|
|
707
|
-
const editor = document.getElementById('modalPromptEditor') as HTMLTextAreaElement | null;
|
|
708
|
-
const content = editor?.value || '';
|
|
709
|
-
await apiJson('/api/prompt', 'PUT', { content });
|
|
710
|
-
document.getElementById('promptModal')?.classList.remove('open');
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// ── Template Modal (Node Map + Editor) ──
|
|
714
|
-
|
|
715
|
-
interface TemplateInfo { id: string; filename: string; content: string; }
|
|
716
|
-
interface TreeNode { id: string; label: string; emoji: string; children: string[]; }
|
|
717
|
-
let _templates: TemplateInfo[] = [];
|
|
718
|
-
let _devMode = false;
|
|
719
|
-
|
|
720
|
-
export async function openTemplateModal(): Promise<void> {
|
|
721
|
-
const data = await api<{ templates: TemplateInfo[]; tree: TreeNode[] }>('/api/prompt-templates');
|
|
722
|
-
if (!data) return;
|
|
723
|
-
_templates = data.templates;
|
|
724
|
-
_devMode = false;
|
|
725
|
-
renderTree(data.tree);
|
|
726
|
-
showTemplateView('tree');
|
|
727
|
-
document.getElementById('templateModal')?.classList.add('open');
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
function renderTree(tree: TreeNode[]): void {
|
|
731
|
-
const container = document.getElementById('templateTree');
|
|
732
|
-
if (!container) return;
|
|
733
|
-
container.innerHTML = '';
|
|
734
|
-
for (const group of tree) {
|
|
735
|
-
const main = document.createElement('div');
|
|
736
|
-
main.style.cssText = 'background:var(--bg);border:1px solid var(--accent);border-radius:6px;padding:8px 10px;margin:8px 0 4px;font-size:12px;color:var(--accent);font-weight:600';
|
|
737
|
-
main.textContent = `${group.emoji} ${group.label}`;
|
|
738
|
-
container.appendChild(main);
|
|
739
|
-
for (const childId of group.children) {
|
|
740
|
-
const tmpl = _templates.find(t => t.id === childId);
|
|
741
|
-
if (!tmpl) continue;
|
|
742
|
-
const node = document.createElement('div');
|
|
743
|
-
node.style.cssText = 'background:var(--bg);border:1px solid var(--border);border-radius:6px;padding:6px 10px;margin:2px 0 2px 24px;font-size:12px;cursor:pointer;transition:border-color .15s';
|
|
744
|
-
node.textContent = `📄 ${tmpl.filename}`;
|
|
745
|
-
node.addEventListener('mouseenter', () => { node.style.borderColor = 'var(--accent2)'; });
|
|
746
|
-
node.addEventListener('mouseleave', () => { node.style.borderColor = 'var(--border)'; });
|
|
747
|
-
node.addEventListener('click', () => { openTemplateEditor(tmpl); });
|
|
748
|
-
container.appendChild(node);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
function openTemplateEditor(tmpl: TemplateInfo): void {
|
|
754
|
-
const editor = document.getElementById('templateEditor') as HTMLTextAreaElement;
|
|
755
|
-
editor.value = tmpl.content;
|
|
756
|
-
editor.dataset.templateId = tmpl.id;
|
|
757
|
-
editor.readOnly = true;
|
|
758
|
-
_devMode = false;
|
|
759
|
-
const label = document.getElementById('templateEditorLabel');
|
|
760
|
-
if (label) label.textContent = `📄 ${tmpl.filename}`;
|
|
761
|
-
const vars = tmpl.content.match(/\{\{[A-Z_]+\}\}/g);
|
|
762
|
-
const varsEl = document.getElementById('templateVars');
|
|
763
|
-
if (varsEl) varsEl.textContent = vars ? `vars: ${[...new Set(vars)].join(', ')}` : 'no variables';
|
|
764
|
-
const saveBtn = document.getElementById('templateSaveBtn');
|
|
765
|
-
if (saveBtn) saveBtn.style.display = 'none';
|
|
766
|
-
const toggle = document.getElementById('templateDevToggle');
|
|
767
|
-
if (toggle) { toggle.style.color = 'var(--text-dim)'; toggle.style.borderColor = 'var(--border)'; toggle.textContent = '🔧 개발자 모드'; }
|
|
768
|
-
const title = document.getElementById('templateModalTitle');
|
|
769
|
-
if (title) title.textContent = `📄 ${tmpl.filename}`;
|
|
770
|
-
showTemplateView('editor');
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
export function toggleDevMode(): void {
|
|
774
|
-
if (!_devMode) {
|
|
775
|
-
if (!confirm('⚠️ 프롬프트를 직접 수정하면 예상치 못한 동작이 발생할 수 있습니다.\n계속하시겠습니까?')) return;
|
|
776
|
-
}
|
|
777
|
-
_devMode = !_devMode;
|
|
778
|
-
const editor = document.getElementById('templateEditor') as HTMLTextAreaElement;
|
|
779
|
-
editor.readOnly = !_devMode;
|
|
780
|
-
const saveBtn = document.getElementById('templateSaveBtn');
|
|
781
|
-
if (saveBtn) saveBtn.style.display = _devMode ? '' : 'none';
|
|
782
|
-
const toggle = document.getElementById('templateDevToggle');
|
|
783
|
-
if (toggle) {
|
|
784
|
-
toggle.style.color = _devMode ? 'var(--stop-btn)' : 'var(--text-dim)';
|
|
785
|
-
toggle.style.borderColor = _devMode ? 'var(--stop-btn)' : 'var(--border)';
|
|
786
|
-
toggle.textContent = _devMode ? '🔓 개발자 모드 ON' : '🔧 개발자 모드';
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
export async function saveTemplateFromModal(): Promise<void> {
|
|
791
|
-
const editor = document.getElementById('templateEditor') as HTMLTextAreaElement;
|
|
792
|
-
const id = editor.dataset.templateId;
|
|
793
|
-
if (!id) return;
|
|
794
|
-
await apiJson(`/api/prompt-templates/${id}`, 'PUT', { content: editor.value });
|
|
795
|
-
const label = document.getElementById('templateEditorLabel');
|
|
796
|
-
if (label) { label.textContent = '✅ 저장 + 핫리로드 완료!'; setTimeout(() => { label.textContent = `📄 ${id}.md`; }, 2000); }
|
|
797
|
-
const t = _templates.find(x => x.id === id);
|
|
798
|
-
if (t) t.content = editor.value;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
function showTemplateView(view: 'tree' | 'editor'): void {
|
|
802
|
-
const treeView = document.getElementById('templateTreeView');
|
|
803
|
-
const editorView = document.getElementById('templateEditorView');
|
|
804
|
-
if (treeView) treeView.style.display = view === 'tree' ? '' : 'none';
|
|
805
|
-
if (editorView) editorView.style.display = view === 'editor' ? 'flex' : 'none';
|
|
806
|
-
const title = document.getElementById('templateModalTitle');
|
|
807
|
-
if (title && view === 'tree') title.textContent = '📝 프롬프트 구조';
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
export function templateGoBack(): void { showTemplateView('tree'); }
|
|
811
|
-
|
|
812
|
-
export function closeTemplateModal(e?: Event): void {
|
|
813
|
-
if (e && e.target !== e.currentTarget) return;
|
|
814
|
-
document.getElementById('templateModal')?.classList.remove('open');
|
|
815
|
-
}
|
|
1
|
+
// settings.ts — barrel re-export (preserves all import paths)
|
|
2
|
+
export { loadSettings, updateSettings, setPerm, getModelValue, handleModelSelect, applyCustomModel, onCliChange, saveActiveCliSettings, savePerCli } from './settings-core.js';
|
|
3
|
+
export { setTelegram, setForwardAll, saveTelegramSettings } from './settings-telegram.js';
|
|
4
|
+
export { setDiscord, setDiscordForwardAll, setDiscordAllowBots, saveDiscordSettings } from './settings-discord.js';
|
|
5
|
+
export { setActiveChannel, loadFallbackOrder, saveFallbackOrder } from './settings-channel.js';
|
|
6
|
+
export { loadMcpServers, syncMcpServers, installMcpGlobal } from './settings-mcp.js';
|
|
7
|
+
export { loadCliStatus } from './settings-cli-status.js';
|
|
8
|
+
export { initSttSettings } from './settings-stt.js';
|
|
9
|
+
export { openPromptModal, closePromptModal, savePromptFromModal, openTemplateModal, saveTemplateFromModal, closeTemplateModal, templateGoBack, toggleDevMode } from './settings-templates.js';
|