@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
|
@@ -1,61 +1,66 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest'
|
|
2
2
|
import { installRendererPlatform } from '../platform'
|
|
3
3
|
import * as desktopAdapter from '../../src/tauri'
|
|
4
|
-
import {
|
|
4
|
+
import { openArtifactInBrowser } from './artifactBrowser'
|
|
5
5
|
|
|
6
6
|
const native = vi.hoisted(() => ({ invoke: vi.fn(async () => undefined) }))
|
|
7
7
|
vi.mock('@tauri-apps/api/core', () => ({ invoke: native.invoke }))
|
|
8
8
|
|
|
9
9
|
const url = 'http://127.0.0.1:12345/site/index.html'
|
|
10
|
-
describe('opening a preview in
|
|
11
|
-
it('opens an existing served URL through
|
|
10
|
+
describe('opening a preview in system browser', () => {
|
|
11
|
+
it('opens an existing served URL through browser on Desktop', async () => {
|
|
12
12
|
const opened: string[] = []
|
|
13
|
-
await
|
|
13
|
+
await openArtifactInBrowser({ path: 'site/index.html', url }, '/projects/Demo', {
|
|
14
14
|
desktop: true,
|
|
15
15
|
startPreview: async () => { throw new Error('An existing URL must be reused') },
|
|
16
|
-
|
|
16
|
+
openBrowser: async (target) => { opened.push(target) },
|
|
17
17
|
})
|
|
18
18
|
expect(opened).toEqual([url])
|
|
19
19
|
})
|
|
20
|
-
it('serves chat artifacts from their pinned project before opening
|
|
20
|
+
it('serves chat artifacts from their pinned project before opening browser', async () => {
|
|
21
21
|
const actions: unknown[] = []
|
|
22
|
-
await
|
|
22
|
+
await openArtifactInBrowser({ path: 'site/index.html', workspacePath: '/projects/Original' }, '/projects/Other', {
|
|
23
23
|
desktop: true,
|
|
24
|
-
startPreview: async (root, path
|
|
25
|
-
|
|
24
|
+
startPreview: async (root, path) => { actions.push([root, path]); return { url, jobId: 'preview-1' } },
|
|
25
|
+
openBrowser: async (target) => { actions.push(target) },
|
|
26
26
|
})
|
|
27
|
-
expect(actions).toEqual([['/projects/Original', 'site/index.html'
|
|
27
|
+
expect(actions).toEqual([['/projects/Original', 'site/index.html'], url])
|
|
28
28
|
})
|
|
29
|
-
it('opens
|
|
30
|
-
const
|
|
31
|
-
await
|
|
29
|
+
it('opens preview via system browser on Web', async () => {
|
|
30
|
+
const actions: unknown[] = []
|
|
31
|
+
await openArtifactInBrowser({ path: 'site/index.html', url, workspacePath: '/projects/Demo' }, undefined, {
|
|
32
32
|
desktop: false,
|
|
33
|
-
startPreview: async (root, path
|
|
34
|
-
|
|
33
|
+
startPreview: async (root, path) => { actions.push([root, path]); return { url, jobId: 'preview-1' } },
|
|
34
|
+
openBrowser: async (target) => { actions.push(target) },
|
|
35
35
|
})
|
|
36
|
-
expect(
|
|
36
|
+
expect(actions).toEqual([url])
|
|
37
37
|
})
|
|
38
38
|
it('reports browser launch failures so the button can show an error', async () => {
|
|
39
|
-
await expect(
|
|
39
|
+
await expect(openArtifactInBrowser({ path: 'site/index.html', url }, undefined, {
|
|
40
40
|
desktop: true,
|
|
41
41
|
startPreview: async () => { throw new Error('Unexpected server startup') },
|
|
42
|
-
|
|
43
|
-
})).rejects.toThrow('
|
|
42
|
+
openBrowser: async () => { throw new Error('Browser unavailable') },
|
|
43
|
+
})).rejects.toThrow('Browser unavailable')
|
|
44
44
|
})
|
|
45
45
|
it('does not start a server without a source project', async () => {
|
|
46
|
-
await expect(
|
|
46
|
+
await expect(openArtifactInBrowser({ path: 'site/index.html' }, undefined, {
|
|
47
47
|
desktop: true,
|
|
48
48
|
startPreview: async () => { throw new Error('Unexpected server startup') },
|
|
49
|
-
|
|
49
|
+
openBrowser: async () => { throw new Error('Unexpected browser startup') },
|
|
50
50
|
})).rejects.toThrow('Select a project')
|
|
51
51
|
})
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
it('sends the
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
it('sends the open_url desktop action for the default Desktop action', async () => {
|
|
55
|
+
vi.stubGlobal('window', { __TAURI_INTERNALS__: {} })
|
|
56
|
+
try {
|
|
57
|
+
installRendererPlatform({ ...desktopAdapter, isTauriRuntime: () => true })
|
|
58
|
+
native.invoke.mockClear()
|
|
59
|
+
await openArtifactInBrowser({ path: 'site/index.html', url }, undefined)
|
|
60
|
+
expect(native.invoke).toHaveBeenCalledWith('run_desktop_action', { action: { type: 'open_url', target: url } })
|
|
61
|
+
} finally {
|
|
62
|
+
vi.unstubAllGlobals()
|
|
63
|
+
}
|
|
59
64
|
})
|
|
60
65
|
|
|
61
66
|
it.each([
|
|
@@ -63,18 +68,18 @@ it.each([
|
|
|
63
68
|
['C:\\Projects\\Demo', 'c:\\projects\\demo\\site\\index.html', 'site/index.html'],
|
|
64
69
|
])('opens absolute artifact paths relative to their source project %s', async (root, path, relative) => {
|
|
65
70
|
const requests: unknown[] = []
|
|
66
|
-
await
|
|
71
|
+
await openArtifactInBrowser({ path, workspacePath: root }, '/projects/Other', {
|
|
67
72
|
desktop: true,
|
|
68
|
-
startPreview: async (workspace, file
|
|
69
|
-
|
|
73
|
+
startPreview: async (workspace, file) => { requests.push([workspace, file]); return { url, jobId: 'preview-1' } },
|
|
74
|
+
openBrowser: async () => {},
|
|
70
75
|
})
|
|
71
|
-
expect(requests).toEqual([[root, relative
|
|
76
|
+
expect(requests).toEqual([[root, relative]])
|
|
72
77
|
})
|
|
73
78
|
|
|
74
79
|
it('rejects an absolute artifact from a different project without starting a server', async () => {
|
|
75
|
-
await expect(
|
|
80
|
+
await expect(openArtifactInBrowser({ path: '/projects/Demo-copy/index.html', workspacePath: '/projects/Demo' }, undefined, {
|
|
76
81
|
desktop: true,
|
|
77
82
|
startPreview: async () => { throw new Error('Unexpected server startup') },
|
|
78
|
-
|
|
83
|
+
openBrowser: async () => {},
|
|
79
84
|
})).rejects.toThrow('outside its source project')
|
|
80
85
|
})
|
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
import type { ArtifactFile } from './artifacts'
|
|
2
2
|
import { runtimePlatform, workspacePlatform } from '../platform'
|
|
3
3
|
|
|
4
|
-
interface BrowserApi {
|
|
5
|
-
desktop
|
|
6
|
-
startPreview(root: string, path: string
|
|
7
|
-
|
|
4
|
+
export interface BrowserApi {
|
|
5
|
+
desktop?: boolean
|
|
6
|
+
startPreview?(root: string, path: string): Promise<{ url: string; jobId: string }>
|
|
7
|
+
openBrowser?(url: string): Promise<void>
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export async function
|
|
10
|
+
export async function openArtifactInBrowser(
|
|
11
11
|
artifact: ArtifactFile,
|
|
12
12
|
workspace: string | undefined,
|
|
13
|
-
api: BrowserApi = {
|
|
14
|
-
desktop: runtimePlatform.isTauriRuntime(),
|
|
15
|
-
startPreview: (root, path, mint) => workspacePlatform.startHtmlPreview(root, path, mint),
|
|
16
|
-
openMintBrowser: async (url) => {
|
|
17
|
-
const { invoke } = await import('@tauri-apps/api/core')
|
|
18
|
-
await invoke('open_mint_browser', { url })
|
|
19
|
-
},
|
|
20
|
-
},
|
|
13
|
+
api: BrowserApi = {},
|
|
21
14
|
): Promise<void> {
|
|
22
|
-
|
|
23
|
-
await
|
|
15
|
+
const openBrowser = api.openBrowser ?? (async (targetUrl: string) => {
|
|
16
|
+
await runtimePlatform.openExternal(targetUrl)
|
|
17
|
+
})
|
|
18
|
+
const startPreview = api.startPreview ?? ((root: string, targetPath: string) => workspacePlatform.startHtmlPreview(root, targetPath))
|
|
19
|
+
|
|
20
|
+
if (artifact.url) {
|
|
21
|
+
await openBrowser(artifact.url)
|
|
24
22
|
return
|
|
25
23
|
}
|
|
26
24
|
const root = (artifact.workspacePath ?? workspace)?.trim()
|
|
27
|
-
if (!root) throw new Error('Select a project before opening its preview in
|
|
25
|
+
if (!root) throw new Error('Select a project before opening its preview in browser')
|
|
28
26
|
let path = artifact.path.replace(/\\/g, '/')
|
|
29
27
|
if (/^(\/|[a-z]:\/)/i.test(path)) {
|
|
30
28
|
const normalizedRoot = root.replace(/\\/g, '/').replace(/\/+$/, '')
|
|
@@ -35,7 +33,7 @@ export async function openArtifactInMintBrowser(
|
|
|
35
33
|
}
|
|
36
34
|
path = path.slice(prefix.length)
|
|
37
35
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (api.desktop) await api.openMintBrowser(preview.url)
|
|
36
|
+
const preview = await startPreview(root, path)
|
|
37
|
+
await openBrowser(preview.url)
|
|
41
38
|
}
|
|
39
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/// <reference path="../../env.d.ts" />
|
|
2
|
+
import { describe, it, expect } from 'vitest'
|
|
3
|
+
import { parseAttachedDocument } from './attachedDocument'
|
|
4
|
+
|
|
5
|
+
describe('parseAttachedDocument', () => {
|
|
6
|
+
it('returns raw text unchanged when no document attachment pattern is present', () => {
|
|
7
|
+
const raw = 'สวัสดีครับ ช่วยดูโค้ดนี้หน่อย'
|
|
8
|
+
const res = parseAttachedDocument(raw)
|
|
9
|
+
expect(res.userText).toBe(raw)
|
|
10
|
+
expect(res.attachedDocument).toBeUndefined()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('handles null, undefined, and empty string', () => {
|
|
14
|
+
expect(parseAttachedDocument(null).userText).toBe('')
|
|
15
|
+
expect(parseAttachedDocument(undefined).userText).toBe('')
|
|
16
|
+
expect(parseAttachedDocument('').userText).toBe('')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('parses user text and attached document payload accurately', () => {
|
|
20
|
+
const raw = `@generate_harness_pdf.py ขอปรับหน่อยอะ ไฟล์ที่ลากมาวา
|
|
21
|
+
|
|
22
|
+
Attached document: LICENSE.electron.txt
|
|
23
|
+
Use the extracted document text below when answering. If the user asks for a summary, summarize this document.
|
|
24
|
+
|
|
25
|
+
--- Extracted document text ---
|
|
26
|
+
Copyright (c) Electron contributors
|
|
27
|
+
Copyright (c) 2013-2020 GitHub Inc.
|
|
28
|
+
|
|
29
|
+
Permission is hereby granted, free of charge.
|
|
30
|
+
--- End extracted document text ---`
|
|
31
|
+
|
|
32
|
+
const res = parseAttachedDocument(raw)
|
|
33
|
+
expect(res.userText).toBe('@generate_harness_pdf.py ขอปรับหน่อยอะ ไฟล์ที่ลากมาวา')
|
|
34
|
+
expect(res.attachedDocument).toBeDefined()
|
|
35
|
+
expect(res.attachedDocument?.filename).toBe('LICENSE.electron.txt')
|
|
36
|
+
expect(res.attachedDocument?.lineCount).toBe(4)
|
|
37
|
+
expect(res.attachedDocument?.content).toContain('Copyright (c) Electron contributors')
|
|
38
|
+
expect(res.attachedDocument?.content).toContain('Permission is hereby granted, free of charge.')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('handles when the user sent only an attachment without typing any message', () => {
|
|
42
|
+
const raw = `Attached document: notes.md
|
|
43
|
+
Use the extracted document text below when answering. If the user asks for a summary, summarize this document.
|
|
44
|
+
|
|
45
|
+
--- Extracted document text ---
|
|
46
|
+
# Notes
|
|
47
|
+
Here are the notes.
|
|
48
|
+
--- End extracted document text ---`
|
|
49
|
+
|
|
50
|
+
const res = parseAttachedDocument(raw)
|
|
51
|
+
expect(res.userText).toBe('')
|
|
52
|
+
expect(res.attachedDocument?.filename).toBe('notes.md')
|
|
53
|
+
expect(res.attachedDocument?.lineCount).toBe(2)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('handles truncated document notice properly', () => {
|
|
57
|
+
const raw = `Check this file
|
|
58
|
+
|
|
59
|
+
Attached document: large.json
|
|
60
|
+
Use the extracted document text below when answering. If the user asks for a summary, summarize this document.
|
|
61
|
+
|
|
62
|
+
--- Extracted document text ---
|
|
63
|
+
{"key": "val"}
|
|
64
|
+
|
|
65
|
+
[Document text truncated because it is long.]
|
|
66
|
+
--- End extracted document text ---`
|
|
67
|
+
|
|
68
|
+
const res = parseAttachedDocument(raw)
|
|
69
|
+
expect(res.userText).toBe('Check this file')
|
|
70
|
+
expect(res.attachedDocument?.filename).toBe('large.json')
|
|
71
|
+
expect(res.attachedDocument?.content).toContain('[Document text truncated because it is long.]')
|
|
72
|
+
})
|
|
73
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shared/utils/attachedDocument.ts
|
|
3
|
+
*
|
|
4
|
+
* Parses document attachment text and boilerplate injected into `interaction.userText`
|
|
5
|
+
* by the backend (`with_document_text`), allowing the chat interface to separate
|
|
6
|
+
* authentic user prompt text from the attached file contents.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface AttachedDocumentPayload {
|
|
10
|
+
filename: string
|
|
11
|
+
content: string
|
|
12
|
+
lineCount: number
|
|
13
|
+
charCount: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ParsedUserMessage {
|
|
17
|
+
userText: string
|
|
18
|
+
attachedDocument?: AttachedDocumentPayload
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const ATTACHED_DOC_REGEX =
|
|
22
|
+
/(?:^|\n\n)Attached document: ([^\n]+)\nUse the extracted document text below when answering[^\n]*\n\n--- Extracted document text ---\n([\s\S]*?)\n--- End extracted document text ---$/
|
|
23
|
+
|
|
24
|
+
export function parseAttachedDocument(rawText: string | null | undefined): ParsedUserMessage {
|
|
25
|
+
if (!rawText || typeof rawText !== 'string') {
|
|
26
|
+
return { userText: '' }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const match = rawText.match(ATTACHED_DOC_REGEX)
|
|
30
|
+
if (!match || match.index === undefined) {
|
|
31
|
+
return { userText: rawText }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const userText = rawText.slice(0, match.index).trim()
|
|
35
|
+
const filename = match[1].trim()
|
|
36
|
+
const content = match[2]
|
|
37
|
+
const lineCount = content ? content.split('\n').length : 0
|
|
38
|
+
const charCount = content ? content.length : 0
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
userText,
|
|
42
|
+
attachedDocument: {
|
|
43
|
+
filename,
|
|
44
|
+
content,
|
|
45
|
+
lineCount,
|
|
46
|
+
charCount,
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
getExtension,
|
|
4
|
+
materialFileIcon,
|
|
5
|
+
materialFolderIcon,
|
|
6
|
+
documentIcon,
|
|
7
|
+
folderIcon,
|
|
8
|
+
folderOpenIcon,
|
|
9
|
+
FILE_ICONS_BY_EXTENSION,
|
|
10
|
+
FILE_ICONS_BY_NAME,
|
|
11
|
+
} from './fileIcons'
|
|
12
|
+
|
|
13
|
+
describe('fileIcons utility', () => {
|
|
14
|
+
it('correctly extracts extensions case-insensitively', () => {
|
|
15
|
+
expect(getExtension('main.py')).toBe('py')
|
|
16
|
+
expect(getExtension('foo.BAR.TSX')).toBe('tsx')
|
|
17
|
+
expect(getExtension('Dockerfile')).toBe('')
|
|
18
|
+
expect(getExtension('.gitignore')).toBe('gitignore')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('maps python files (.py, .pyw, .ipynb) to Python/Jupyter icons', () => {
|
|
22
|
+
const pyIcon = materialFileIcon('script.py', 'py')
|
|
23
|
+
expect(pyIcon).toBeDefined()
|
|
24
|
+
expect(pyIcon).not.toBe(documentIcon)
|
|
25
|
+
expect(pyIcon).toBe(FILE_ICONS_BY_EXTENSION['py'])
|
|
26
|
+
|
|
27
|
+
const ipynbIcon = materialFileIcon('analysis.ipynb', 'ipynb')
|
|
28
|
+
expect(ipynbIcon).toBe(FILE_ICONS_BY_EXTENSION['ipynb'])
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('maps major programming languages to their dedicated icons', () => {
|
|
32
|
+
expect(materialFileIcon('main.rs', 'rs')).toBe(FILE_ICONS_BY_EXTENSION['rs'])
|
|
33
|
+
expect(materialFileIcon('main.go', 'go')).toBe(FILE_ICONS_BY_EXTENSION['go'])
|
|
34
|
+
expect(materialFileIcon('Main.java', 'java')).toBe(FILE_ICONS_BY_EXTENSION['java'])
|
|
35
|
+
expect(materialFileIcon('app.c', 'c')).toBe(FILE_ICONS_BY_EXTENSION['c'])
|
|
36
|
+
expect(materialFileIcon('app.cpp', 'cpp')).toBe(FILE_ICONS_BY_EXTENSION['cpp'])
|
|
37
|
+
expect(materialFileIcon('App.cs', 'cs')).toBe(FILE_ICONS_BY_EXTENSION['cs'])
|
|
38
|
+
expect(materialFileIcon('script.sh', 'sh')).toBe(FILE_ICONS_BY_EXTENSION['sh'])
|
|
39
|
+
expect(materialFileIcon('query.sql', 'sql')).toBe(FILE_ICONS_BY_EXTENSION['sql'])
|
|
40
|
+
expect(materialFileIcon('doc.pdf', 'pdf')).toBe(FILE_ICONS_BY_EXTENSION['pdf'])
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('maps special file names by exact or lowercased name', () => {
|
|
44
|
+
expect(materialFileIcon('Dockerfile', '')).toBe(FILE_ICONS_BY_NAME['dockerfile'])
|
|
45
|
+
expect(materialFileIcon('.gitignore', 'gitignore')).toBe(FILE_ICONS_BY_NAME['.gitignore'])
|
|
46
|
+
expect(materialFileIcon('package.json', 'json')).toBe(FILE_ICONS_BY_NAME['package.json'])
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('falls back to documentIcon for unrecognized extensions', () => {
|
|
50
|
+
expect(materialFileIcon('mystery.unrecognizedext123', 'unrecognizedext123')).toBe(documentIcon)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('returns appropriate folder icons', () => {
|
|
54
|
+
expect(materialFolderIcon('unknown_folder', false)).toBe(folderIcon)
|
|
55
|
+
expect(materialFolderIcon('unknown_folder', true)).toBe(folderOpenIcon)
|
|
56
|
+
expect(materialFolderIcon('src', false)).not.toBe(folderIcon)
|
|
57
|
+
expect(materialFolderIcon('src', true)).not.toBe(folderOpenIcon)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* shared/utils/fileIcons.ts
|
|
3
3
|
* Utility mapping and resolution functions for Material Icon Theme icons.
|
|
4
|
-
* Extracted from WorkspacePanel to be shared across multiple components (e.g. AgentActivityTable).
|
|
4
|
+
* Extracted from WorkspacePanel to be shared across multiple components (e.g. AgentActivityTable, TurnFileChanges).
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import folderIcon from 'material-icon-theme/icons/folder.svg?url'
|
|
@@ -40,25 +40,57 @@ import folderUiIcon from 'material-icon-theme/icons/folder-ui.svg?url'
|
|
|
40
40
|
import folderUiOpenIcon from 'material-icon-theme/icons/folder-ui-open.svg?url'
|
|
41
41
|
import folderUtilsIcon from 'material-icon-theme/icons/folder-utils.svg?url'
|
|
42
42
|
import folderUtilsOpenIcon from 'material-icon-theme/icons/folder-utils-open.svg?url'
|
|
43
|
+
|
|
44
|
+
// Language & file icons
|
|
45
|
+
import audioIcon from 'material-icon-theme/icons/audio.svg?url'
|
|
46
|
+
import cIcon from 'material-icon-theme/icons/c.svg?url'
|
|
47
|
+
import consoleIcon from 'material-icon-theme/icons/console.svg?url'
|
|
48
|
+
import cppIcon from 'material-icon-theme/icons/cpp.svg?url'
|
|
49
|
+
import csharpIcon from 'material-icon-theme/icons/csharp.svg?url'
|
|
43
50
|
import cssIcon from 'material-icon-theme/icons/css.svg?url'
|
|
51
|
+
import dartIcon from 'material-icon-theme/icons/dart.svg?url'
|
|
52
|
+
import databaseIcon from 'material-icon-theme/icons/database.svg?url'
|
|
53
|
+
import dockerIcon from 'material-icon-theme/icons/docker.svg?url'
|
|
44
54
|
import documentIcon from 'material-icon-theme/icons/document.svg?url'
|
|
55
|
+
import fontIcon from 'material-icon-theme/icons/font.svg?url'
|
|
56
|
+
import gitIcon from 'material-icon-theme/icons/git.svg?url'
|
|
57
|
+
import goIcon from 'material-icon-theme/icons/go.svg?url'
|
|
58
|
+
import graphqlIcon from 'material-icon-theme/icons/graphql.svg?url'
|
|
45
59
|
import htmlIcon from 'material-icon-theme/icons/html.svg?url'
|
|
46
60
|
import imageIcon from 'material-icon-theme/icons/image.svg?url'
|
|
61
|
+
import javaIcon from 'material-icon-theme/icons/java.svg?url'
|
|
47
62
|
import javascriptIcon from 'material-icon-theme/icons/javascript.svg?url'
|
|
48
63
|
import jsonIcon from 'material-icon-theme/icons/json.svg?url'
|
|
64
|
+
import jupyterIcon from 'material-icon-theme/icons/jupyter.svg?url'
|
|
65
|
+
import kotlinIcon from 'material-icon-theme/icons/kotlin.svg?url'
|
|
49
66
|
import lockIcon from 'material-icon-theme/icons/lock.svg?url'
|
|
50
67
|
import logIcon from 'material-icon-theme/icons/log.svg?url'
|
|
68
|
+
import luaIcon from 'material-icon-theme/icons/lua.svg?url'
|
|
51
69
|
import markdownIcon from 'material-icon-theme/icons/markdown.svg?url'
|
|
52
70
|
import npmIcon from 'material-icon-theme/icons/npm.svg?url'
|
|
71
|
+
import pdfIcon from 'material-icon-theme/icons/pdf.svg?url'
|
|
72
|
+
import phpIcon from 'material-icon-theme/icons/php.svg?url'
|
|
73
|
+
import powershellIcon from 'material-icon-theme/icons/powershell.svg?url'
|
|
74
|
+
import pythonIcon from 'material-icon-theme/icons/python.svg?url'
|
|
75
|
+
import rIcon from 'material-icon-theme/icons/r.svg?url'
|
|
53
76
|
import reactIcon from 'material-icon-theme/icons/react.svg?url'
|
|
54
77
|
import reactTsIcon from 'material-icon-theme/icons/react_ts.svg?url'
|
|
78
|
+
import rubyIcon from 'material-icon-theme/icons/ruby.svg?url'
|
|
55
79
|
import rustIcon from 'material-icon-theme/icons/rust.svg?url'
|
|
80
|
+
import sassIcon from 'material-icon-theme/icons/sass.svg?url'
|
|
81
|
+
import scalaIcon from 'material-icon-theme/icons/scala.svg?url'
|
|
56
82
|
import settingsIcon from 'material-icon-theme/icons/settings.svg?url'
|
|
83
|
+
import svelteIcon from 'material-icon-theme/icons/svelte.svg?url'
|
|
84
|
+
import swiftIcon from 'material-icon-theme/icons/swift.svg?url'
|
|
57
85
|
import tauriIcon from 'material-icon-theme/icons/tauri.svg?url'
|
|
58
86
|
import tomlIcon from 'material-icon-theme/icons/toml.svg?url'
|
|
59
87
|
import typescriptIcon from 'material-icon-theme/icons/typescript.svg?url'
|
|
88
|
+
import videoIcon from 'material-icon-theme/icons/video.svg?url'
|
|
60
89
|
import viteIcon from 'material-icon-theme/icons/vite.svg?url'
|
|
90
|
+
import vueIcon from 'material-icon-theme/icons/vue.svg?url'
|
|
91
|
+
import xmlIcon from 'material-icon-theme/icons/xml.svg?url'
|
|
61
92
|
import yamlIcon from 'material-icon-theme/icons/yaml.svg?url'
|
|
93
|
+
import zipIcon from 'material-icon-theme/icons/zip.svg?url'
|
|
62
94
|
|
|
63
95
|
export const FOLDER_ICONS: Record<string, { closed: string; open: string }> = {
|
|
64
96
|
'.cargo_home': { closed: folderRustIcon, open: folderRustOpenIcon },
|
|
@@ -86,23 +118,111 @@ export const FOLDER_ICONS: Record<string, { closed: string; open: string }> = {
|
|
|
86
118
|
}
|
|
87
119
|
|
|
88
120
|
export const FILE_ICONS_BY_EXTENSION: Record<string, string> = {
|
|
121
|
+
// Web & Styles
|
|
89
122
|
css: cssIcon,
|
|
123
|
+
scss: sassIcon,
|
|
124
|
+
sass: sassIcon,
|
|
125
|
+
less: cssIcon,
|
|
90
126
|
html: htmlIcon,
|
|
91
|
-
|
|
92
|
-
|
|
127
|
+
htm: htmlIcon,
|
|
128
|
+
graphql: graphqlIcon,
|
|
129
|
+
gql: graphqlIcon,
|
|
130
|
+
vue: vueIcon,
|
|
131
|
+
svelte: svelteIcon,
|
|
132
|
+
|
|
133
|
+
// JavaScript & TypeScript
|
|
93
134
|
js: javascriptIcon,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
md: markdownIcon,
|
|
98
|
-
png: imageIcon,
|
|
99
|
-
rs: rustIcon,
|
|
100
|
-
svg: imageIcon,
|
|
101
|
-
toml: tomlIcon,
|
|
135
|
+
mjs: javascriptIcon,
|
|
136
|
+
cjs: javascriptIcon,
|
|
137
|
+
jsx: reactIcon,
|
|
102
138
|
ts: typescriptIcon,
|
|
139
|
+
mts: typescriptIcon,
|
|
140
|
+
cts: typescriptIcon,
|
|
103
141
|
tsx: reactTsIcon,
|
|
142
|
+
|
|
143
|
+
// Python & Data Science
|
|
144
|
+
py: pythonIcon,
|
|
145
|
+
pyc: pythonIcon,
|
|
146
|
+
pyd: pythonIcon,
|
|
147
|
+
pyw: pythonIcon,
|
|
148
|
+
ipynb: jupyterIcon,
|
|
149
|
+
|
|
150
|
+
// Systems & Compiled Languages
|
|
151
|
+
rs: rustIcon,
|
|
152
|
+
c: cIcon,
|
|
153
|
+
h: cIcon,
|
|
154
|
+
cpp: cppIcon,
|
|
155
|
+
cc: cppIcon,
|
|
156
|
+
cxx: cppIcon,
|
|
157
|
+
hpp: cppIcon,
|
|
158
|
+
hh: cppIcon,
|
|
159
|
+
hxx: cppIcon,
|
|
160
|
+
cs: csharpIcon,
|
|
161
|
+
go: goIcon,
|
|
162
|
+
java: javaIcon,
|
|
163
|
+
jar: javaIcon,
|
|
164
|
+
kt: kotlinIcon,
|
|
165
|
+
kts: kotlinIcon,
|
|
166
|
+
php: phpIcon,
|
|
167
|
+
rb: rubyIcon,
|
|
168
|
+
swift: swiftIcon,
|
|
169
|
+
scala: scalaIcon,
|
|
170
|
+
dart: dartIcon,
|
|
171
|
+
lua: luaIcon,
|
|
172
|
+
r: rIcon,
|
|
173
|
+
|
|
174
|
+
// Shell & Scripts
|
|
175
|
+
sh: consoleIcon,
|
|
176
|
+
bash: consoleIcon,
|
|
177
|
+
zsh: consoleIcon,
|
|
178
|
+
fish: consoleIcon,
|
|
179
|
+
ps1: powershellIcon,
|
|
180
|
+
psm1: powershellIcon,
|
|
181
|
+
bat: consoleIcon,
|
|
182
|
+
cmd: consoleIcon,
|
|
183
|
+
|
|
184
|
+
// Data, Config & Docs
|
|
185
|
+
json: jsonIcon,
|
|
186
|
+
json5: jsonIcon,
|
|
187
|
+
jsonc: jsonIcon,
|
|
104
188
|
yaml: yamlIcon,
|
|
105
189
|
yml: yamlIcon,
|
|
190
|
+
toml: tomlIcon,
|
|
191
|
+
xml: xmlIcon,
|
|
192
|
+
sql: databaseIcon,
|
|
193
|
+
db: databaseIcon,
|
|
194
|
+
sqlite: databaseIcon,
|
|
195
|
+
sqlite3: databaseIcon,
|
|
196
|
+
md: markdownIcon,
|
|
197
|
+
mdx: markdownIcon,
|
|
198
|
+
pdf: pdfIcon,
|
|
199
|
+
log: logIcon,
|
|
200
|
+
lock: lockIcon,
|
|
201
|
+
|
|
202
|
+
// Media, Fonts & Archives
|
|
203
|
+
png: imageIcon,
|
|
204
|
+
jpg: imageIcon,
|
|
205
|
+
jpeg: imageIcon,
|
|
206
|
+
gif: imageIcon,
|
|
207
|
+
webp: imageIcon,
|
|
208
|
+
svg: imageIcon,
|
|
209
|
+
ico: imageIcon,
|
|
210
|
+
mp3: audioIcon,
|
|
211
|
+
wav: audioIcon,
|
|
212
|
+
ogg: audioIcon,
|
|
213
|
+
mp4: videoIcon,
|
|
214
|
+
webm: videoIcon,
|
|
215
|
+
mov: videoIcon,
|
|
216
|
+
zip: zipIcon,
|
|
217
|
+
tar: zipIcon,
|
|
218
|
+
gz: zipIcon,
|
|
219
|
+
tgz: zipIcon,
|
|
220
|
+
'7z': zipIcon,
|
|
221
|
+
rar: zipIcon,
|
|
222
|
+
woff: fontIcon,
|
|
223
|
+
woff2: fontIcon,
|
|
224
|
+
ttf: fontIcon,
|
|
225
|
+
otf: fontIcon,
|
|
106
226
|
}
|
|
107
227
|
|
|
108
228
|
export const FILE_ICONS_BY_NAME: Record<string, string> = {
|
|
@@ -111,6 +231,18 @@ export const FILE_ICONS_BY_NAME: Record<string, string> = {
|
|
|
111
231
|
'tauri.conf.json': tauriIcon,
|
|
112
232
|
'vite.config.ts': viteIcon,
|
|
113
233
|
'vite.config.web.ts': viteIcon,
|
|
234
|
+
'vite.config.js': viteIcon,
|
|
235
|
+
'dockerfile': dockerIcon,
|
|
236
|
+
'containerfile': dockerIcon,
|
|
237
|
+
'docker-compose.yml': dockerIcon,
|
|
238
|
+
'docker-compose.yaml': dockerIcon,
|
|
239
|
+
'.gitignore': gitIcon,
|
|
240
|
+
'.gitattributes': gitIcon,
|
|
241
|
+
'.gitmodules': gitIcon,
|
|
242
|
+
'.env': settingsIcon,
|
|
243
|
+
'.env.local': settingsIcon,
|
|
244
|
+
'.env.development': settingsIcon,
|
|
245
|
+
'.env.production': settingsIcon,
|
|
114
246
|
}
|
|
115
247
|
|
|
116
248
|
export function getExtension(name: string): string {
|
|
@@ -125,11 +257,12 @@ export function materialFolderIcon(name: string, open: boolean): string {
|
|
|
125
257
|
}
|
|
126
258
|
|
|
127
259
|
export function materialFileIcon(name: string, fileExtension: string): string {
|
|
128
|
-
|
|
129
|
-
if (
|
|
130
|
-
if (
|
|
131
|
-
|
|
260
|
+
const lowerName = name.toLowerCase()
|
|
261
|
+
if (FILE_ICONS_BY_NAME[lowerName]) return FILE_ICONS_BY_NAME[lowerName]
|
|
262
|
+
if (lowerName.endsWith('.config.ts') || lowerName.endsWith('.config.js') || lowerName.endsWith('.config.mjs')) return settingsIcon
|
|
263
|
+
if (lowerName.endsWith('.tsx')) return reactTsIcon
|
|
264
|
+
if (lowerName.endsWith('.jsx')) return reactIcon
|
|
265
|
+
return FILE_ICONS_BY_EXTENSION[fileExtension.toLowerCase()] || documentIcon
|
|
132
266
|
}
|
|
133
267
|
|
|
134
268
|
export { folderIcon, folderOpenIcon, documentIcon }
|
|
135
|
-
|