@pheem49/mint 1.17.0 → 1.18.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/Cargo.lock +6 -6
- package/Cargo.toml +2 -2
- package/README.md +8 -2
- package/Release_Note.md +222 -71
- package/crates/mint-cli/src/agent/diff_render.rs +66 -44
- package/crates/mint-cli/src/agent/live_status.rs +21 -4
- package/crates/mint-cli/src/agent/markdown_render.rs +342 -5
- package/crates/mint-cli/src/agent.rs +25 -10
- package/crates/mint-cli/src/commands/agent.rs +4 -92
- package/crates/mint-cli/src/commands/browser.rs +2 -15
- package/crates/mint-cli/src/commands/integrations.rs +3 -3
- package/crates/mint-cli/src/commands/mod.rs +0 -3
- package/crates/mint-cli/src/commands/tailnet_web.rs +1 -0
- package/crates/mint-cli/src/interactive/chat_tui/dialog.rs +572 -0
- package/crates/mint-cli/src/interactive/chat_tui/mod.rs +1427 -0
- package/crates/mint-cli/src/interactive/chat_tui/render.rs +1524 -0
- package/crates/mint-cli/src/interactive/chat_tui/selection.rs +401 -0
- package/crates/mint-cli/src/interactive/chat_tui/state.rs +1833 -0
- package/crates/mint-cli/src/interactive/chat_tui/tests.rs +3414 -0
- package/crates/mint-cli/src/interactive/chat_tui/thought.rs +202 -0
- package/crates/mint-cli/src/interactive/chat_tui/transcript.rs +728 -0
- package/crates/mint-cli/src/interactive/chat_tui/watermark.rs +148 -0
- package/crates/mint-cli/src/interactive/command_ui.rs +53 -5
- package/crates/mint-cli/src/interactive/composer.rs +186 -0
- package/crates/mint-cli/src/interactive/format.rs +78 -3
- package/crates/mint-cli/src/interactive/input_box.rs +61 -1
- package/crates/mint-cli/src/interactive/resume_picker.rs +367 -25
- package/crates/mint-cli/src/interactive/slash_commands.rs +648 -371
- package/crates/mint-cli/src/interactive/tool_activity.rs +93 -20
- package/crates/mint-cli/src/interactive.rs +37 -0
- package/crates/mint-cli/src/main.rs +6 -3
- package/crates/mint-cli/src/markdown.rs +2 -37
- package/crates/mint-cli/src/onboard.rs +700 -282
- package/crates/mint-cli/src/setup.rs +1342 -624
- package/crates/mint-cli/src/terminal_theme.rs +159 -35
- package/crates/mint-cli/tests/library_intake.rs +1 -0
- package/crates/mint-core/src/agent/chat/anthropic.rs +318 -0
- package/crates/mint-core/src/agent/chat/custom.rs +149 -0
- package/crates/mint-core/src/agent/chat/gemini.rs +518 -0
- package/crates/mint-core/src/agent/chat/mod.rs +857 -0
- package/crates/mint-core/src/agent/chat/ollama.rs +321 -0
- package/crates/mint-core/src/agent/chat/openai.rs +582 -0
- package/crates/mint-core/src/agent/chat/streaming.rs +469 -0
- package/crates/mint-core/src/agent/chat/tests.rs +1479 -0
- package/crates/mint-core/src/agent/memory.rs +56 -2
- package/crates/mint-core/src/agent/tasks.rs +2 -2
- package/crates/mint-core/src/api_server/routes/chat.rs +24 -2
- package/crates/mint-core/src/api_server/routes/gemini_live.rs +14 -1
- package/crates/mint-core/src/api_server/routes/html_preview.rs +1 -8
- package/crates/mint-core/src/api_server/routes/sessions.rs +21 -0
- package/crates/mint-core/src/avatar_bridge.rs +0 -22
- package/crates/mint-core/src/browser/cdp.rs +10 -4
- package/crates/mint-core/src/browser/headless.rs +582 -0
- package/crates/mint-core/src/browser/input.rs +7 -62
- package/crates/mint-core/src/browser/interact.rs +0 -14
- package/crates/mint-core/src/browser/mod.rs +8 -29
- package/crates/mint-core/src/browser/navigate.rs +2 -36
- package/crates/mint-core/src/browser/runtime.rs +2 -4
- package/crates/mint-core/src/browser/session.rs +50 -466
- package/crates/mint-core/src/browser/workflow.rs +142 -32
- package/crates/mint-core/src/cron/store.rs +2 -2
- package/crates/mint-core/src/integrations/mcp.rs +6 -8
- package/crates/mint-core/src/lib.rs +0 -5
- package/crates/mint-core/src/media/gemini_live.rs +636 -86
- package/crates/mint-core/src/media/library/migration.rs +26 -0
- package/crates/mint-core/src/media/library/tests.rs +1 -1
- package/crates/mint-core/src/media/library/thumbnails.rs +8 -2
- package/crates/mint-core/src/media/pictures.rs +1 -1
- package/crates/mint-core/src/media/tool_images.rs +92 -1
- package/crates/mint-core/src/mods/manager.rs +101 -35
- package/crates/mint-core/src/orchestration/context_render.rs +441 -24
- package/crates/mint-core/src/orchestration/decision_parsing.rs +531 -16
- package/crates/mint-core/src/orchestration/full_skill_result_tests.rs +12 -0
- package/crates/mint-core/src/orchestration/loop_guard.rs +145 -0
- package/crates/mint-core/src/orchestration/mcp_outcome_tests.rs +864 -0
- package/crates/mint-core/src/orchestration/memory_skill.rs +88 -28
- package/crates/mint-core/src/orchestration/mod.rs +320 -4249
- package/crates/mint-core/src/orchestration/reliability.rs +67 -27
- package/crates/mint-core/src/orchestration/review_regressions.rs +5 -0
- package/crates/mint-core/src/orchestration/tests.rs +1665 -0
- package/crates/mint-core/src/orchestration/tools/dispatch.rs +967 -0
- package/crates/mint-core/src/orchestration/tools/files.rs +1 -0
- package/crates/mint-core/src/orchestration/tools/mod.rs +5 -1
- package/crates/mint-core/src/orchestration/tools/planning.rs +102 -42
- package/crates/mint-core/src/orchestration/tools/shell.rs +129 -58
- package/crates/mint-core/src/orchestration/truncation.rs +170 -13
- package/crates/mint-core/src/orchestration/types.rs +648 -0
- package/crates/mint-core/src/orchestration/verification.rs +0 -3
- package/crates/mint-core/src/orchestration/workspace_helpers.rs +24 -6
- package/crates/mint-core/src/prompts/agent.rs +52 -76
- package/crates/mint-core/src/prompts/tool_catalog.rs +8 -151
- package/crates/mint-core/src/search/files.rs +20 -0
- package/crates/mint-core/src/slash/mod.rs +228 -265
- package/crates/mint-core/src/slash/models.rs +6 -1
- package/crates/mint-core/src/system/bg_shell.rs +1 -0
- package/crates/mint-core/src/system/config.rs +176 -34
- package/crates/mint-mod-runtime/src/lib.rs +37 -23
- package/out/web/assets/ArtifactPreviewPanel-Cx6BVOOF.js +2 -0
- package/out/web/assets/CalculationCard-D2E74u5q.js +1 -0
- package/out/web/assets/CliSessionsView-ZbdtSjvK.css +1 -0
- package/out/web/assets/{CliSessionsView-MI8kXMAb.js → CliSessionsView-z5i6qGyb.js} +1 -1
- package/out/web/assets/CodeReviewPage-BK2bOScd.css +1 -0
- package/out/web/assets/CodeReviewPage-Dp6zHuHu.js +2 -0
- package/out/web/assets/{CommandPalette-BD8SlTE5.js → CommandPalette-DaKlzbKs.js} +1 -1
- package/out/web/assets/ImageGenCard-BMCJHP9O.js +1 -0
- package/out/web/assets/ImageSearchCard-Cld_SOUg.js +1 -0
- package/out/web/assets/{ImageStudioPanel-BP7N4rLr.js → ImageStudioPanel-B5N7TjeB.js} +1 -1
- package/out/web/assets/LibraryPage-CMB89rJ0.css +1 -0
- package/out/web/assets/LibraryPage-DbZEi4W_.js +2 -0
- package/out/web/assets/LinkedFoldersView-9B9DIPoZ.js +1 -0
- package/out/web/assets/{McpRegistryPicker-CoS83vtc.js → McpRegistryPicker-DnXPlzI7.js} +1 -1
- package/out/web/assets/McpServersView-CiNBNUl4.js +1 -0
- package/out/web/assets/MermaidCard-BBDNEXbY.js +2 -0
- package/out/web/assets/MintDashboard-C_UYPoNV.js +119 -0
- package/out/web/assets/MintDashboard-DTd8C_c8.css +1 -0
- package/out/web/assets/PlanCard-C2x5pajq.js +1 -0
- package/out/web/assets/{PluginsView-jBYmcKh4.js → PluginsView-DoTg9MVa.js} +1 -1
- package/out/web/assets/RewindModal-B5oowrR0.js +1 -0
- package/out/web/assets/{ScheduledTasksView-5uw9-V9H.js → ScheduledTasksView-BD5DVPkZ.js} +1 -1
- package/out/web/assets/{SelectField-DXBQtrUK.js → SelectField-Cy6CghrU.js} +1 -1
- package/out/web/assets/SettingsWindow-BYl_oCFh.js +4 -0
- package/out/web/assets/SettingsWindow-Ckcgnjt8.css +1 -0
- package/out/web/assets/{SkillsView-C-gp9J7m.js → SkillsView-CIeWwq5z.js} +1 -1
- package/out/web/assets/StockCard-DxUciKyp.js +1 -0
- package/out/web/assets/ToolSurfacePage-qBgs_VHq.css +1 -0
- package/out/web/assets/ToolSurfacePage-saVbVrkE.js +38 -0
- package/out/web/assets/{UiFeatureCard-6BwxTOCe.js → UiFeatureCard-CdY0hGWy.js} +1 -1
- package/out/web/assets/{UiGridCard-DvZcLNxb.js → UiGridCard-BBK3I5hC.js} +1 -1
- package/out/web/assets/UiMockupWidget-CpR9EDuc.js +1 -0
- package/out/web/assets/{VeoStudioPanel-DOj7_WR3.css → VeoStudioPanel-9kU9YLEN.css} +1 -1
- package/out/web/assets/{VeoStudioPanel-DfsOJKv0.js → VeoStudioPanel-Co6-wEWM.js} +2 -2
- package/out/web/assets/WeatherCard-Buzi7Vfu.js +1 -0
- package/out/web/assets/WorkspacePdfPreview-Bi8Zzyir.js +2 -0
- package/out/web/assets/{abnfDiagram-VCTEODGH-BOo3Ckng.js → abnfDiagram-VCTEODGH-CMfR95N2.js} +1 -1
- package/out/web/assets/{architecture-7GRP2DOG-ZOwheW3n.js → architecture-7GRP2DOG-DhAM4HyO.js} +1 -1
- package/out/web/assets/{architectureDiagram-5GKGNRK7-DC2FDzVd.js → architectureDiagram-5GKGNRK7-Yk3TUJ_F.js} +1 -1
- package/out/web/assets/{blockDiagram-I7D4REHJ-BrKFWdAH.js → blockDiagram-I7D4REHJ-X9fBgJik.js} +1 -1
- package/out/web/assets/{c4Diagram-7LVT6UL2-BHTHK1Yd.js → c4Diagram-7LVT6UL2-Bk9x7N-8.js} +1 -1
- package/out/web/assets/{chunk-4HAMMTFA-BYFkZwNj.js → chunk-4HAMMTFA-Dx5fk1_0.js} +1 -1
- package/out/web/assets/{chunk-75Z2AOVW-BSKfSKSA.js → chunk-75Z2AOVW-BszTQoM4.js} +1 -1
- package/out/web/assets/{chunk-DU6HZSFF-vIhsiW6n.js → chunk-DU6HZSFF-DK-As3rk.js} +1 -1
- package/out/web/assets/{chunk-F27PBJKO-BlYpW9xq.js → chunk-F27PBJKO-LmncZZIS.js} +1 -1
- package/out/web/assets/{chunk-GMAD6QVW-BIBz_Ug5.js → chunk-GMAD6QVW-DSQ_sDRJ.js} +1 -1
- package/out/web/assets/{chunk-GVQU2GXP-NPSHxeqC.js → chunk-GVQU2GXP-Cno3ulje.js} +1 -1
- package/out/web/assets/{chunk-IMKFNOWR-YlJK8_Fp.js → chunk-IMKFNOWR-bIzfY9Jc.js} +1 -1
- package/out/web/assets/{chunk-L3NEJ4N5-DMYi4-af.js → chunk-L3NEJ4N5-Dl6eOa0D.js} +1 -1
- package/out/web/assets/{chunk-OSK3NFVY-Begd3-jA.js → chunk-OSK3NFVY-BaUGJ-cM.js} +1 -1
- package/out/web/assets/{chunk-P2QGCYS3-D1I4xFHN.js → chunk-P2QGCYS3-_066ndhH.js} +1 -1
- package/out/web/assets/{chunk-POPQ4Y6H-CafZZzNE.js → chunk-POPQ4Y6H-YT1AKhTv.js} +1 -1
- package/out/web/assets/{chunk-PWAF6VOD-Dwh6_Lnt.js → chunk-PWAF6VOD-CrEgDsxh.js} +1 -1
- package/out/web/assets/{chunk-SHT3W25Y-B0XrCSEb.js → chunk-SHT3W25Y-_KwaRLOl.js} +1 -1
- package/out/web/assets/{chunk-SVP7TREG-CxLsddxC.js → chunk-SVP7TREG-BQ1qb32L.js} +1 -1
- package/out/web/assets/{chunk-TICWLB2K-y156QInb.js → chunk-TICWLB2K-BDyehCtg.js} +1 -1
- package/out/web/assets/classDiagram-ZZMXUADV-BoSpzRCJ.js +1 -0
- package/out/web/assets/classDiagram-v2-VYDZK3BY-BoSpzRCJ.js +1 -0
- package/out/web/assets/{config-DqXJXeZM.css → config-2suVFPZg.css} +1 -1
- package/out/web/assets/config-CkRCdkxn.js +2 -0
- package/out/web/assets/{cynefin-OW5HDTMX-SMVvrLf-.js → cynefin-OW5HDTMX-Dl_31aaN.js} +1 -1
- package/out/web/assets/{cynefinDiagram-5FMLGOSQ-rZznN24T.js → cynefinDiagram-5FMLGOSQ-Bpir8jha.js} +1 -1
- package/out/web/assets/{dagre-GXQ25YYZ-BOToydFu.js → dagre-GXQ25YYZ-D9xu3nsq.js} +1 -1
- package/out/web/assets/{diagram-S7CK7UJ4-TMVaGQEJ.js → diagram-S7CK7UJ4-DeveoEeB.js} +1 -1
- package/out/web/assets/{diagram-UQ7AKVKN-C2JK-GP2.js → diagram-UQ7AKVKN-p4xWRESV.js} +1 -1
- package/out/web/assets/{diagram-VSXAHHWV-Cw8VSi2K.js → diagram-VSXAHHWV-C7qz9NDF.js} +1 -1
- package/out/web/assets/{diagram-VX7I27RA-DXp4fKk9.js → diagram-VX7I27RA-DRiCa3Vd.js} +1 -1
- package/out/web/assets/{diagram-Z3DM3KII-CzSicYiW.js → diagram-Z3DM3KII-Bt7zduQX.js} +1 -1
- package/out/web/assets/{ebnfDiagram-PWID7BFC-Dqj-zqPu.js → ebnfDiagram-PWID7BFC-DV9WpwdR.js} +1 -1
- package/out/web/assets/{erDiagram-RLTQ6QDP-DZwFZAuD.js → erDiagram-RLTQ6QDP-BJ_nwG2m.js} +1 -1
- package/out/web/assets/{eventmodeling-NTZA5JFV-C0O-Lvgp.js → eventmodeling-NTZA5JFV-BTBMrfVa.js} +1 -1
- package/out/web/assets/flowDiagram-HODETNUW-Cdlq3cJL.js +1 -0
- package/out/web/assets/{ganttDiagram-EL5Y4UJY-Da4ULXTl.js → ganttDiagram-EL5Y4UJY-DQLdsXrC.js} +1 -1
- package/out/web/assets/{gitGraph-4MIJSDKK-B9wNFZIP.js → gitGraph-4MIJSDKK-CL1OEOQ_.js} +1 -1
- package/out/web/assets/{gitGraphDiagram-WWUBYQGX-RjrhB0MP.js → gitGraphDiagram-WWUBYQGX-8cSi42H7.js} +1 -1
- package/out/web/assets/index-BocxnrDG.js +168 -0
- package/out/web/assets/index-yeh_r55a.css +1 -0
- package/out/web/assets/{info-A6RAGUB7-B3dfCpeY.js → info-A6RAGUB7-C1zsX5sc.js} +1 -1
- package/out/web/assets/{infoDiagram-27XIBGKW-QVWkLVx7.js → infoDiagram-27XIBGKW-DsRYtIyI.js} +1 -1
- package/out/web/assets/{ishikawaDiagram-5VMMS53U-CLFNIRI9.js → ishikawaDiagram-5VMMS53U-B2crwIXj.js} +1 -1
- package/out/web/assets/{journeyDiagram-3NMN7TZE-fgOQadYF.js → journeyDiagram-3NMN7TZE-BTH-GyVR.js} +1 -1
- package/out/web/assets/{kanban-definition-UXKFOSKX-G3Q_9g9O.js → kanban-definition-UXKFOSKX-BeRfCnuA.js} +1 -1
- package/out/web/assets/{mermaid-parser.core-v3Jm7nco.js → mermaid-parser.core-BJwgCBBc.js} +3 -3
- package/out/web/assets/{mermaid.core-DTEjLUA1.js → mermaid.core-CsDDodN8.js} +4 -4
- package/out/web/assets/{mindmap-definition-YA3MSWOX-C_D42_fF.js → mindmap-definition-YA3MSWOX-B42efOQ1.js} +1 -1
- package/out/web/assets/{modelManager-BPLycQrN.js → modelManager-B3ZFMh8v.js} +2 -2
- package/out/web/assets/{oauthManager-BUK7ic7q.js → oauthManager-Ch5Du2fF.js} +1 -1
- package/out/web/assets/{packet-AYTQ26CC-B-R-SHlF.js → packet-AYTQ26CC-B6xUyE6r.js} +1 -1
- package/out/web/assets/{pegDiagram-XKGWAZYB-Da2q_giz.js → pegDiagram-XKGWAZYB-1LabVycL.js} +1 -1
- package/out/web/assets/{pie-WAS4IAKB-BC8F0N7-.js → pie-WAS4IAKB-DJwo-nf_.js} +1 -1
- package/out/web/assets/{pieDiagram-E7YTZNPT-Iy9REJNC.js → pieDiagram-E7YTZNPT-icmAqzy4.js} +1 -1
- package/out/web/assets/{quadrantDiagram-AXDQQJYC-ztsiYw7h.js → quadrantDiagram-AXDQQJYC-CZ-wEx41.js} +1 -1
- package/out/web/assets/{radar-RG4KPBEZ-B_1P8Z_z.js → radar-RG4KPBEZ-D7d-Xriw.js} +1 -1
- package/out/web/assets/{railroad-74A4TZTK-DuTqczSo.js → railroad-74A4TZTK-viuhdYbs.js} +1 -1
- package/out/web/assets/{railroad-abnf-HS5TGJTU-Df29WLmp.js → railroad-abnf-HS5TGJTU-DNXiCNea.js} +1 -1
- package/out/web/assets/{railroad-ebnf-LZEXJU2U-ePFMo-qp.js → railroad-ebnf-LZEXJU2U-nkSu1-0C.js} +1 -1
- package/out/web/assets/{railroad-peg-WCYAUIDC-DYXLW4_E.js → railroad-peg-WCYAUIDC-BhbMeQzz.js} +1 -1
- package/out/web/assets/{railroadDiagram-O6MQD6OU-LStnZf2S.js → railroadDiagram-O6MQD6OU-CLpG1jUX.js} +1 -1
- package/out/web/assets/{requirementDiagram-BXWQKSXE-DmzonMH-.js → requirementDiagram-BXWQKSXE-kRDrvWrc.js} +1 -1
- package/out/web/assets/{sankeyDiagram-P5KCCOFB-B8vjmUU1.js → sankeyDiagram-P5KCCOFB-DxAwmq4x.js} +1 -1
- package/out/web/assets/{sequenceDiagram-WJ2MYXX4-CTnplOAX.js → sequenceDiagram-WJ2MYXX4-aLgY-6Wz.js} +1 -1
- package/out/web/assets/{stateDiagram-D77RDMKH-BFrIaLdI.js → stateDiagram-D77RDMKH-D5QWfOhp.js} +1 -1
- package/out/web/assets/stateDiagram-v2-MP3YSRHH-D6OiZoAP.js +1 -0
- package/out/web/assets/{swimlanes-42K2YHIH-BXGngUNU.js → swimlanes-42K2YHIH-CRs5UyA-.js} +1 -1
- package/out/web/assets/swimlanesDiagram-VR7AAH4N-UgEXIsV0.js +8 -0
- package/out/web/assets/syntaxHighlight-C-wAGT84.js +3 -0
- package/out/web/assets/{timeline-definition-24CTP7MA-CegH7n43.js → timeline-definition-24CTP7MA-Denqd9qb.js} +1 -1
- package/out/web/assets/{treeView-Q6P3EWNA-DTpJv2Tw.js → treeView-Q6P3EWNA-0my3Z3s4.js} +1 -1
- package/out/web/assets/{treemap-WGGIJYW6-i8M9iJU6.js → treemap-WGGIJYW6-B_EjkLYq.js} +1 -1
- package/out/web/assets/{vennDiagram-4TSXK5OY-Dpzo1S8U.js → vennDiagram-4TSXK5OY-DxVg3Ewr.js} +1 -1
- package/out/web/assets/{wardley-WFR3VGLG-BrNsgtfw.js → wardley-WFR3VGLG-CGD-Tj4p.js} +1 -1
- package/out/web/assets/{wardleyDiagram-VM6X3IG4-lQ92LFE1.js → wardleyDiagram-VM6X3IG4-CmfS39Xm.js} +1 -1
- package/out/web/assets/{xychartDiagram-S5SC5T6Z-BaOaEoBd.js → xychartDiagram-S5SC5T6Z-BVM9bKis.js} +1 -1
- package/out/web/index-web.html +2 -2
- package/out/web/index.html +2 -2
- package/package.json +2 -2
- package/shared-modules/CODEOWNERS +3 -3
- package/shared-modules/SDL2/SDL2_mixer.json +27 -0
- package/shared-modules/appstream/README.md +13 -0
- package/shared-modules/appstream/appstream-compose.json +111 -0
- package/shared-modules/dbus-glib/dbus-glib.json +2 -2
- package/shared-modules/libportal/libportal.json +23 -0
- package/shared-modules/linux-audio/fluidsynth2-static.json +2 -2
- package/shared-modules/linux-audio/fluidsynth2.json +2 -2
- package/shared-modules/linux-audio/libinstpatch.json +2 -2
- package/shared-modules/linux-audio/liblo-static.json +3 -0
- package/shared-modules/luajit/luajit.json +2 -2
- package/shared-modules/squashfs-tools/squashfs-tools.json +0 -3
- package/slash-commands.json +7 -2
- package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/src/renderer/shared/agentProgress.ts +51 -3
- package/src/renderer/shared/components/Settings/AutomationTab.tsx +2 -56
- package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +15 -1
- package/src/renderer/shared/components/Settings/GeneralTab.tsx +25 -12
- package/src/renderer/shared/components/Settings/ThemeTab.test.tsx +45 -0
- package/src/renderer/shared/components/Settings/ThemeTab.tsx +106 -3
- package/src/renderer/shared/components/activity/AgentActivityDrawer.tsx +67 -17
- package/src/renderer/shared/components/activity/AgentActivityTable.tsx +376 -134
- package/src/renderer/shared/components/activity/AskUserActivityCard.test.tsx +122 -0
- package/src/renderer/shared/components/activity/AskUserActivityCard.tsx +70 -0
- package/src/renderer/shared/components/activity/McpToolResults.tsx +39 -2
- package/src/renderer/shared/components/activity/SubagentDagView.tsx +7 -7
- package/src/renderer/shared/components/activity/ViewedImages.tsx +41 -2
- package/src/renderer/shared/components/app/ChunkErrorBoundary.tsx +3 -3
- package/src/renderer/shared/components/app/CommandPalette.tsx +7 -7
- package/src/renderer/shared/components/app/DesktopTitlebar.tsx +2 -2
- package/src/renderer/shared/components/app/MintDashboard.tsx +27 -17
- package/src/renderer/shared/components/app/ModalErrorBoundary.tsx +3 -3
- package/src/renderer/shared/components/cards/CalculationCard.tsx +3 -3
- package/src/renderer/shared/components/cards/ImageGenCard.tsx +2 -2
- package/src/renderer/shared/components/cards/ImageSearchCard.tsx +2 -2
- package/src/renderer/shared/components/cards/MermaidCard.tsx +1 -1
- package/src/renderer/shared/components/cards/PlanCard.test.tsx +41 -0
- package/src/renderer/shared/components/cards/PlanCard.tsx +32 -0
- package/src/renderer/shared/components/cards/ReleaseNotesCard.test.tsx +29 -0
- package/src/renderer/shared/components/cards/ReleaseNotesCard.tsx +137 -0
- package/src/renderer/shared/components/cards/StockCard.tsx +7 -7
- package/src/renderer/shared/components/cards/ToolResultCards.tsx +11 -3
- package/src/renderer/shared/components/cards/UiMockupWidget.tsx +4 -4
- package/src/renderer/shared/components/cards/WeatherCard.tsx +5 -5
- package/src/renderer/shared/components/chat/ApprovalCard.test.tsx +11 -0
- package/src/renderer/shared/components/chat/ApprovalCard.tsx +21 -2
- package/src/renderer/shared/components/chat/ArtifactCards.test.tsx +69 -0
- package/src/renderer/shared/components/chat/ArtifactCards.tsx +238 -0
- package/src/renderer/shared/components/chat/AttachedDocumentCard.test.tsx +39 -0
- package/src/renderer/shared/components/chat/AttachedDocumentCard.tsx +220 -0
- package/src/renderer/shared/components/chat/ChatCodeBlock.test.tsx +33 -0
- package/src/renderer/shared/components/chat/ChatCodeBlock.tsx +15 -1
- package/src/renderer/shared/components/chat/ChatMessageItem.test.tsx +40 -2
- package/src/renderer/shared/components/chat/ChatMessageItem.tsx +180 -34
- package/src/renderer/shared/components/chat/ChatModeSelector.css +227 -0
- package/src/renderer/shared/components/chat/ChatModeSelector.test.tsx +45 -0
- package/src/renderer/shared/components/chat/ChatModeSelector.tsx +198 -0
- package/src/renderer/shared/components/chat/ChatPanel.test.tsx +22 -0
- package/src/renderer/shared/components/chat/ChatPanel.tsx +227 -53
- package/src/renderer/shared/components/chat/DiffReviewModal.tsx +6 -6
- package/src/renderer/shared/components/chat/GeminiLiveOverlay.test.tsx +142 -1
- package/src/renderer/shared/components/chat/GeminiLiveOverlay.tsx +45 -3
- package/src/renderer/shared/components/chat/ModelSelectorPopover.tsx +42 -14
- package/src/renderer/shared/components/chat/RewindModal.tsx +10 -10
- package/src/renderer/shared/components/chat/SlashSuggestions.test.tsx +14 -0
- package/src/renderer/shared/components/chat/SourcesBlock.test.tsx +53 -0
- package/src/renderer/shared/components/chat/SourcesBlock.tsx +236 -90
- package/src/renderer/shared/components/chat/TurnFileChanges.test.tsx +45 -1
- package/src/renderer/shared/components/chat/TurnFileChanges.tsx +202 -169
- package/src/renderer/shared/components/extensions/CliSessionsView.tsx +5 -4
- package/src/renderer/shared/components/extensions/McpRegistryPicker.tsx +3 -3
- package/src/renderer/shared/components/studio/LibraryPage.tsx +48 -5
- package/src/renderer/shared/components/workspace/ArtifactPreviewPanel.tsx +125 -13
- package/src/renderer/shared/components/workspace/CodeReviewPage.test.tsx +50 -0
- package/src/renderer/shared/components/workspace/CodeReviewPage.tsx +77 -16
- package/src/renderer/shared/components/workspace/GitBranchSelector.tsx +78 -22
- package/src/renderer/shared/components/workspace/ToolSurfacePage.test.tsx +13 -0
- package/src/renderer/shared/components/workspace/ToolSurfacePage.tsx +48 -28
- package/src/renderer/shared/components/workspace/WorkspacePdfPreview.tsx +266 -47
- package/src/renderer/shared/components/workspace/WorkspacePreviewActions.test.tsx +18 -6
- package/src/renderer/shared/components/workspace/background-terminals.css +11 -11
- package/src/renderer/shared/constants/config.ts +1 -5
- package/src/renderer/shared/constants/models.test.ts +51 -0
- package/src/renderer/shared/constants/models.ts +139 -32
- package/src/renderer/shared/conversation/lifecycle.test.ts +91 -3
- package/src/renderer/shared/conversation/lifecycle.ts +104 -5
- package/src/renderer/shared/conversation/progressiveStream.test.ts +83 -0
- package/src/renderer/shared/conversation/progressiveStream.ts +219 -0
- package/src/renderer/shared/css/agent-observability.css +133 -0
- package/src/renderer/shared/css/chat-ui-cards.css +13 -13
- package/src/renderer/shared/css/code-review.css +63 -34
- package/src/renderer/shared/css/code-sessions.css +47 -18
- package/src/renderer/shared/css/collapsed-paste.css +1 -1
- package/src/renderer/shared/css/error-notice.css +1 -1
- package/src/renderer/shared/css/file-changes.css +165 -80
- package/src/renderer/shared/css/library.css +105 -10
- package/src/renderer/shared/css/management-views.css +1 -1
- package/src/renderer/shared/css/mcp-results.css +5 -5
- package/src/renderer/shared/css/model-selector.css +18 -18
- package/src/renderer/shared/css/mods.css +7 -7
- package/src/renderer/shared/css/notification-notice.css +2 -2
- package/src/renderer/shared/css/queued-messages.css +5 -5
- package/src/renderer/shared/css/settings/general.css +18 -13
- package/src/renderer/shared/css/settings/profile.css +5 -5
- package/src/renderer/shared/css/settings/theme.css +5 -5
- package/src/renderer/shared/css/slash-choice.css +2 -2
- package/src/renderer/shared/css/slash-suggestions.css +3 -3
- package/src/renderer/shared/css/sources-block.css +41 -2
- package/src/renderer/shared/css/tools-panel.css +2 -2
- package/src/renderer/shared/css/ui-tailwind.css +8 -0
- package/src/renderer/shared/css/veo-studio.css +2 -2
- package/src/renderer/shared/css/viewed-images.css +7 -7
- package/src/renderer/shared/platform.ts +2 -1
- package/src/renderer/shared/theme/themeManager.test.ts +17 -0
- package/src/renderer/shared/theme/themeManager.ts +21 -4
- package/src/renderer/shared/theme/themes.ts +54 -0
- package/src/renderer/shared/theme/tokens.css +6 -4
- package/src/renderer/shared/types.ts +1 -1
- package/src/renderer/shared/utils/agentActivity.test.ts +468 -2
- package/src/renderer/shared/utils/agentActivity.ts +602 -35
- package/src/renderer/shared/utils/artifactBrowser.test.ts +37 -32
- package/src/renderer/shared/utils/artifactBrowser.ts +17 -19
- package/src/renderer/shared/utils/attachedDocument.test.ts +73 -0
- package/src/renderer/shared/utils/attachedDocument.ts +49 -0
- package/src/renderer/shared/utils/fileIcons.test.ts +59 -0
- package/src/renderer/shared/utils/fileIcons.ts +149 -16
- package/src/renderer/shared/utils/markdown.tsx +72 -19
- package/src/renderer/shared/utils/markdown.webImages.test.tsx +16 -0
- package/src/renderer/shared/utils/mcpResults.test.tsx +29 -0
- package/src/renderer/shared/utils/slashCommandProcessor.ts +4 -1
- package/src/renderer/shared/utils/syntaxHighlight.test.tsx +11 -1
- package/src/renderer/shared/utils/syntaxHighlight.tsx +51 -3
- package/src/renderer/shared/utils/useGeminiLiveVoice.ts +324 -51
- package/src/renderer/shared/utils/workspaceDrag.test.ts +153 -0
- package/src/renderer/shared/utils/workspaceDrag.ts +142 -0
- package/src/renderer/shared/utils/workspaceMedia.ts +10 -2
- package/src/renderer/src/App.tsx +14 -8
- package/src/renderer/src/agentProgress.ts +1 -0
- package/src/renderer/src/components/ScreenPicker.css +1 -1
- package/src/renderer/src/components/WorkspacePanel.tsx +6 -5
- package/src/renderer/src/css/app-shell.css +4 -4
- package/src/renderer/src/css/chat.css +1261 -241
- package/src/renderer/src/css/desktop-tools.css +11 -11
- package/src/renderer/src/css/sidebar-workspace.css +2 -2
- package/src/renderer/src/css/tool-surfaces.css +12 -12
- package/src/renderer/src/index.css +38 -20
- package/src/renderer/src/tauri.ts +22 -2
- package/src/renderer/src-web/App.tsx +14 -0
- package/src/renderer/src-web/agentProgress.ts +1 -0
- package/src/renderer/src-web/css/app-shell.css +4 -4
- package/src/renderer/src-web/css/chat.css +1278 -190
- package/src/renderer/src-web/css/mobile.css +29 -13
- package/src/renderer/src-web/css/settings/mobile.css +2 -2
- package/src/renderer/src-web/css/sidebar-workspace.css +1 -1
- package/src/renderer/src-web/index.css +38 -20
- package/src/renderer/src-web/tauri.ts +22 -2
- package/src/renderer/tests/browserArtifacts.browser.tsx +1 -1
- package/src/renderer/tests/library.browser.tsx +3 -0
- package/src/renderer/tests/liveVoice.browser.html +1 -0
- package/src/renderer/tests/workspaceDrop.browser.tsx +1 -1
- package/src-tauri/src/app/lifecycle.rs +1 -14
- package/src-tauri/src/background/headless.rs +14 -8
- package/src-tauri/src/commands/conversation.rs +38 -0
- package/src-tauri/src/native/mod.rs +0 -1
- package/src-tauri/src/native/system.rs +4 -47
- package/crates/mint-cli/src/interactive/chat_tui.rs +0 -8855
- package/crates/mint-core/src/agent/chat.rs +0 -4394
- package/crates/mint-core/src/browser/lifecycle.rs +0 -291
- package/crates/mint-core/src/browser/logging.rs +0 -20
- package/crates/mint-core/src/orchestration/tools/browser.rs +0 -31
- package/out/web/assets/ArtifactPreviewPanel-S0dPfYFx.js +0 -2
- package/out/web/assets/CalculationCard-CRjP3E1j.js +0 -1
- package/out/web/assets/CliSessionsView-C3Br2v5Y.css +0 -1
- package/out/web/assets/CodeReviewPage-CUJceQme.css +0 -1
- package/out/web/assets/CodeReviewPage-VCUgPla_.js +0 -2
- package/out/web/assets/ImageGenCard-BCXxkVJX.js +0 -1
- package/out/web/assets/ImageSearchCard-N3yQOr8Z.js +0 -1
- package/out/web/assets/LibraryPage-DAxUTAg7.css +0 -1
- package/out/web/assets/LibraryPage-WlviRdR8.js +0 -2
- package/out/web/assets/LinkedFoldersView-CKRgroWK.js +0 -1
- package/out/web/assets/McpServersView-D3wHnuHg.js +0 -1
- package/out/web/assets/MermaidCard-NqrHdyJW.js +0 -2
- package/out/web/assets/MintDashboard-B2DJsDDO.css +0 -1
- package/out/web/assets/MintDashboard-COw_xol7.js +0 -63
- package/out/web/assets/RewindModal-DempuDod.js +0 -1
- package/out/web/assets/SettingsWindow-2YP3yj7s.js +0 -4
- package/out/web/assets/SettingsWindow-Dz8LQVgD.css +0 -1
- package/out/web/assets/StockCard-BDMCe7mx.js +0 -1
- package/out/web/assets/ToolSurfacePage-B0J_q0Jl.js +0 -38
- package/out/web/assets/ToolSurfacePage-CRIQ1owD.css +0 -1
- package/out/web/assets/UiMockupWidget-DD73QWg1.js +0 -1
- package/out/web/assets/WeatherCard-CPucIfq8.js +0 -1
- package/out/web/assets/WorkspacePdfPreview-Dx_lkjNu.js +0 -2
- package/out/web/assets/classDiagram-ZZMXUADV-BgJ5WtSp.js +0 -1
- package/out/web/assets/classDiagram-v2-VYDZK3BY-BgJ5WtSp.js +0 -1
- package/out/web/assets/config-CvIO5hkn.js +0 -2
- package/out/web/assets/flowDiagram-HODETNUW-uqCHJond.js +0 -1
- package/out/web/assets/index-BmpulIkg.js +0 -168
- package/out/web/assets/index-CkvBwhX_.css +0 -1
- package/out/web/assets/stateDiagram-v2-MP3YSRHH-uf3kdNW4.js +0 -1
- package/out/web/assets/swimlanesDiagram-VR7AAH4N-Y8q5bQce.js +0 -8
- package/shared-modules/libsecret/libsecret.json +0 -23
- package/shared-modules/libusb/libusb.json +0 -27
- package/shared-modules/lzo/lzo.json +0 -27
- package/src/renderer/src/components/BrowserShell.tsx +0 -108
- package/src/renderer/src/components/BrowserSuggestionsPopup.tsx +0 -91
- package/src/renderer/src/components/browser-shell.css +0 -185
- package/src-tauri/src/native/browser.rs +0 -252
|
@@ -18,8 +18,11 @@ use std::net::{TcpStream, ToSocketAddrs};
|
|
|
18
18
|
use std::process::Command;
|
|
19
19
|
use std::sync::mpsc;
|
|
20
20
|
use std::time::Duration;
|
|
21
|
+
use unicode_width::UnicodeWidthStr;
|
|
21
22
|
|
|
22
|
-
use crate::terminal_theme::{
|
|
23
|
+
use crate::terminal_theme::{
|
|
24
|
+
self, ACCENT, BLUE, MUTED, SELECTION_BACKGROUND, SELECTION_TEXT, SUBTLE, TEXT,
|
|
25
|
+
};
|
|
23
26
|
use mint_core::slash::models::HUGGINGFACE_MODEL_PRESETS;
|
|
24
27
|
use mint_core::{MintConfig, load_config, save_config};
|
|
25
28
|
|
|
@@ -2232,10 +2235,10 @@ impl OnboardWizard {
|
|
|
2232
2235
|
let block = Block::default()
|
|
2233
2236
|
.borders(Borders::ALL)
|
|
2234
2237
|
.border_type(BorderType::Rounded)
|
|
2235
|
-
.border_style(Style::default().fg(
|
|
2238
|
+
.border_style(Style::default().fg(SUBTLE))
|
|
2236
2239
|
.title(Span::styled(
|
|
2237
2240
|
" Mint Setup Wizard ",
|
|
2238
|
-
Style::default().fg(
|
|
2241
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2239
2242
|
));
|
|
2240
2243
|
|
|
2241
2244
|
let paragraph = Paragraph::new(header_line)
|
|
@@ -2250,14 +2253,14 @@ impl OnboardWizard {
|
|
|
2250
2253
|
Span::styled(
|
|
2251
2254
|
format!(" [{title}] "),
|
|
2252
2255
|
Style::default()
|
|
2253
|
-
.fg(
|
|
2254
|
-
.bg(
|
|
2256
|
+
.fg(SELECTION_TEXT)
|
|
2257
|
+
.bg(SELECTION_BACKGROUND)
|
|
2255
2258
|
.add_modifier(Modifier::BOLD),
|
|
2256
2259
|
)
|
|
2257
2260
|
} else if is_done {
|
|
2258
2261
|
Span::styled(
|
|
2259
2262
|
format!(" ✔ {title} "),
|
|
2260
|
-
Style::default().fg(
|
|
2263
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2261
2264
|
)
|
|
2262
2265
|
} else {
|
|
2263
2266
|
Span::styled(format!(" {title} "), Style::default().fg(MUTED))
|
|
@@ -2275,7 +2278,7 @@ impl OnboardWizard {
|
|
|
2275
2278
|
.border_style(Style::default().fg(SUBTLE))
|
|
2276
2279
|
.title(Span::styled(
|
|
2277
2280
|
" Step 1: Core AI (Google Gemini) ",
|
|
2278
|
-
Style::default().fg(
|
|
2281
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2279
2282
|
));
|
|
2280
2283
|
|
|
2281
2284
|
let inner = block.inner(area);
|
|
@@ -2301,19 +2304,25 @@ impl OnboardWizard {
|
|
|
2301
2304
|
frame.render_widget(subtitle, chunks[0]);
|
|
2302
2305
|
|
|
2303
2306
|
// Key Input Box
|
|
2304
|
-
let
|
|
2305
|
-
|
|
2307
|
+
let is_key_focused = self.gemini_focus == 0;
|
|
2308
|
+
let mut key_spans = Vec::new();
|
|
2309
|
+
if self.gemini_key.is_empty() {
|
|
2310
|
+
key_spans.push(Span::styled(
|
|
2306
2311
|
"(Paste your Gemini API key here with Ctrl+V)",
|
|
2307
2312
|
Style::default().fg(MUTED),
|
|
2308
|
-
)
|
|
2313
|
+
));
|
|
2309
2314
|
} else if self.gemini_masked {
|
|
2310
|
-
Span::styled(
|
|
2315
|
+
key_spans.push(Span::styled(
|
|
2311
2316
|
"•".repeat(self.gemini_key.chars().count().min(50)),
|
|
2312
2317
|
Style::default().fg(TEXT),
|
|
2313
|
-
)
|
|
2318
|
+
));
|
|
2314
2319
|
} else {
|
|
2315
|
-
Span::styled(&self.gemini_key, Style::default().fg(TEXT))
|
|
2316
|
-
}
|
|
2320
|
+
key_spans.push(Span::styled(&self.gemini_key, Style::default().fg(TEXT)));
|
|
2321
|
+
}
|
|
2322
|
+
if is_key_focused {
|
|
2323
|
+
key_spans.push(Span::styled("█", Style::default().fg(TEXT)));
|
|
2324
|
+
}
|
|
2325
|
+
let key_disp = Line::from(key_spans);
|
|
2317
2326
|
|
|
2318
2327
|
let mask_hint = if self.gemini_masked {
|
|
2319
2328
|
"[Ctrl+H: Show]"
|
|
@@ -2321,38 +2330,60 @@ impl OnboardWizard {
|
|
|
2321
2330
|
"[Ctrl+H: Hide]"
|
|
2322
2331
|
};
|
|
2323
2332
|
|
|
2324
|
-
let key_border_color = if
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
SUBTLE
|
|
2328
|
-
};
|
|
2329
|
-
let key_block = Block::default()
|
|
2330
|
-
.borders(Borders::ALL)
|
|
2331
|
-
.border_type(BorderType::Rounded)
|
|
2332
|
-
.border_style(Style::default().fg(key_border_color))
|
|
2333
|
-
.title(Line::from(vec![
|
|
2333
|
+
let key_border_color = if is_key_focused { TEXT } else { SUBTLE };
|
|
2334
|
+
let key_title = if is_key_focused {
|
|
2335
|
+
Line::from(vec![
|
|
2334
2336
|
Span::styled(
|
|
2335
2337
|
" API Key ",
|
|
2338
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2339
|
+
),
|
|
2340
|
+
Span::styled(
|
|
2341
|
+
" [ EDITING ] ",
|
|
2336
2342
|
Style::default()
|
|
2337
|
-
.fg(
|
|
2343
|
+
.fg(SELECTION_TEXT)
|
|
2344
|
+
.bg(SELECTION_BACKGROUND)
|
|
2338
2345
|
.add_modifier(Modifier::BOLD),
|
|
2339
2346
|
),
|
|
2347
|
+
Span::raw(" "),
|
|
2340
2348
|
Span::styled(mask_hint, Style::default().fg(BLUE)),
|
|
2341
|
-
])
|
|
2349
|
+
])
|
|
2350
|
+
} else if !self.gemini_key.is_empty() {
|
|
2351
|
+
Line::from(vec![
|
|
2352
|
+
Span::styled(
|
|
2353
|
+
" ✔ API Key (Configured · Tab to edit) ",
|
|
2354
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2355
|
+
),
|
|
2356
|
+
Span::styled(mask_hint, Style::default().fg(MUTED)),
|
|
2357
|
+
])
|
|
2358
|
+
} else {
|
|
2359
|
+
Line::from(vec![
|
|
2360
|
+
Span::styled(" API Key (Tab to edit) ", Style::default().fg(MUTED)),
|
|
2361
|
+
Span::styled(mask_hint, Style::default().fg(MUTED)),
|
|
2362
|
+
])
|
|
2363
|
+
};
|
|
2364
|
+
|
|
2365
|
+
let key_block = Block::default()
|
|
2366
|
+
.borders(Borders::ALL)
|
|
2367
|
+
.border_type(BorderType::Rounded)
|
|
2368
|
+
.border_style(Style::default().fg(key_border_color))
|
|
2369
|
+
.title(key_title);
|
|
2342
2370
|
|
|
2343
2371
|
frame.render_widget(Paragraph::new(key_disp).block(key_block), chunks[1]);
|
|
2344
2372
|
|
|
2345
2373
|
// Tip line
|
|
2374
|
+
let tip_text = if is_key_focused {
|
|
2375
|
+
"Paste with Ctrl+V. Press [Enter] or [Tab] to switch to model list."
|
|
2376
|
+
} else {
|
|
2377
|
+
"Use [↑/↓] to select a model. Press [Enter] to continue, or [Tab] to edit API key."
|
|
2378
|
+
};
|
|
2346
2379
|
let tip_line = Line::from(vec![
|
|
2347
2380
|
Span::styled("• Tip: ", Style::default().fg(MUTED)),
|
|
2348
|
-
Span::styled(
|
|
2349
|
-
"You can paste from clipboard with Ctrl+V. Press Tab or ↓ to jump to model list.",
|
|
2350
|
-
Style::default().fg(MUTED),
|
|
2351
|
-
),
|
|
2381
|
+
Span::styled(tip_text, Style::default().fg(MUTED)),
|
|
2352
2382
|
]);
|
|
2353
2383
|
frame.render_widget(Paragraph::new(tip_line), chunks[2]);
|
|
2354
2384
|
|
|
2355
2385
|
// Vertical Model List
|
|
2386
|
+
let is_model_focused = self.gemini_focus == 1;
|
|
2356
2387
|
let model_items: Vec<ListItem> = self
|
|
2357
2388
|
.gemini_models
|
|
2358
2389
|
.iter()
|
|
@@ -2360,7 +2391,7 @@ impl OnboardWizard {
|
|
|
2360
2391
|
.map(|(i, model)| {
|
|
2361
2392
|
let is_sel = i == self.gemini_model_idx;
|
|
2362
2393
|
let radio = if is_sel { " ◉ " } else { " ○ " };
|
|
2363
|
-
let cursor = if is_sel { "
|
|
2394
|
+
let cursor = if is_sel { " › " } else { " " };
|
|
2364
2395
|
|
|
2365
2396
|
let desc = match model.as_str() {
|
|
2366
2397
|
"gemini-2.5-flash" => "Recommended · Ultra-fast, multipurpose, thinking",
|
|
@@ -2373,25 +2404,58 @@ impl OnboardWizard {
|
|
|
2373
2404
|
_ => "",
|
|
2374
2405
|
};
|
|
2375
2406
|
|
|
2376
|
-
|
|
2377
|
-
|
|
2407
|
+
if is_model_focused && is_sel {
|
|
2408
|
+
let line = Line::from(vec![
|
|
2409
|
+
Span::styled(
|
|
2410
|
+
cursor,
|
|
2411
|
+
Style::default()
|
|
2412
|
+
.fg(SELECTION_TEXT)
|
|
2413
|
+
.bg(SELECTION_BACKGROUND)
|
|
2414
|
+
.add_modifier(Modifier::BOLD),
|
|
2415
|
+
),
|
|
2416
|
+
Span::styled(
|
|
2417
|
+
radio,
|
|
2418
|
+
Style::default()
|
|
2419
|
+
.fg(SELECTION_TEXT)
|
|
2420
|
+
.bg(SELECTION_BACKGROUND)
|
|
2421
|
+
.add_modifier(Modifier::BOLD),
|
|
2422
|
+
),
|
|
2423
|
+
Span::styled(
|
|
2424
|
+
format!("{:<20}", model),
|
|
2425
|
+
Style::default()
|
|
2426
|
+
.fg(SELECTION_TEXT)
|
|
2427
|
+
.bg(SELECTION_BACKGROUND)
|
|
2428
|
+
.add_modifier(Modifier::BOLD),
|
|
2429
|
+
),
|
|
2430
|
+
Span::styled(
|
|
2431
|
+
" ",
|
|
2432
|
+
Style::default().fg(SELECTION_TEXT).bg(SELECTION_BACKGROUND),
|
|
2433
|
+
),
|
|
2434
|
+
Span::styled(
|
|
2435
|
+
desc,
|
|
2436
|
+
Style::default().fg(SELECTION_TEXT).bg(SELECTION_BACKGROUND),
|
|
2437
|
+
),
|
|
2438
|
+
]);
|
|
2439
|
+
ListItem::new(line).style(Style::default().bg(SELECTION_BACKGROUND))
|
|
2440
|
+
} else if is_sel {
|
|
2441
|
+
let line = Line::from(vec![
|
|
2442
|
+
Span::styled(" › ", Style::default().fg(SUBTLE)),
|
|
2443
|
+
Span::styled(radio, Style::default().fg(SUBTLE)),
|
|
2444
|
+
Span::styled(format!("{:<20}", model), Style::default().fg(TEXT)),
|
|
2445
|
+
Span::raw(" "),
|
|
2446
|
+
Span::styled(format!("{desc} (selected)"), Style::default().fg(MUTED)),
|
|
2447
|
+
]);
|
|
2448
|
+
ListItem::new(line)
|
|
2378
2449
|
} else {
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
.add_modifier(Modifier::BOLD),
|
|
2389
|
-
),
|
|
2390
|
-
Span::styled(format!("{:<20}", model), name_style),
|
|
2391
|
-
Span::raw(" "),
|
|
2392
|
-
Span::styled(desc, Style::default().fg(MUTED)),
|
|
2393
|
-
]);
|
|
2394
|
-
ListItem::new(line)
|
|
2450
|
+
let line = Line::from(vec![
|
|
2451
|
+
Span::raw(" "),
|
|
2452
|
+
Span::styled(radio, Style::default().fg(MUTED)),
|
|
2453
|
+
Span::styled(format!("{:<20}", model), Style::default().fg(TEXT)),
|
|
2454
|
+
Span::raw(" "),
|
|
2455
|
+
Span::styled(desc, Style::default().fg(MUTED)),
|
|
2456
|
+
]);
|
|
2457
|
+
ListItem::new(line)
|
|
2458
|
+
}
|
|
2395
2459
|
})
|
|
2396
2460
|
.collect();
|
|
2397
2461
|
|
|
@@ -2408,27 +2472,44 @@ impl OnboardWizard {
|
|
|
2408
2472
|
)
|
|
2409
2473
|
};
|
|
2410
2474
|
|
|
2411
|
-
let model_border_color = if
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
.border_type(BorderType::Rounded)
|
|
2419
|
-
.border_style(Style::default().fg(model_border_color))
|
|
2420
|
-
.title(Line::from(vec![
|
|
2475
|
+
let model_border_color = if is_model_focused { TEXT } else { SUBTLE };
|
|
2476
|
+
let model_title = if is_model_focused {
|
|
2477
|
+
Line::from(vec![
|
|
2478
|
+
Span::styled(
|
|
2479
|
+
" Default Model ",
|
|
2480
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2481
|
+
),
|
|
2421
2482
|
Span::styled(
|
|
2422
|
-
"
|
|
2483
|
+
" [ SELECTING ] ",
|
|
2423
2484
|
Style::default()
|
|
2424
|
-
.fg(
|
|
2485
|
+
.fg(SELECTION_TEXT)
|
|
2486
|
+
.bg(SELECTION_BACKGROUND)
|
|
2425
2487
|
.add_modifier(Modifier::BOLD),
|
|
2426
2488
|
),
|
|
2489
|
+
Span::styled(" (↑/↓ to choose) ", Style::default().fg(MUTED)),
|
|
2427
2490
|
Span::styled(
|
|
2428
2491
|
format!(" {model_status} "),
|
|
2429
2492
|
Style::default().fg(if self.is_verifying { ACCENT } else { BLUE }),
|
|
2430
2493
|
),
|
|
2431
|
-
])
|
|
2494
|
+
])
|
|
2495
|
+
} else {
|
|
2496
|
+
Line::from(vec![
|
|
2497
|
+
Span::styled(
|
|
2498
|
+
" Default Model (Press Tab or ↓ to select) ",
|
|
2499
|
+
Style::default().fg(MUTED),
|
|
2500
|
+
),
|
|
2501
|
+
Span::styled(
|
|
2502
|
+
format!(" {model_status} "),
|
|
2503
|
+
Style::default().fg(if self.is_verifying { ACCENT } else { BLUE }),
|
|
2504
|
+
),
|
|
2505
|
+
])
|
|
2506
|
+
};
|
|
2507
|
+
|
|
2508
|
+
let list_block = Block::default()
|
|
2509
|
+
.borders(Borders::ALL)
|
|
2510
|
+
.border_type(BorderType::Rounded)
|
|
2511
|
+
.border_style(Style::default().fg(model_border_color))
|
|
2512
|
+
.title(model_title);
|
|
2432
2513
|
|
|
2433
2514
|
let mut list_state = ListState::default();
|
|
2434
2515
|
list_state.select(Some(self.gemini_model_idx));
|
|
@@ -2440,38 +2521,79 @@ impl OnboardWizard {
|
|
|
2440
2521
|
|
|
2441
2522
|
// Custom Model Input Box
|
|
2442
2523
|
if self.is_custom_gemini_model {
|
|
2524
|
+
let is_custom_focused = self.gemini_focus == 1;
|
|
2525
|
+
let custom_border_color = if is_custom_focused { TEXT } else { SUBTLE };
|
|
2526
|
+
let custom_title = if is_custom_focused {
|
|
2527
|
+
Line::from(vec![
|
|
2528
|
+
Span::styled(
|
|
2529
|
+
" Custom Model Identifier ",
|
|
2530
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2531
|
+
),
|
|
2532
|
+
Span::styled(
|
|
2533
|
+
" [ EDITING ] ",
|
|
2534
|
+
Style::default()
|
|
2535
|
+
.fg(SELECTION_TEXT)
|
|
2536
|
+
.bg(SELECTION_BACKGROUND)
|
|
2537
|
+
.add_modifier(Modifier::BOLD),
|
|
2538
|
+
),
|
|
2539
|
+
])
|
|
2540
|
+
} else {
|
|
2541
|
+
Line::from(vec![Span::styled(
|
|
2542
|
+
" Custom Model Identifier ",
|
|
2543
|
+
Style::default().fg(MUTED),
|
|
2544
|
+
)])
|
|
2545
|
+
};
|
|
2443
2546
|
let custom_block = Block::default()
|
|
2444
2547
|
.borders(Borders::ALL)
|
|
2445
2548
|
.border_type(BorderType::Rounded)
|
|
2446
|
-
.border_style(Style::default().fg(
|
|
2447
|
-
.title(
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
let custom_val = if self.custom_gemini_model.is_empty() {
|
|
2452
|
-
Span::styled(
|
|
2549
|
+
.border_style(Style::default().fg(custom_border_color))
|
|
2550
|
+
.title(custom_title);
|
|
2551
|
+
let mut custom_spans = Vec::new();
|
|
2552
|
+
if self.custom_gemini_model.is_empty() {
|
|
2553
|
+
custom_spans.push(Span::styled(
|
|
2453
2554
|
"(Type custom model identifier, e.g. gemini-2.0-flash-exp)",
|
|
2454
2555
|
Style::default().fg(MUTED),
|
|
2455
|
-
)
|
|
2556
|
+
));
|
|
2456
2557
|
} else {
|
|
2457
|
-
Span::styled(
|
|
2458
|
-
|
|
2459
|
-
|
|
2558
|
+
custom_spans.push(Span::styled(
|
|
2559
|
+
&self.custom_gemini_model,
|
|
2560
|
+
Style::default().fg(TEXT),
|
|
2561
|
+
));
|
|
2562
|
+
}
|
|
2563
|
+
if is_custom_focused {
|
|
2564
|
+
custom_spans.push(Span::styled("█", Style::default().fg(TEXT)));
|
|
2565
|
+
}
|
|
2566
|
+
frame.render_widget(
|
|
2567
|
+
Paragraph::new(Line::from(custom_spans)).block(custom_block),
|
|
2568
|
+
chunks[4],
|
|
2569
|
+
);
|
|
2460
2570
|
}
|
|
2461
2571
|
|
|
2462
2572
|
// Bottom Action Hint
|
|
2463
|
-
let action_hint =
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
.fg(
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
)
|
|
2473
|
-
|
|
2474
|
-
|
|
2573
|
+
let action_hint = if is_key_focused {
|
|
2574
|
+
Paragraph::new(Line::from(vec![
|
|
2575
|
+
Span::styled(" [ Esc: Cancel ] ", Style::default().fg(MUTED)),
|
|
2576
|
+
Span::raw(" "),
|
|
2577
|
+
Span::styled(
|
|
2578
|
+
" [ Enter / Tab: Select Model ➔ ] ",
|
|
2579
|
+
Style::default().fg(TEXT),
|
|
2580
|
+
),
|
|
2581
|
+
]))
|
|
2582
|
+
.alignment(Alignment::Right)
|
|
2583
|
+
} else {
|
|
2584
|
+
Paragraph::new(Line::from(vec![
|
|
2585
|
+
Span::styled(" [ Tab: Back to API Key ] ", Style::default().fg(MUTED)),
|
|
2586
|
+
Span::raw(" "),
|
|
2587
|
+
Span::styled(
|
|
2588
|
+
" [ Enter: Continue to Services ➔ ] ",
|
|
2589
|
+
Style::default()
|
|
2590
|
+
.fg(SELECTION_TEXT)
|
|
2591
|
+
.bg(SELECTION_BACKGROUND)
|
|
2592
|
+
.add_modifier(Modifier::BOLD),
|
|
2593
|
+
),
|
|
2594
|
+
]))
|
|
2595
|
+
.alignment(Alignment::Right)
|
|
2596
|
+
};
|
|
2475
2597
|
frame.render_widget(action_hint, chunks[5]);
|
|
2476
2598
|
}
|
|
2477
2599
|
|
|
@@ -2486,7 +2608,7 @@ impl OnboardWizard {
|
|
|
2486
2608
|
.border_style(Style::default().fg(SUBTLE))
|
|
2487
2609
|
.title(Span::styled(
|
|
2488
2610
|
" Step 2: QuickStart Services & Providers ",
|
|
2489
|
-
Style::default().fg(
|
|
2611
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2490
2612
|
));
|
|
2491
2613
|
|
|
2492
2614
|
let inner = block.inner(area);
|
|
@@ -2511,20 +2633,12 @@ impl OnboardWizard {
|
|
|
2511
2633
|
// Build list items with category headers
|
|
2512
2634
|
let mut list_items = Vec::new();
|
|
2513
2635
|
let mut cur_category = "";
|
|
2636
|
+
let list_inner_width = chunks[1].width.saturating_sub(2) as usize;
|
|
2514
2637
|
|
|
2515
2638
|
for (i, svc) in self.services.iter().enumerate() {
|
|
2516
2639
|
let is_cursor = i == self.service_cursor;
|
|
2517
2640
|
let check_icon = if svc.enabled { " ◉ " } else { " ○ " };
|
|
2518
|
-
let
|
|
2519
|
-
|
|
2520
|
-
let cursor_prefix = if is_cursor { " ❯ " } else { " " };
|
|
2521
|
-
let name_style = if is_cursor {
|
|
2522
|
-
Style::default().fg(ACCENT).add_modifier(Modifier::BOLD)
|
|
2523
|
-
} else if svc.enabled {
|
|
2524
|
-
Style::default().fg(TEXT)
|
|
2525
|
-
} else {
|
|
2526
|
-
Style::default().fg(MUTED)
|
|
2527
|
-
};
|
|
2641
|
+
let cursor_prefix = if is_cursor { " › " } else { " " };
|
|
2528
2642
|
|
|
2529
2643
|
let mut lines = Vec::new();
|
|
2530
2644
|
if svc.category != cur_category {
|
|
@@ -2535,33 +2649,95 @@ impl OnboardWizard {
|
|
|
2535
2649
|
)]));
|
|
2536
2650
|
}
|
|
2537
2651
|
|
|
2538
|
-
|
|
2539
|
-
|
|
2652
|
+
if is_cursor {
|
|
2653
|
+
let check_style = Style::default()
|
|
2654
|
+
.fg(if svc.enabled {
|
|
2655
|
+
Color::Black
|
|
2656
|
+
} else {
|
|
2657
|
+
Color::DarkGray
|
|
2658
|
+
})
|
|
2659
|
+
.bg(SELECTION_BACKGROUND)
|
|
2660
|
+
.add_modifier(Modifier::BOLD);
|
|
2661
|
+
|
|
2662
|
+
let desc_part = format!(" — {}", svc.description);
|
|
2663
|
+
let full_row_text = format!("{cursor_prefix}{check_icon}{}{desc_part}", svc.name);
|
|
2664
|
+
let visual_width = UnicodeWidthStr::width(full_row_text.as_str());
|
|
2665
|
+
let pad_len = list_inner_width.saturating_sub(visual_width);
|
|
2666
|
+
|
|
2667
|
+
lines.push(Line::from(vec![
|
|
2668
|
+
Span::styled(
|
|
2669
|
+
cursor_prefix,
|
|
2670
|
+
Style::default()
|
|
2671
|
+
.fg(SELECTION_TEXT)
|
|
2672
|
+
.bg(SELECTION_BACKGROUND)
|
|
2673
|
+
.add_modifier(Modifier::BOLD),
|
|
2674
|
+
),
|
|
2675
|
+
Span::styled(check_icon, check_style),
|
|
2676
|
+
Span::styled(
|
|
2677
|
+
svc.name,
|
|
2678
|
+
Style::default()
|
|
2679
|
+
.fg(SELECTION_TEXT)
|
|
2680
|
+
.bg(SELECTION_BACKGROUND)
|
|
2681
|
+
.add_modifier(Modifier::BOLD),
|
|
2682
|
+
),
|
|
2683
|
+
Span::styled(
|
|
2684
|
+
desc_part,
|
|
2685
|
+
Style::default().fg(SELECTION_TEXT).bg(SELECTION_BACKGROUND),
|
|
2686
|
+
),
|
|
2687
|
+
Span::styled(
|
|
2688
|
+
" ".repeat(pad_len),
|
|
2689
|
+
Style::default().bg(SELECTION_BACKGROUND),
|
|
2690
|
+
),
|
|
2691
|
+
]));
|
|
2692
|
+
list_items.push(ListItem::new(lines));
|
|
2693
|
+
} else {
|
|
2694
|
+
let name_style = if svc.enabled {
|
|
2695
|
+
Style::default().fg(TEXT)
|
|
2696
|
+
} else {
|
|
2697
|
+
Style::default().fg(MUTED)
|
|
2698
|
+
};
|
|
2699
|
+
let check_color = if svc.enabled { ACCENT } else { MUTED };
|
|
2700
|
+
|
|
2701
|
+
lines.push(Line::from(vec![
|
|
2702
|
+
Span::raw(cursor_prefix),
|
|
2703
|
+
Span::styled(
|
|
2704
|
+
check_icon,
|
|
2705
|
+
Style::default()
|
|
2706
|
+
.fg(check_color)
|
|
2707
|
+
.add_modifier(Modifier::BOLD),
|
|
2708
|
+
),
|
|
2709
|
+
Span::styled(svc.name, name_style),
|
|
2710
|
+
Span::styled(
|
|
2711
|
+
format!(" — {}", svc.description),
|
|
2712
|
+
Style::default().fg(MUTED),
|
|
2713
|
+
),
|
|
2714
|
+
]));
|
|
2715
|
+
list_items.push(ListItem::new(lines));
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2719
|
+
let list_block = Block::default()
|
|
2720
|
+
.borders(Borders::ALL)
|
|
2721
|
+
.border_type(BorderType::Rounded)
|
|
2722
|
+
.border_style(Style::default().fg(TEXT))
|
|
2723
|
+
.title(Line::from(vec![
|
|
2724
|
+
Span::styled(
|
|
2725
|
+
" Available Services ",
|
|
2726
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2727
|
+
),
|
|
2540
2728
|
Span::styled(
|
|
2541
|
-
|
|
2729
|
+
" [ SELECTING ] ",
|
|
2542
2730
|
Style::default()
|
|
2543
|
-
.fg(
|
|
2731
|
+
.fg(SELECTION_TEXT)
|
|
2732
|
+
.bg(SELECTION_BACKGROUND)
|
|
2544
2733
|
.add_modifier(Modifier::BOLD),
|
|
2545
2734
|
),
|
|
2546
|
-
Span::styled(svc.name, name_style),
|
|
2547
2735
|
Span::styled(
|
|
2548
|
-
|
|
2736
|
+
" [Space: Toggle | a: All | i: Invert] ",
|
|
2549
2737
|
Style::default().fg(MUTED),
|
|
2550
2738
|
),
|
|
2551
2739
|
]));
|
|
2552
2740
|
|
|
2553
|
-
list_items.push(ListItem::new(lines));
|
|
2554
|
-
}
|
|
2555
|
-
|
|
2556
|
-
let list_block = Block::default()
|
|
2557
|
-
.borders(Borders::ALL)
|
|
2558
|
-
.border_type(BorderType::Rounded)
|
|
2559
|
-
.border_style(Style::default().fg(ACCENT))
|
|
2560
|
-
.title(Span::styled(
|
|
2561
|
-
" Available Services [Space: Toggle | a: All | i: Invert] ",
|
|
2562
|
-
Style::default().fg(ACCENT),
|
|
2563
|
-
));
|
|
2564
|
-
|
|
2565
2741
|
let mut list_state = ListState::default();
|
|
2566
2742
|
list_state.select(Some(self.service_cursor));
|
|
2567
2743
|
frame.render_stateful_widget(
|
|
@@ -2582,8 +2758,8 @@ impl OnboardWizard {
|
|
|
2582
2758
|
Span::styled(
|
|
2583
2759
|
" [ Enter: Configure Selected Services ➔ ] ",
|
|
2584
2760
|
Style::default()
|
|
2585
|
-
.fg(
|
|
2586
|
-
.bg(
|
|
2761
|
+
.fg(SELECTION_TEXT)
|
|
2762
|
+
.bg(SELECTION_BACKGROUND)
|
|
2587
2763
|
.add_modifier(Modifier::BOLD),
|
|
2588
2764
|
),
|
|
2589
2765
|
]))
|
|
@@ -2603,14 +2779,14 @@ impl OnboardWizard {
|
|
|
2603
2779
|
.border_style(Style::default().fg(SUBTLE))
|
|
2604
2780
|
.title(Span::styled(
|
|
2605
2781
|
" Step 3: Service Configurations ",
|
|
2606
|
-
Style::default().fg(
|
|
2782
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2607
2783
|
));
|
|
2608
2784
|
let inner = block.inner(area);
|
|
2609
2785
|
frame.render_widget(block, area);
|
|
2610
2786
|
let notice = Paragraph::new(
|
|
2611
2787
|
"\n ✔ Core AI (Gemini) is configured.\n\n No additional services were selected in Step 2.\n Press [Enter] to proceed to Summary and Save.",
|
|
2612
2788
|
)
|
|
2613
|
-
.style(Style::default().fg(
|
|
2789
|
+
.style(Style::default().fg(TEXT));
|
|
2614
2790
|
frame.render_widget(notice, inner);
|
|
2615
2791
|
return;
|
|
2616
2792
|
}
|
|
@@ -2630,7 +2806,7 @@ impl OnboardWizard {
|
|
|
2630
2806
|
.border_style(Style::default().fg(SUBTLE))
|
|
2631
2807
|
.title(Span::styled(
|
|
2632
2808
|
title,
|
|
2633
|
-
Style::default().fg(
|
|
2809
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2634
2810
|
));
|
|
2635
2811
|
|
|
2636
2812
|
let inner = block.inner(area);
|
|
@@ -2648,6 +2824,9 @@ impl OnboardWizard {
|
|
|
2648
2824
|
{
|
|
2649
2825
|
// Unified: Key on top, Model picker below
|
|
2650
2826
|
let is_custom = f1.is_custom;
|
|
2827
|
+
let is_f0_focused = focused_rel == 0;
|
|
2828
|
+
let is_f1_focused = focused_rel == 1;
|
|
2829
|
+
|
|
2651
2830
|
let chunks = Layout::default()
|
|
2652
2831
|
.direction(Direction::Vertical)
|
|
2653
2832
|
.margin(1)
|
|
@@ -2669,19 +2848,23 @@ impl OnboardWizard {
|
|
|
2669
2848
|
frame.render_widget(subtitle, chunks[0]);
|
|
2670
2849
|
|
|
2671
2850
|
// Field 0: Text Input
|
|
2672
|
-
let
|
|
2673
|
-
|
|
2851
|
+
let mut val_spans = Vec::new();
|
|
2852
|
+
if f0.value.is_empty() {
|
|
2853
|
+
val_spans.push(Span::styled(
|
|
2674
2854
|
format!("(Type or paste {} here)", f0.label),
|
|
2675
2855
|
Style::default().fg(MUTED),
|
|
2676
|
-
)
|
|
2856
|
+
));
|
|
2677
2857
|
} else if f0.is_secret && !f0.show_secret {
|
|
2678
|
-
Span::styled(
|
|
2858
|
+
val_spans.push(Span::styled(
|
|
2679
2859
|
"•".repeat(f0.value.chars().count().min(50)),
|
|
2680
2860
|
Style::default().fg(TEXT),
|
|
2681
|
-
)
|
|
2861
|
+
));
|
|
2682
2862
|
} else {
|
|
2683
|
-
Span::styled(&f0.value, Style::default().fg(TEXT))
|
|
2684
|
-
}
|
|
2863
|
+
val_spans.push(Span::styled(&f0.value, Style::default().fg(TEXT)));
|
|
2864
|
+
}
|
|
2865
|
+
if is_f0_focused {
|
|
2866
|
+
val_spans.push(Span::styled("█", Style::default().fg(TEXT)));
|
|
2867
|
+
}
|
|
2685
2868
|
|
|
2686
2869
|
let mask_badge = if f0.is_secret {
|
|
2687
2870
|
if f0.show_secret {
|
|
@@ -2693,29 +2876,60 @@ impl OnboardWizard {
|
|
|
2693
2876
|
""
|
|
2694
2877
|
};
|
|
2695
2878
|
|
|
2696
|
-
let f0_border = if
|
|
2697
|
-
let
|
|
2698
|
-
|
|
2699
|
-
.border_type(BorderType::Rounded)
|
|
2700
|
-
.border_style(Style::default().fg(f0_border))
|
|
2701
|
-
.title(Line::from(vec![
|
|
2879
|
+
let f0_border = if is_f0_focused { TEXT } else { SUBTLE };
|
|
2880
|
+
let f0_title = if is_f0_focused {
|
|
2881
|
+
Line::from(vec![
|
|
2702
2882
|
Span::styled(
|
|
2703
2883
|
format!(" {} ", f0.label),
|
|
2884
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2885
|
+
),
|
|
2886
|
+
Span::styled(
|
|
2887
|
+
" [ EDITING ] ",
|
|
2704
2888
|
Style::default()
|
|
2705
|
-
.fg(
|
|
2889
|
+
.fg(SELECTION_TEXT)
|
|
2890
|
+
.bg(SELECTION_BACKGROUND)
|
|
2706
2891
|
.add_modifier(Modifier::BOLD),
|
|
2707
2892
|
),
|
|
2893
|
+
Span::raw(" "),
|
|
2708
2894
|
Span::styled(mask_badge, Style::default().fg(BLUE)),
|
|
2709
|
-
])
|
|
2895
|
+
])
|
|
2896
|
+
} else if !f0.value.is_empty() {
|
|
2897
|
+
Line::from(vec![
|
|
2898
|
+
Span::styled(
|
|
2899
|
+
format!(" ✔ {} (Configured · Tab to edit) ", f0.label),
|
|
2900
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
2901
|
+
),
|
|
2902
|
+
Span::styled(mask_badge, Style::default().fg(MUTED)),
|
|
2903
|
+
])
|
|
2904
|
+
} else {
|
|
2905
|
+
Line::from(vec![
|
|
2906
|
+
Span::styled(
|
|
2907
|
+
format!(" {} (Tab to edit) ", f0.label),
|
|
2908
|
+
Style::default().fg(MUTED),
|
|
2909
|
+
),
|
|
2910
|
+
Span::styled(mask_badge, Style::default().fg(MUTED)),
|
|
2911
|
+
])
|
|
2912
|
+
};
|
|
2913
|
+
|
|
2914
|
+
let f0_block = Block::default()
|
|
2915
|
+
.borders(Borders::ALL)
|
|
2916
|
+
.border_type(BorderType::Rounded)
|
|
2917
|
+
.border_style(Style::default().fg(f0_border))
|
|
2918
|
+
.title(f0_title);
|
|
2710
2919
|
|
|
2711
|
-
frame.render_widget(
|
|
2920
|
+
frame.render_widget(
|
|
2921
|
+
Paragraph::new(Line::from(val_spans)).block(f0_block),
|
|
2922
|
+
chunks[1],
|
|
2923
|
+
);
|
|
2712
2924
|
|
|
2925
|
+
let tip_text = if is_f0_focused {
|
|
2926
|
+
"Press [Enter] or [Tab] to switch to model selection."
|
|
2927
|
+
} else {
|
|
2928
|
+
"Press [↑/↓] to change model. Press [Enter] to continue, or [Tab] to edit key."
|
|
2929
|
+
};
|
|
2713
2930
|
let tip = Line::from(vec![
|
|
2714
2931
|
Span::styled("• Tip: ", Style::default().fg(MUTED)),
|
|
2715
|
-
Span::styled(
|
|
2716
|
-
"Press [Tab] or [↓] to switch between API key and model selection.",
|
|
2717
|
-
Style::default().fg(MUTED),
|
|
2718
|
-
),
|
|
2932
|
+
Span::styled(tip_text, Style::default().fg(MUTED)),
|
|
2719
2933
|
]);
|
|
2720
2934
|
frame.render_widget(Paragraph::new(tip), chunks[2]);
|
|
2721
2935
|
|
|
@@ -2731,25 +2945,49 @@ impl OnboardWizard {
|
|
|
2731
2945
|
.map(|(i, opt)| {
|
|
2732
2946
|
let is_sel = i == selected;
|
|
2733
2947
|
let radio = if is_sel { " ◉ " } else { " ○ " };
|
|
2734
|
-
let cursor = if is_sel { "
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2948
|
+
let cursor = if is_sel { " › " } else { " " };
|
|
2949
|
+
|
|
2950
|
+
if is_f1_focused && is_sel {
|
|
2951
|
+
let line = Line::from(vec![
|
|
2952
|
+
Span::styled(
|
|
2953
|
+
cursor,
|
|
2954
|
+
Style::default()
|
|
2955
|
+
.fg(SELECTION_TEXT)
|
|
2956
|
+
.bg(SELECTION_BACKGROUND)
|
|
2957
|
+
.add_modifier(Modifier::BOLD),
|
|
2958
|
+
),
|
|
2959
|
+
Span::styled(
|
|
2960
|
+
radio,
|
|
2961
|
+
Style::default()
|
|
2962
|
+
.fg(SELECTION_TEXT)
|
|
2963
|
+
.bg(SELECTION_BACKGROUND)
|
|
2964
|
+
.add_modifier(Modifier::BOLD),
|
|
2965
|
+
),
|
|
2966
|
+
Span::styled(
|
|
2967
|
+
opt,
|
|
2968
|
+
Style::default()
|
|
2969
|
+
.fg(SELECTION_TEXT)
|
|
2970
|
+
.bg(SELECTION_BACKGROUND)
|
|
2971
|
+
.add_modifier(Modifier::BOLD),
|
|
2972
|
+
),
|
|
2973
|
+
]);
|
|
2974
|
+
ListItem::new(line).style(Style::default().bg(SELECTION_BACKGROUND))
|
|
2975
|
+
} else if is_sel {
|
|
2976
|
+
let line = Line::from(vec![
|
|
2977
|
+
Span::styled(" › ", Style::default().fg(SUBTLE)),
|
|
2978
|
+
Span::styled(radio, Style::default().fg(SUBTLE)),
|
|
2979
|
+
Span::styled(opt, Style::default().fg(TEXT)),
|
|
2980
|
+
Span::styled(" (selected)", Style::default().fg(MUTED)),
|
|
2981
|
+
]);
|
|
2982
|
+
ListItem::new(line)
|
|
2738
2983
|
} else {
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
Style::default()
|
|
2747
|
-
.fg(if is_sel { ACCENT } else { MUTED })
|
|
2748
|
-
.add_modifier(Modifier::BOLD),
|
|
2749
|
-
),
|
|
2750
|
-
Span::styled(opt, name_style),
|
|
2751
|
-
]);
|
|
2752
|
-
ListItem::new(line)
|
|
2984
|
+
let line = Line::from(vec![
|
|
2985
|
+
Span::raw(" "),
|
|
2986
|
+
Span::styled(radio, Style::default().fg(MUTED)),
|
|
2987
|
+
Span::styled(opt, Style::default().fg(TEXT)),
|
|
2988
|
+
]);
|
|
2989
|
+
ListItem::new(line)
|
|
2990
|
+
}
|
|
2753
2991
|
})
|
|
2754
2992
|
.collect();
|
|
2755
2993
|
|
|
@@ -2764,18 +3002,21 @@ impl OnboardWizard {
|
|
|
2764
3002
|
)
|
|
2765
3003
|
};
|
|
2766
3004
|
|
|
2767
|
-
let f1_border = if
|
|
2768
|
-
let
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
3005
|
+
let f1_border = if is_f1_focused { TEXT } else { SUBTLE };
|
|
3006
|
+
let f1_title = if is_f1_focused {
|
|
3007
|
+
Line::from(vec![
|
|
3008
|
+
Span::styled(
|
|
3009
|
+
format!(" Default {} ", f1.label),
|
|
3010
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
3011
|
+
),
|
|
2773
3012
|
Span::styled(
|
|
2774
|
-
|
|
3013
|
+
" [ SELECTING ] ",
|
|
2775
3014
|
Style::default()
|
|
2776
|
-
.fg(
|
|
3015
|
+
.fg(SELECTION_TEXT)
|
|
3016
|
+
.bg(SELECTION_BACKGROUND)
|
|
2777
3017
|
.add_modifier(Modifier::BOLD),
|
|
2778
3018
|
),
|
|
3019
|
+
Span::styled(" (↑/↓ to select) ", Style::default().fg(MUTED)),
|
|
2779
3020
|
Span::styled(
|
|
2780
3021
|
format!(" {status_badge} "),
|
|
2781
3022
|
Style::default().fg(if self.is_fetching_service_models {
|
|
@@ -2784,7 +3025,29 @@ impl OnboardWizard {
|
|
|
2784
3025
|
BLUE
|
|
2785
3026
|
}),
|
|
2786
3027
|
),
|
|
2787
|
-
])
|
|
3028
|
+
])
|
|
3029
|
+
} else {
|
|
3030
|
+
Line::from(vec![
|
|
3031
|
+
Span::styled(
|
|
3032
|
+
format!(" Default {} (Press Tab or ↓ to select) ", f1.label),
|
|
3033
|
+
Style::default().fg(MUTED),
|
|
3034
|
+
),
|
|
3035
|
+
Span::styled(
|
|
3036
|
+
format!(" {status_badge} "),
|
|
3037
|
+
Style::default().fg(if self.is_fetching_service_models {
|
|
3038
|
+
ACCENT
|
|
3039
|
+
} else {
|
|
3040
|
+
BLUE
|
|
3041
|
+
}),
|
|
3042
|
+
),
|
|
3043
|
+
])
|
|
3044
|
+
};
|
|
3045
|
+
|
|
3046
|
+
let list_block = Block::default()
|
|
3047
|
+
.borders(Borders::ALL)
|
|
3048
|
+
.border_type(BorderType::Rounded)
|
|
3049
|
+
.border_style(Style::default().fg(f1_border))
|
|
3050
|
+
.title(f1_title);
|
|
2788
3051
|
|
|
2789
3052
|
let mut list_state = ListState::default();
|
|
2790
3053
|
list_state.select(Some(selected));
|
|
@@ -2795,24 +3058,49 @@ impl OnboardWizard {
|
|
|
2795
3058
|
);
|
|
2796
3059
|
|
|
2797
3060
|
if is_custom {
|
|
3061
|
+
let custom_border = if is_f1_focused { TEXT } else { SUBTLE };
|
|
3062
|
+
let custom_title = if is_f1_focused {
|
|
3063
|
+
Line::from(vec![
|
|
3064
|
+
Span::styled(
|
|
3065
|
+
format!(" Custom {} Identifier ", f1.label),
|
|
3066
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
3067
|
+
),
|
|
3068
|
+
Span::styled(
|
|
3069
|
+
" [ EDITING ] ",
|
|
3070
|
+
Style::default()
|
|
3071
|
+
.fg(SELECTION_TEXT)
|
|
3072
|
+
.bg(SELECTION_BACKGROUND)
|
|
3073
|
+
.add_modifier(Modifier::BOLD),
|
|
3074
|
+
),
|
|
3075
|
+
])
|
|
3076
|
+
} else {
|
|
3077
|
+
Line::from(vec![Span::styled(
|
|
3078
|
+
format!(" Custom {} Identifier ", f1.label),
|
|
3079
|
+
Style::default().fg(MUTED),
|
|
3080
|
+
)])
|
|
3081
|
+
};
|
|
3082
|
+
|
|
2798
3083
|
let custom_block = Block::default()
|
|
2799
3084
|
.borders(Borders::ALL)
|
|
2800
3085
|
.border_type(BorderType::Rounded)
|
|
2801
|
-
.border_style(Style::default().fg(
|
|
2802
|
-
.title(
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
Span::styled(
|
|
3086
|
+
.border_style(Style::default().fg(custom_border))
|
|
3087
|
+
.title(custom_title);
|
|
3088
|
+
|
|
3089
|
+
let mut custom_spans = Vec::new();
|
|
3090
|
+
if f1.custom_value.is_empty() {
|
|
3091
|
+
custom_spans.push(Span::styled(
|
|
2808
3092
|
"(Type custom model identifier)",
|
|
2809
3093
|
Style::default().fg(MUTED),
|
|
2810
|
-
)
|
|
3094
|
+
));
|
|
2811
3095
|
} else {
|
|
2812
|
-
|
|
2813
|
-
|
|
3096
|
+
custom_spans
|
|
3097
|
+
.push(Span::styled(&f1.custom_value, Style::default().fg(TEXT)));
|
|
3098
|
+
}
|
|
3099
|
+
if is_f1_focused {
|
|
3100
|
+
custom_spans.push(Span::styled("█", Style::default().fg(TEXT)));
|
|
3101
|
+
}
|
|
2814
3102
|
frame.render_widget(
|
|
2815
|
-
Paragraph::new(
|
|
3103
|
+
Paragraph::new(Line::from(custom_spans)).block(custom_block),
|
|
2816
3104
|
chunks[4],
|
|
2817
3105
|
);
|
|
2818
3106
|
}
|
|
@@ -2824,18 +3112,30 @@ impl OnboardWizard {
|
|
|
2824
3112
|
" [ Enter: Continue to Finish ➔ ] "
|
|
2825
3113
|
};
|
|
2826
3114
|
|
|
2827
|
-
let action_hint =
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
.fg(
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
)
|
|
2837
|
-
|
|
2838
|
-
|
|
3115
|
+
let action_hint = if is_f0_focused {
|
|
3116
|
+
Paragraph::new(Line::from(vec![
|
|
3117
|
+
Span::styled(" [ Esc: Back ] ", Style::default().fg(MUTED)),
|
|
3118
|
+
Span::raw(" "),
|
|
3119
|
+
Span::styled(
|
|
3120
|
+
" [ Enter / Tab: Next Field (Select Model) ➔ ] ",
|
|
3121
|
+
Style::default().fg(TEXT),
|
|
3122
|
+
),
|
|
3123
|
+
]))
|
|
3124
|
+
.alignment(Alignment::Right)
|
|
3125
|
+
} else {
|
|
3126
|
+
Paragraph::new(Line::from(vec![
|
|
3127
|
+
Span::styled(" [ Tab: Back to Key ] ", Style::default().fg(MUTED)),
|
|
3128
|
+
Span::raw(" "),
|
|
3129
|
+
Span::styled(
|
|
3130
|
+
next_label,
|
|
3131
|
+
Style::default()
|
|
3132
|
+
.fg(SELECTION_TEXT)
|
|
3133
|
+
.bg(SELECTION_BACKGROUND)
|
|
3134
|
+
.add_modifier(Modifier::BOLD),
|
|
3135
|
+
),
|
|
3136
|
+
]))
|
|
3137
|
+
.alignment(Alignment::Right)
|
|
3138
|
+
};
|
|
2839
3139
|
frame.render_widget(action_hint, chunks[5]);
|
|
2840
3140
|
return;
|
|
2841
3141
|
} else {
|
|
@@ -2862,19 +3162,24 @@ impl OnboardWizard {
|
|
|
2862
3162
|
frame.render_widget(subtitle, chunks[0]);
|
|
2863
3163
|
|
|
2864
3164
|
for (slot, (f, idx_rel)) in [(&f0, 0), (&f1, 1)].into_iter().enumerate() {
|
|
2865
|
-
let
|
|
2866
|
-
|
|
3165
|
+
let is_active = focused_rel == idx_rel;
|
|
3166
|
+
let mut val_spans = Vec::new();
|
|
3167
|
+
if f.value.is_empty() {
|
|
3168
|
+
val_spans.push(Span::styled(
|
|
2867
3169
|
format!("(Type or paste {} here)", f.label),
|
|
2868
3170
|
Style::default().fg(MUTED),
|
|
2869
|
-
)
|
|
3171
|
+
));
|
|
2870
3172
|
} else if f.is_secret && !f.show_secret {
|
|
2871
|
-
Span::styled(
|
|
3173
|
+
val_spans.push(Span::styled(
|
|
2872
3174
|
"•".repeat(f.value.chars().count().min(50)),
|
|
2873
3175
|
Style::default().fg(TEXT),
|
|
2874
|
-
)
|
|
3176
|
+
));
|
|
2875
3177
|
} else {
|
|
2876
|
-
Span::styled(&f.value, Style::default().fg(TEXT))
|
|
2877
|
-
}
|
|
3178
|
+
val_spans.push(Span::styled(&f.value, Style::default().fg(TEXT)));
|
|
3179
|
+
}
|
|
3180
|
+
if is_active {
|
|
3181
|
+
val_spans.push(Span::styled("█", Style::default().fg(TEXT)));
|
|
3182
|
+
}
|
|
2878
3183
|
|
|
2879
3184
|
let mask_badge = if f.is_secret {
|
|
2880
3185
|
if f.show_secret {
|
|
@@ -2886,28 +3191,52 @@ impl OnboardWizard {
|
|
|
2886
3191
|
""
|
|
2887
3192
|
};
|
|
2888
3193
|
|
|
2889
|
-
let border_color = if
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
};
|
|
2894
|
-
let b = Block::default()
|
|
2895
|
-
.borders(Borders::ALL)
|
|
2896
|
-
.border_type(BorderType::Rounded)
|
|
2897
|
-
.border_style(Style::default().fg(border_color))
|
|
2898
|
-
.title(Line::from(vec![
|
|
3194
|
+
let border_color = if is_active { TEXT } else { SUBTLE };
|
|
3195
|
+
|
|
3196
|
+
let title = if is_active {
|
|
3197
|
+
Line::from(vec![
|
|
2899
3198
|
Span::styled(
|
|
2900
3199
|
format!(" {} ", f.label),
|
|
3200
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
3201
|
+
),
|
|
3202
|
+
Span::styled(
|
|
3203
|
+
" [ EDITING ] ",
|
|
2901
3204
|
Style::default()
|
|
2902
|
-
.fg(
|
|
3205
|
+
.fg(SELECTION_TEXT)
|
|
3206
|
+
.bg(SELECTION_BACKGROUND)
|
|
2903
3207
|
.add_modifier(Modifier::BOLD),
|
|
2904
3208
|
),
|
|
3209
|
+
Span::raw(" "),
|
|
2905
3210
|
Span::styled(mask_badge, Style::default().fg(BLUE)),
|
|
2906
|
-
])
|
|
3211
|
+
])
|
|
3212
|
+
} else if !f.value.is_empty() {
|
|
3213
|
+
Line::from(vec![
|
|
3214
|
+
Span::styled(
|
|
3215
|
+
format!(" ✔ {} (Configured · Tab to edit) ", f.label),
|
|
3216
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
3217
|
+
),
|
|
3218
|
+
Span::styled(mask_badge, Style::default().fg(MUTED)),
|
|
3219
|
+
])
|
|
3220
|
+
} else {
|
|
3221
|
+
Line::from(vec![
|
|
3222
|
+
Span::styled(
|
|
3223
|
+
format!(" {} (Tab to edit) ", f.label),
|
|
3224
|
+
Style::default().fg(MUTED),
|
|
3225
|
+
),
|
|
3226
|
+
Span::styled(mask_badge, Style::default().fg(MUTED)),
|
|
3227
|
+
])
|
|
3228
|
+
};
|
|
3229
|
+
|
|
3230
|
+
let b = Block::default()
|
|
3231
|
+
.borders(Borders::ALL)
|
|
3232
|
+
.border_type(BorderType::Rounded)
|
|
3233
|
+
.border_style(Style::default().fg(border_color))
|
|
3234
|
+
.title(title);
|
|
2907
3235
|
|
|
2908
3236
|
let chunk_input = if slot == 0 { chunks[1] } else { chunks[3] };
|
|
2909
3237
|
let chunk_hint = if slot == 0 { chunks[2] } else { chunks[4] };
|
|
2910
|
-
frame
|
|
3238
|
+
frame
|
|
3239
|
+
.render_widget(Paragraph::new(Line::from(val_spans)).block(b), chunk_input);
|
|
2911
3240
|
frame.render_widget(
|
|
2912
3241
|
Paragraph::new(format!(" Example / Hint: {}", f.hint))
|
|
2913
3242
|
.style(Style::default().fg(MUTED)),
|
|
@@ -2921,18 +3250,27 @@ impl OnboardWizard {
|
|
|
2921
3250
|
" [ Enter: Continue to Finish ➔ ] "
|
|
2922
3251
|
};
|
|
2923
3252
|
|
|
2924
|
-
let action_hint =
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
3253
|
+
let action_hint = if focused_rel == 0 {
|
|
3254
|
+
Paragraph::new(Line::from(vec![
|
|
3255
|
+
Span::styled(" [ Esc: Back ] ", Style::default().fg(MUTED)),
|
|
3256
|
+
Span::raw(" "),
|
|
3257
|
+
Span::styled(" [ Enter / Tab: Next Field ➔ ] ", Style::default().fg(TEXT)),
|
|
3258
|
+
]))
|
|
3259
|
+
.alignment(Alignment::Right)
|
|
3260
|
+
} else {
|
|
3261
|
+
Paragraph::new(Line::from(vec![
|
|
3262
|
+
Span::styled(" [ Tab: Back to Field 1 ] ", Style::default().fg(MUTED)),
|
|
3263
|
+
Span::raw(" "),
|
|
3264
|
+
Span::styled(
|
|
3265
|
+
next_label,
|
|
3266
|
+
Style::default()
|
|
3267
|
+
.fg(SELECTION_TEXT)
|
|
3268
|
+
.bg(SELECTION_BACKGROUND)
|
|
3269
|
+
.add_modifier(Modifier::BOLD),
|
|
3270
|
+
),
|
|
3271
|
+
]))
|
|
3272
|
+
.alignment(Alignment::Right)
|
|
3273
|
+
};
|
|
2936
3274
|
frame.render_widget(action_hint, chunks[6]);
|
|
2937
3275
|
return;
|
|
2938
3276
|
}
|
|
@@ -2966,40 +3304,68 @@ impl OnboardWizard {
|
|
|
2966
3304
|
.map(|(i, opt)| {
|
|
2967
3305
|
let is_sel = i == *selected;
|
|
2968
3306
|
let radio = if is_sel { " ◉ " } else { " ○ " };
|
|
2969
|
-
let cursor = if is_sel { "
|
|
3307
|
+
let cursor = if is_sel { " › " } else { " " };
|
|
2970
3308
|
|
|
2971
|
-
|
|
2972
|
-
|
|
3309
|
+
if is_sel {
|
|
3310
|
+
let line = Line::from(vec![
|
|
3311
|
+
Span::styled(
|
|
3312
|
+
cursor,
|
|
3313
|
+
Style::default()
|
|
3314
|
+
.fg(SELECTION_TEXT)
|
|
3315
|
+
.bg(SELECTION_BACKGROUND)
|
|
3316
|
+
.add_modifier(Modifier::BOLD),
|
|
3317
|
+
),
|
|
3318
|
+
Span::styled(
|
|
3319
|
+
radio,
|
|
3320
|
+
Style::default()
|
|
3321
|
+
.fg(SELECTION_TEXT)
|
|
3322
|
+
.bg(SELECTION_BACKGROUND)
|
|
3323
|
+
.add_modifier(Modifier::BOLD),
|
|
3324
|
+
),
|
|
3325
|
+
Span::styled(
|
|
3326
|
+
opt,
|
|
3327
|
+
Style::default()
|
|
3328
|
+
.fg(SELECTION_TEXT)
|
|
3329
|
+
.bg(SELECTION_BACKGROUND)
|
|
3330
|
+
.add_modifier(Modifier::BOLD),
|
|
3331
|
+
),
|
|
3332
|
+
]);
|
|
3333
|
+
ListItem::new(line).style(Style::default().bg(SELECTION_BACKGROUND))
|
|
2973
3334
|
} else {
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
Style::default()
|
|
2982
|
-
.fg(if is_sel { ACCENT } else { MUTED })
|
|
2983
|
-
.add_modifier(Modifier::BOLD),
|
|
2984
|
-
),
|
|
2985
|
-
Span::styled(opt, name_style),
|
|
2986
|
-
]);
|
|
2987
|
-
ListItem::new(line)
|
|
3335
|
+
let line = Line::from(vec![
|
|
3336
|
+
Span::raw(" "),
|
|
3337
|
+
Span::styled(radio, Style::default().fg(MUTED)),
|
|
3338
|
+
Span::styled(opt, Style::default().fg(TEXT)),
|
|
3339
|
+
]);
|
|
3340
|
+
ListItem::new(line)
|
|
3341
|
+
}
|
|
2988
3342
|
})
|
|
2989
3343
|
.collect();
|
|
2990
3344
|
|
|
2991
3345
|
let list_block = Block::default()
|
|
2992
3346
|
.borders(Borders::ALL)
|
|
2993
3347
|
.border_type(BorderType::Rounded)
|
|
2994
|
-
.border_style(Style::default().fg(
|
|
2995
|
-
.title(
|
|
2996
|
-
|
|
2997
|
-
" Default {}
|
|
2998
|
-
|
|
2999
|
-
options.len().saturating_sub(1).max(1)
|
|
3348
|
+
.border_style(Style::default().fg(TEXT))
|
|
3349
|
+
.title(Line::from(vec![
|
|
3350
|
+
Span::styled(
|
|
3351
|
+
format!(" Default {} ", f0.label),
|
|
3352
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
3000
3353
|
),
|
|
3001
|
-
|
|
3002
|
-
|
|
3354
|
+
Span::styled(
|
|
3355
|
+
" [ SELECTING ] ",
|
|
3356
|
+
Style::default()
|
|
3357
|
+
.fg(SELECTION_TEXT)
|
|
3358
|
+
.bg(SELECTION_BACKGROUND)
|
|
3359
|
+
.add_modifier(Modifier::BOLD),
|
|
3360
|
+
),
|
|
3361
|
+
Span::styled(
|
|
3362
|
+
format!(
|
|
3363
|
+
" (↑/↓ to select) [✓ {} models loaded] ",
|
|
3364
|
+
options.len().saturating_sub(1).max(1)
|
|
3365
|
+
),
|
|
3366
|
+
Style::default().fg(MUTED),
|
|
3367
|
+
),
|
|
3368
|
+
]));
|
|
3003
3369
|
|
|
3004
3370
|
let mut list_state = ListState::default();
|
|
3005
3371
|
list_state.select(Some(*selected));
|
|
@@ -3013,17 +3379,35 @@ impl OnboardWizard {
|
|
|
3013
3379
|
let custom_block = Block::default()
|
|
3014
3380
|
.borders(Borders::ALL)
|
|
3015
3381
|
.border_type(BorderType::Rounded)
|
|
3016
|
-
.border_style(Style::default().fg(
|
|
3017
|
-
.title(
|
|
3018
|
-
|
|
3019
|
-
|
|
3382
|
+
.border_style(Style::default().fg(TEXT))
|
|
3383
|
+
.title(Line::from(vec![
|
|
3384
|
+
Span::styled(
|
|
3385
|
+
format!(" Custom {} Identifier ", f0.label),
|
|
3386
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
3387
|
+
),
|
|
3388
|
+
Span::styled(
|
|
3389
|
+
" [ EDITING ] ",
|
|
3390
|
+
Style::default()
|
|
3391
|
+
.fg(SELECTION_TEXT)
|
|
3392
|
+
.bg(SELECTION_BACKGROUND)
|
|
3393
|
+
.add_modifier(Modifier::BOLD),
|
|
3394
|
+
),
|
|
3395
|
+
]));
|
|
3396
|
+
let mut custom_spans = Vec::new();
|
|
3397
|
+
if f0.custom_value.is_empty() {
|
|
3398
|
+
custom_spans.push(Span::styled(
|
|
3399
|
+
"(Type custom model identifier)",
|
|
3400
|
+
Style::default().fg(MUTED),
|
|
3020
3401
|
));
|
|
3021
|
-
let custom_val = if f0.custom_value.is_empty() {
|
|
3022
|
-
Span::styled("(Type custom model identifier)", Style::default().fg(MUTED))
|
|
3023
3402
|
} else {
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3403
|
+
custom_spans
|
|
3404
|
+
.push(Span::styled(&f0.custom_value, Style::default().fg(TEXT)));
|
|
3405
|
+
}
|
|
3406
|
+
custom_spans.push(Span::styled("█", Style::default().fg(TEXT)));
|
|
3407
|
+
frame.render_widget(
|
|
3408
|
+
Paragraph::new(Line::from(custom_spans)).block(custom_block),
|
|
3409
|
+
chunks[2],
|
|
3410
|
+
);
|
|
3027
3411
|
}
|
|
3028
3412
|
|
|
3029
3413
|
let next_label = if curr_idx < total_services {
|
|
@@ -3038,8 +3422,8 @@ impl OnboardWizard {
|
|
|
3038
3422
|
Span::styled(
|
|
3039
3423
|
next_label,
|
|
3040
3424
|
Style::default()
|
|
3041
|
-
.fg(
|
|
3042
|
-
.bg(
|
|
3425
|
+
.fg(SELECTION_TEXT)
|
|
3426
|
+
.bg(SELECTION_BACKGROUND)
|
|
3043
3427
|
.add_modifier(Modifier::BOLD),
|
|
3044
3428
|
),
|
|
3045
3429
|
]))
|
|
@@ -3066,19 +3450,21 @@ impl OnboardWizard {
|
|
|
3066
3450
|
.style(Style::default().fg(MUTED));
|
|
3067
3451
|
frame.render_widget(subtitle, chunks[0]);
|
|
3068
3452
|
|
|
3069
|
-
let
|
|
3070
|
-
|
|
3453
|
+
let mut val_spans = Vec::new();
|
|
3454
|
+
if f0.value.is_empty() {
|
|
3455
|
+
val_spans.push(Span::styled(
|
|
3071
3456
|
format!("(Type or paste {} here)", f0.label),
|
|
3072
3457
|
Style::default().fg(MUTED),
|
|
3073
|
-
)
|
|
3458
|
+
));
|
|
3074
3459
|
} else if f0.is_secret && !f0.show_secret {
|
|
3075
|
-
Span::styled(
|
|
3460
|
+
val_spans.push(Span::styled(
|
|
3076
3461
|
"•".repeat(f0.value.chars().count().min(50)),
|
|
3077
3462
|
Style::default().fg(TEXT),
|
|
3078
|
-
)
|
|
3463
|
+
));
|
|
3079
3464
|
} else {
|
|
3080
|
-
Span::styled(&f0.value, Style::default().fg(TEXT))
|
|
3081
|
-
}
|
|
3465
|
+
val_spans.push(Span::styled(&f0.value, Style::default().fg(TEXT)));
|
|
3466
|
+
}
|
|
3467
|
+
val_spans.push(Span::styled("█", Style::default().fg(TEXT)));
|
|
3082
3468
|
|
|
3083
3469
|
let mask_badge = if f0.is_secret {
|
|
3084
3470
|
if f0.show_secret {
|
|
@@ -3093,16 +3479,27 @@ impl OnboardWizard {
|
|
|
3093
3479
|
let f0_block = Block::default()
|
|
3094
3480
|
.borders(Borders::ALL)
|
|
3095
3481
|
.border_type(BorderType::Rounded)
|
|
3096
|
-
.border_style(Style::default().fg(
|
|
3482
|
+
.border_style(Style::default().fg(TEXT))
|
|
3097
3483
|
.title(Line::from(vec![
|
|
3098
3484
|
Span::styled(
|
|
3099
3485
|
format!(" {} ", f0.label),
|
|
3100
|
-
Style::default().fg(
|
|
3486
|
+
Style::default().fg(TEXT).add_modifier(Modifier::BOLD),
|
|
3487
|
+
),
|
|
3488
|
+
Span::styled(
|
|
3489
|
+
" [ EDITING ] ",
|
|
3490
|
+
Style::default()
|
|
3491
|
+
.fg(SELECTION_TEXT)
|
|
3492
|
+
.bg(SELECTION_BACKGROUND)
|
|
3493
|
+
.add_modifier(Modifier::BOLD),
|
|
3101
3494
|
),
|
|
3495
|
+
Span::raw(" "),
|
|
3102
3496
|
Span::styled(mask_badge, Style::default().fg(BLUE)),
|
|
3103
3497
|
]));
|
|
3104
3498
|
|
|
3105
|
-
frame.render_widget(
|
|
3499
|
+
frame.render_widget(
|
|
3500
|
+
Paragraph::new(Line::from(val_spans)).block(f0_block),
|
|
3501
|
+
chunks[1],
|
|
3502
|
+
);
|
|
3106
3503
|
frame.render_widget(
|
|
3107
3504
|
Paragraph::new(format!("Example / Hint: {}", f0.hint))
|
|
3108
3505
|
.style(Style::default().fg(MUTED)),
|
|
@@ -3121,8 +3518,8 @@ impl OnboardWizard {
|
|
|
3121
3518
|
Span::styled(
|
|
3122
3519
|
next_label,
|
|
3123
3520
|
Style::default()
|
|
3124
|
-
.fg(
|
|
3125
|
-
.bg(
|
|
3521
|
+
.fg(SELECTION_TEXT)
|
|
3522
|
+
.bg(SELECTION_BACKGROUND)
|
|
3126
3523
|
.add_modifier(Modifier::BOLD),
|
|
3127
3524
|
),
|
|
3128
3525
|
]))
|
|
@@ -3275,30 +3672,30 @@ impl OnboardWizard {
|
|
|
3275
3672
|
Span::styled(
|
|
3276
3673
|
" [ Save & Launch Mint ] ",
|
|
3277
3674
|
Style::default()
|
|
3278
|
-
.fg(
|
|
3279
|
-
.bg(
|
|
3675
|
+
.fg(SELECTION_TEXT)
|
|
3676
|
+
.bg(SELECTION_BACKGROUND)
|
|
3280
3677
|
.add_modifier(Modifier::BOLD),
|
|
3281
3678
|
)
|
|
3282
3679
|
} else {
|
|
3283
|
-
Span::styled(" [ Save & Launch Mint ] ", Style::default().fg(
|
|
3680
|
+
Span::styled(" [ Save & Launch Mint ] ", Style::default().fg(TEXT))
|
|
3284
3681
|
};
|
|
3285
3682
|
let btn_exit = if self.summary_action == 1 {
|
|
3286
3683
|
Span::styled(
|
|
3287
3684
|
" [ Save & Exit ] ",
|
|
3288
3685
|
Style::default()
|
|
3289
|
-
.fg(
|
|
3290
|
-
.bg(
|
|
3686
|
+
.fg(SELECTION_TEXT)
|
|
3687
|
+
.bg(SELECTION_BACKGROUND)
|
|
3291
3688
|
.add_modifier(Modifier::BOLD),
|
|
3292
3689
|
)
|
|
3293
3690
|
} else {
|
|
3294
|
-
Span::styled(" [ Save & Exit ] ", Style::default().fg(
|
|
3691
|
+
Span::styled(" [ Save & Exit ] ", Style::default().fg(MUTED))
|
|
3295
3692
|
};
|
|
3296
3693
|
let btn_back = if self.summary_action == 2 {
|
|
3297
3694
|
Span::styled(
|
|
3298
3695
|
" [ ⬅ Back to Edit ] ",
|
|
3299
3696
|
Style::default()
|
|
3300
|
-
.fg(
|
|
3301
|
-
.bg(
|
|
3697
|
+
.fg(SELECTION_TEXT)
|
|
3698
|
+
.bg(SELECTION_BACKGROUND)
|
|
3302
3699
|
.add_modifier(Modifier::BOLD),
|
|
3303
3700
|
)
|
|
3304
3701
|
} else {
|
|
@@ -3319,15 +3716,36 @@ impl OnboardWizard {
|
|
|
3319
3716
|
fn render_footer(&self, frame: &mut ratatui::Frame, area: Rect) {
|
|
3320
3717
|
let shortcuts = match self.step {
|
|
3321
3718
|
OnboardStep::CoreAi => {
|
|
3322
|
-
|
|
3719
|
+
if self.gemini_focus == 0 {
|
|
3720
|
+
"Focus: [API Key] · Type to edit · [Ctrl+V] Paste · [Enter/Tab] Model List · [Ctrl+H] Mask · [Esc] Cancel"
|
|
3721
|
+
} else {
|
|
3722
|
+
"Focus: [Model List] · [↑/↓] Select Model · [Enter] Continue · [Tab] API Key · [Esc] Cancel"
|
|
3723
|
+
}
|
|
3323
3724
|
}
|
|
3324
3725
|
OnboardStep::Services => {
|
|
3325
|
-
"[↑/↓] Move
|
|
3726
|
+
"Focus: [Services Checklist] · [↑/↓] Move · [Space] Toggle · [a] All · [i] Invert · [Enter] Next · [Esc] Back"
|
|
3326
3727
|
}
|
|
3327
3728
|
OnboardStep::Config => {
|
|
3328
|
-
|
|
3729
|
+
if self.service_groups.is_empty() {
|
|
3730
|
+
"[Enter] Continue to Finish · [Esc] Back"
|
|
3731
|
+
} else {
|
|
3732
|
+
let group = &self.service_groups[self.service_group_idx];
|
|
3733
|
+
let focused_rel = group.focused_field;
|
|
3734
|
+
let field_idx = group.field_indices.get(focused_rel).copied().unwrap_or(0);
|
|
3735
|
+
let is_choice = matches!(
|
|
3736
|
+
self.fields.get(field_idx).map(|f| &f.field_type),
|
|
3737
|
+
Some(FieldType::Choice { .. })
|
|
3738
|
+
);
|
|
3739
|
+
if is_choice {
|
|
3740
|
+
"Focus: [Model List] · [↑/↓] Select Model · [Enter] Next · [Tab] Key · [Esc] Back"
|
|
3741
|
+
} else {
|
|
3742
|
+
"Focus: [Input Field] · Type to edit · [Tab] Next Field · [Enter] Next · [Ctrl+H] Mask · [Esc] Back"
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
OnboardStep::Summary => {
|
|
3747
|
+
"Focus: [Action Selection] · [←/→ / Tab] Select Action · [Enter] Confirm · [Esc] Back"
|
|
3329
3748
|
}
|
|
3330
|
-
OnboardStep::Summary => "[←/→ / Tab] Select Action [Enter] Confirm [Esc] Back",
|
|
3331
3749
|
};
|
|
3332
3750
|
|
|
3333
3751
|
let chunks = Layout::default()
|
|
@@ -3340,7 +3758,7 @@ impl OnboardWizard {
|
|
|
3340
3758
|
chunks[0],
|
|
3341
3759
|
);
|
|
3342
3760
|
frame.render_widget(
|
|
3343
|
-
Paragraph::new("Mint v1.
|
|
3761
|
+
Paragraph::new("Mint v1.18.0 ")
|
|
3344
3762
|
.style(Style::default().fg(SUBTLE))
|
|
3345
3763
|
.alignment(Alignment::Right),
|
|
3346
3764
|
chunks[1],
|