@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
|
@@ -30,7 +30,7 @@ function ImageTile({ image }: { image: ImageSearchHit }) {
|
|
|
30
30
|
display: 'flex',
|
|
31
31
|
flex: '0 0 116px',
|
|
32
32
|
flexDirection: 'column',
|
|
33
|
-
borderRadius: '10px',
|
|
33
|
+
borderRadius: 'var(--radius-md, 10px)',
|
|
34
34
|
overflow: 'hidden',
|
|
35
35
|
background: 'var(--surface-strong)',
|
|
36
36
|
border: '1px solid var(--border)',
|
|
@@ -93,7 +93,7 @@ export default function ImageSearchCard({ data }: { data: ImageSearchData }) {
|
|
|
93
93
|
style={{
|
|
94
94
|
background: cardBg,
|
|
95
95
|
color: cardText,
|
|
96
|
-
borderRadius: '
|
|
96
|
+
borderRadius: 'var(--radius-xl, 18px)',
|
|
97
97
|
padding: '16px 20px',
|
|
98
98
|
margin: '12px 0',
|
|
99
99
|
boxShadow: 'var(--shadow-md)',
|
|
@@ -210,7 +210,7 @@ export default function MermaidCard({ code }: { code: string }) {
|
|
|
210
210
|
style={{
|
|
211
211
|
background: 'var(--bg-surface-soft)',
|
|
212
212
|
color: 'var(--text-primary)',
|
|
213
|
-
borderRadius: '
|
|
213
|
+
borderRadius: 'var(--radius-xl, 18px)',
|
|
214
214
|
padding: '16px 20px',
|
|
215
215
|
margin: '12px 0',
|
|
216
216
|
boxShadow: 'var(--shadow-md)',
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { renderToStaticMarkup } from 'react-dom/server'
|
|
4
|
+
import { PlanCard } from './PlanCard'
|
|
5
|
+
import { extractToolCardPayloads } from './ToolResultCards'
|
|
6
|
+
import type { AgentProgress } from '../../types'
|
|
7
|
+
|
|
8
|
+
describe('PlanCard and ToolResultCards plan extraction', () => {
|
|
9
|
+
it('extracts planData from exit_plan_mode ToolEnd event', () => {
|
|
10
|
+
const progress: AgentProgress[] = [
|
|
11
|
+
{
|
|
12
|
+
type: 'ToolEnd',
|
|
13
|
+
data: {
|
|
14
|
+
action: 'exit_plan_mode',
|
|
15
|
+
input: { plan: '## Implementation Plan\n1. Step one\n2. Step two' },
|
|
16
|
+
result: 'Plan approved by user',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
const payloads = extractToolCardPayloads(progress, 'Proceeding with the implementation.')
|
|
22
|
+
expect(payloads.planData).toBe('## Implementation Plan\n1. Step one\n2. Step two')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('renders PlanCard with Proposed Plan title, Plan badge, and markdown content', () => {
|
|
26
|
+
const sample = '## Objectives\n- [ ] Task 1: Initialize\n- [x] Task 2: Complete'
|
|
27
|
+
const html = renderToStaticMarkup(<PlanCard plan={sample} />)
|
|
28
|
+
|
|
29
|
+
expect(html).toContain('Proposed Plan')
|
|
30
|
+
expect(html).toContain('approval-badge-chip plan')
|
|
31
|
+
expect(html).toContain('Plan')
|
|
32
|
+
expect(html).toContain('Objectives')
|
|
33
|
+
expect(html).toContain('Task 1: Initialize')
|
|
34
|
+
expect(html).toContain('Task 2: Complete')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('returns null if plan is empty', () => {
|
|
38
|
+
const html = renderToStaticMarkup(<PlanCard plan=" " />)
|
|
39
|
+
expect(html).toBe('')
|
|
40
|
+
})
|
|
41
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { memo } from 'react'
|
|
2
|
+
import { FormattedMessage } from '../../utils/markdown'
|
|
3
|
+
|
|
4
|
+
export interface PlanCardProps {
|
|
5
|
+
plan: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const PlanCard = memo(function PlanCard({ plan }: PlanCardProps) {
|
|
9
|
+
if (!plan || !plan.trim()) return null
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
className="action-card approval-card plan-inline-card"
|
|
14
|
+
style={{ width: '100%', alignItems: 'stretch', textAlign: 'left', marginBottom: '12px' }}
|
|
15
|
+
>
|
|
16
|
+
<div className="approval-card-header" style={{ width: '100%', textAlign: 'left' }}>
|
|
17
|
+
<div className="approval-title-group" style={{ textAlign: 'left' }}>
|
|
18
|
+
<div className="approval-title-text" style={{ textAlign: 'left' }}>Proposed Plan</div>
|
|
19
|
+
</div>
|
|
20
|
+
<span className="approval-badge-chip plan">
|
|
21
|
+
Plan
|
|
22
|
+
</span>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div className="approval-content-box plan-review-content" style={{ maxHeight: '420px', overflowY: 'auto' }}>
|
|
26
|
+
<FormattedMessage text={plan.trim()} />
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export default PlanCard
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { renderToStaticMarkup } from 'react-dom/server'
|
|
4
|
+
import { ReleaseNotesCard } from './ReleaseNotesCard'
|
|
5
|
+
import { renderFormattedMessage } from '../../utils/markdown'
|
|
6
|
+
|
|
7
|
+
describe('ReleaseNotesCard', () => {
|
|
8
|
+
it('renders release notes with framed card, version badge, and sections', () => {
|
|
9
|
+
const sample = `# Release Notes - Mint Agent v1.18.0\n\n## Smart Thinking\n- **Safe Non-Text Filter**: Excludes media\n- **Unrestricted**: All models`
|
|
10
|
+
const html = renderToStaticMarkup(<ReleaseNotesCard markdown={sample} />)
|
|
11
|
+
|
|
12
|
+
expect(html).toContain('release-notes-card')
|
|
13
|
+
expect(html).toContain('v1.18.0')
|
|
14
|
+
expect(html).toContain('Release Notes')
|
|
15
|
+
expect(html).toContain('Smart Thinking')
|
|
16
|
+
expect(html).toContain('Safe Non-Text Filter')
|
|
17
|
+
expect(html).toContain('Excludes media')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('renders through renderFormattedMessage seamlessly', () => {
|
|
21
|
+
const sample = `# Release Notes - Mint Agent v1.18.0\n\n## UI Ergonomics\n- **Code Blocks**: Clean copying`
|
|
22
|
+
const node = renderFormattedMessage(sample)
|
|
23
|
+
const html = renderToStaticMarkup(<>{node}</>)
|
|
24
|
+
|
|
25
|
+
expect(html).toContain('release-notes-card')
|
|
26
|
+
expect(html).toContain('UI Ergonomics')
|
|
27
|
+
expect(html).toContain('Clean copying')
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
|
+
import { Rocket } from 'lucide-react'
|
|
3
|
+
|
|
4
|
+
export interface ReleaseNotesCardProps {
|
|
5
|
+
markdown: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface ReleaseSection {
|
|
9
|
+
title: string
|
|
10
|
+
items: { title: string; desc: string; subItems?: string[] }[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ReleaseNotesCard({ markdown }: ReleaseNotesCardProps) {
|
|
14
|
+
const { version, sections } = useMemo(() => {
|
|
15
|
+
let version = 'Latest'
|
|
16
|
+
const sections: ReleaseSection[] = []
|
|
17
|
+
let currentSection: ReleaseSection | null = null
|
|
18
|
+
let currentItem: { title: string; desc: string; subItems?: string[] } | null = null
|
|
19
|
+
|
|
20
|
+
for (const rawLine of markdown.split('\n')) {
|
|
21
|
+
const line = rawLine.trim()
|
|
22
|
+
if (!line) continue
|
|
23
|
+
|
|
24
|
+
if (line.startsWith('# ')) {
|
|
25
|
+
const vMatch = line.match(/v\d+\.\d+(?:\.\d+)?/i)
|
|
26
|
+
if (vMatch) version = vMatch[0]
|
|
27
|
+
continue
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (line.startsWith('## ')) {
|
|
31
|
+
if (currentItem && currentSection) {
|
|
32
|
+
currentSection.items.push(currentItem)
|
|
33
|
+
currentItem = null
|
|
34
|
+
}
|
|
35
|
+
if (currentSection) {
|
|
36
|
+
sections.push(currentSection)
|
|
37
|
+
}
|
|
38
|
+
currentSection = {
|
|
39
|
+
title: line.replace(/^##\s+/, '').trim(),
|
|
40
|
+
items: [],
|
|
41
|
+
}
|
|
42
|
+
continue
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const indent = rawLine.length - rawLine.trimStart().length
|
|
46
|
+
if (line.startsWith('- ') || line.startsWith('* ')) {
|
|
47
|
+
const content = line.slice(2).trim()
|
|
48
|
+
if (indent >= 2 && currentItem) {
|
|
49
|
+
if (!currentItem.subItems) currentItem.subItems = []
|
|
50
|
+
currentItem.subItems.push(content)
|
|
51
|
+
continue
|
|
52
|
+
}
|
|
53
|
+
if (currentItem && currentSection) {
|
|
54
|
+
currentSection.items.push(currentItem)
|
|
55
|
+
}
|
|
56
|
+
const boldMatch = content.match(/^\*\*([^*]+)\*\*:\s*(.*)$/)
|
|
57
|
+
if (boldMatch) {
|
|
58
|
+
currentItem = {
|
|
59
|
+
title: boldMatch[1],
|
|
60
|
+
desc: boldMatch[2],
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
currentItem = {
|
|
64
|
+
title: '',
|
|
65
|
+
desc: content,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (currentItem) {
|
|
72
|
+
currentItem.desc += ' ' + line
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (currentItem && currentSection) {
|
|
77
|
+
currentSection.items.push(currentItem)
|
|
78
|
+
}
|
|
79
|
+
if (currentSection) {
|
|
80
|
+
sections.push(currentSection)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { version, sections }
|
|
84
|
+
}, [markdown])
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<div className="release-notes-card">
|
|
88
|
+
<div className="release-notes-header">
|
|
89
|
+
<div className="release-notes-title">
|
|
90
|
+
<Rocket size={18} className="release-notes-icon" />
|
|
91
|
+
<span>Release Notes</span>
|
|
92
|
+
<span className="release-notes-version-badge">{version}</span>
|
|
93
|
+
</div>
|
|
94
|
+
<span className="release-notes-count-badge">
|
|
95
|
+
{sections.length} Highlights
|
|
96
|
+
</span>
|
|
97
|
+
</div>
|
|
98
|
+
<div className="release-notes-track">
|
|
99
|
+
<div className="release-notes-bar" />
|
|
100
|
+
</div>
|
|
101
|
+
<div className="release-notes-body">
|
|
102
|
+
{sections.map((section, sIdx) => (
|
|
103
|
+
<div key={sIdx} className="release-notes-section">
|
|
104
|
+
<div className="release-notes-section-title">
|
|
105
|
+
<span className="release-notes-bullet">●</span>
|
|
106
|
+
<span>{section.title}</span>
|
|
107
|
+
</div>
|
|
108
|
+
<div className="release-notes-items">
|
|
109
|
+
{section.items.map((item, iIdx) => (
|
|
110
|
+
<div key={iIdx} className="release-notes-item">
|
|
111
|
+
<div className="release-notes-item-header">
|
|
112
|
+
<span className="release-notes-item-bullet">•</span>
|
|
113
|
+
{item.title ? (
|
|
114
|
+
<span className="release-notes-item-title">{item.title}:</span>
|
|
115
|
+
) : null}
|
|
116
|
+
<span className="release-notes-item-desc">{item.desc}</span>
|
|
117
|
+
</div>
|
|
118
|
+
{item.subItems && item.subItems.length > 0 && (
|
|
119
|
+
<div className="release-notes-subitems">
|
|
120
|
+
{item.subItems.map((sub, subIdx) => (
|
|
121
|
+
<div key={subIdx} className="release-notes-subitem">
|
|
122
|
+
<span className="release-notes-subitem-bullet">›</span>
|
|
123
|
+
<span>{sub.replace(/\*\*/g, '')}</span>
|
|
124
|
+
</div>
|
|
125
|
+
))}
|
|
126
|
+
</div>
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
129
|
+
))}
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
))}
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
export default ReleaseNotesCard
|
|
@@ -60,7 +60,7 @@ export default function StockCard({ data }: { data: StockData }) {
|
|
|
60
60
|
style={{
|
|
61
61
|
background: t.cardBg,
|
|
62
62
|
color: t.cardText,
|
|
63
|
-
borderRadius: '
|
|
63
|
+
borderRadius: 'var(--radius-xl, 18px)',
|
|
64
64
|
padding: '16px 20px',
|
|
65
65
|
margin: '12px 0',
|
|
66
66
|
boxShadow: t.cardShadow,
|
|
@@ -80,7 +80,7 @@ export default function StockCard({ data }: { data: StockData }) {
|
|
|
80
80
|
fontSize: '11px',
|
|
81
81
|
fontWeight: 700,
|
|
82
82
|
padding: '2px 6px',
|
|
83
|
-
borderRadius: '4px',
|
|
83
|
+
borderRadius: 'var(--radius-2xs, 4px)',
|
|
84
84
|
background: t.tagBg,
|
|
85
85
|
color: t.tagColor,
|
|
86
86
|
textTransform: 'none',
|
|
@@ -98,7 +98,7 @@ export default function StockCard({ data }: { data: StockData }) {
|
|
|
98
98
|
background: isPositive ? 'rgba(16, 185, 129, 0.12)' : 'rgba(239, 68, 68, 0.12)',
|
|
99
99
|
border: `1px solid ${isPositive ? 'rgba(16, 185, 129, 0.3)' : 'rgba(239, 68, 68, 0.3)'}`,
|
|
100
100
|
padding: '4px 10px',
|
|
101
|
-
borderRadius: '
|
|
101
|
+
borderRadius: 'var(--radius-full, 9999px)',
|
|
102
102
|
display: 'flex',
|
|
103
103
|
alignItems: 'center',
|
|
104
104
|
gap: '4px',
|
|
@@ -123,26 +123,26 @@ export default function StockCard({ data }: { data: StockData }) {
|
|
|
123
123
|
|
|
124
124
|
{/* Stats Grid */}
|
|
125
125
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '8px' }}>
|
|
126
|
-
<div style={{ background: t.statBg, borderRadius: '8px', padding: '8px 10px', border: `1px solid ${t.statBorder}` }}>
|
|
126
|
+
<div style={{ background: t.statBg, borderRadius: 'var(--radius-sm, 8px)', padding: '8px 10px', border: `1px solid ${t.statBorder}` }}>
|
|
127
127
|
<p style={{ margin: 0, fontSize: '10px', color: t.statLabel, textTransform: 'none' }}>Day high</p>
|
|
128
128
|
<p style={{ margin: '2px 0 0', fontSize: '12px', fontWeight: 700, color: t.statValue }}>
|
|
129
129
|
{data.dayHigh ? `${currencySymbol}${data.dayHigh.toFixed(2)}` : 'N/A'}
|
|
130
130
|
</p>
|
|
131
131
|
</div>
|
|
132
132
|
|
|
133
|
-
<div style={{ background: t.statBg, borderRadius: '8px', padding: '8px 10px', border: `1px solid ${t.statBorder}` }}>
|
|
133
|
+
<div style={{ background: t.statBg, borderRadius: 'var(--radius-sm, 8px)', padding: '8px 10px', border: `1px solid ${t.statBorder}` }}>
|
|
134
134
|
<p style={{ margin: 0, fontSize: '10px', color: t.statLabel, textTransform: 'none' }}>Day low</p>
|
|
135
135
|
<p style={{ margin: '2px 0 0', fontSize: '12px', fontWeight: 700, color: t.statValue }}>
|
|
136
136
|
{data.dayLow ? `${currencySymbol}${data.dayLow.toFixed(2)}` : 'N/A'}
|
|
137
137
|
</p>
|
|
138
138
|
</div>
|
|
139
139
|
|
|
140
|
-
<div style={{ background: t.statBg, borderRadius: '8px', padding: '8px 10px', border: `1px solid ${t.statBorder}` }}>
|
|
140
|
+
<div style={{ background: t.statBg, borderRadius: 'var(--radius-sm, 8px)', padding: '8px 10px', border: `1px solid ${t.statBorder}` }}>
|
|
141
141
|
<p style={{ margin: 0, fontSize: '10px', color: t.statLabel, textTransform: 'none' }}>Market cap</p>
|
|
142
142
|
<p style={{ margin: '2px 0 0', fontSize: '12px', fontWeight: 700, color: t.statValue }}>{formatLargeNum(data.marketCap)}</p>
|
|
143
143
|
</div>
|
|
144
144
|
|
|
145
|
-
<div style={{ background: t.statBg, borderRadius: '8px', padding: '8px 10px', border: `1px solid ${t.statBorder}` }}>
|
|
145
|
+
<div style={{ background: t.statBg, borderRadius: 'var(--radius-sm, 8px)', padding: '8px 10px', border: `1px solid ${t.statBorder}` }}>
|
|
146
146
|
<p style={{ margin: 0, fontSize: '10px', color: t.statLabel, textTransform: 'none' }}>Volume</p>
|
|
147
147
|
<p style={{ margin: '2px 0 0', fontSize: '12px', fontWeight: 700, color: t.statValue }}>{formatLargeNum(data.volume)}</p>
|
|
148
148
|
</div>
|
|
@@ -6,6 +6,7 @@ const StockCard = lazy(() => import('./StockCard'))
|
|
|
6
6
|
const CalculationCard = lazy(() => import('./CalculationCard'))
|
|
7
7
|
const ImageSearchCard = lazy(() => import('./ImageSearchCard'))
|
|
8
8
|
const ImageGenCard = lazy(() => import('./ImageGenCard'))
|
|
9
|
+
const PlanCard = lazy(() => import('./PlanCard'))
|
|
9
10
|
|
|
10
11
|
export interface ToolResultCardsProps {
|
|
11
12
|
progress?: AgentProgress[]
|
|
@@ -41,6 +42,7 @@ export function extractToolCardPayloads(progress?: AgentProgress[], aiText?: str
|
|
|
41
42
|
let calcData: any = null
|
|
42
43
|
let imageSearchData: any = null
|
|
43
44
|
let imageGenData: any = null
|
|
45
|
+
let planData: string | null = null
|
|
44
46
|
|
|
45
47
|
for (const event of progress || []) {
|
|
46
48
|
if (event.type !== 'ToolEnd') continue
|
|
@@ -56,24 +58,30 @@ export function extractToolCardPayloads(progress?: AgentProgress[], aiText?: str
|
|
|
56
58
|
imageSearchData = parseMatchedJson(res, IMAGE_SEARCH_RE)
|
|
57
59
|
} else if (!skipImageGen && !imageGenData && IMAGE_GEN_ACTIONS.has(actionName)) {
|
|
58
60
|
imageGenData = parseMatchedJson(res, IMAGE_GEN_RE)
|
|
61
|
+
} else if (!planData && actionName === 'exit_plan_mode') {
|
|
62
|
+
const raw = (event.data?.input as any)?.plan || (event.data as any)?.plan
|
|
63
|
+
if (typeof raw === 'string' && raw.trim()) {
|
|
64
|
+
planData = raw.trim()
|
|
65
|
+
}
|
|
59
66
|
}
|
|
60
67
|
}
|
|
61
68
|
|
|
62
|
-
return { weatherData, stockData, calcData, imageSearchData, imageGenData }
|
|
69
|
+
return { weatherData, stockData, calcData, imageSearchData, imageGenData, planData }
|
|
63
70
|
}
|
|
64
71
|
|
|
65
72
|
export const ToolResultCards = memo(function ToolResultCards({ progress, aiText }: ToolResultCardsProps) {
|
|
66
|
-
const { weatherData, stockData, calcData, imageSearchData, imageGenData } = useMemo(
|
|
73
|
+
const { weatherData, stockData, calcData, imageSearchData, imageGenData, planData } = useMemo(
|
|
67
74
|
() => extractToolCardPayloads(progress, aiText),
|
|
68
75
|
[progress, aiText],
|
|
69
76
|
)
|
|
70
77
|
|
|
71
|
-
if (!weatherData && !stockData && !calcData && !imageSearchData && !imageGenData) {
|
|
78
|
+
if (!weatherData && !stockData && !calcData && !imageSearchData && !imageGenData && !planData) {
|
|
72
79
|
return null
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
return (
|
|
76
83
|
<Suspense fallback={null}>
|
|
84
|
+
{planData && <PlanCard plan={planData} />}
|
|
77
85
|
{weatherData && <WeatherCard data={weatherData} />}
|
|
78
86
|
{stockData && <StockCard data={stockData} />}
|
|
79
87
|
{calcData && <CalculationCard data={calcData} />}
|
|
@@ -30,11 +30,11 @@ export default function UiMockupWidget({ data }: { data: UiMockupData }) {
|
|
|
30
30
|
|
|
31
31
|
const title = data.title || 'App Preview'
|
|
32
32
|
const subtitle = data.subtitle
|
|
33
|
-
const dropzoneText = data.dropzoneText || '
|
|
34
|
-
const dropzoneHint = data.dropzoneHint || '
|
|
35
|
-
const buttonText = data.buttonText || '
|
|
33
|
+
const dropzoneText = data.dropzoneText || 'Drag files here'
|
|
34
|
+
const dropzoneHint = data.dropzoneHint || 'or choose files from your device'
|
|
35
|
+
const buttonText = data.buttonText || 'Choose file'
|
|
36
36
|
const disclaimer =
|
|
37
|
-
data.disclaimer || '
|
|
37
|
+
data.disclaimer || 'UI mockup preview only, not a live file processor'
|
|
38
38
|
|
|
39
39
|
// Options state
|
|
40
40
|
let initialOptions: Array<{ label: string; current: string; choices: string[] }> = []
|
|
@@ -94,7 +94,7 @@ export default function WeatherCard({ data }: { data: WeatherData }) {
|
|
|
94
94
|
style={{
|
|
95
95
|
background: weatherInfo.gradient,
|
|
96
96
|
color: '#ffffff',
|
|
97
|
-
borderRadius: '
|
|
97
|
+
borderRadius: 'var(--radius-xl, 18px)',
|
|
98
98
|
padding: '16px 20px',
|
|
99
99
|
margin: '12px 0',
|
|
100
100
|
boxShadow: '0 10px 25px -5px rgba(0, 0, 0, 0.4)',
|
|
@@ -161,7 +161,7 @@ export default function WeatherCard({ data }: { data: WeatherData }) {
|
|
|
161
161
|
alignItems: 'center',
|
|
162
162
|
background: 'rgba(255, 255, 255, 0.12)',
|
|
163
163
|
backdropFilter: 'blur(4px)',
|
|
164
|
-
borderRadius: '8px',
|
|
164
|
+
borderRadius: 'var(--radius-sm, 8px)',
|
|
165
165
|
padding: '8px 4px',
|
|
166
166
|
}}
|
|
167
167
|
>
|
|
@@ -187,7 +187,7 @@ export default function WeatherCard({ data }: { data: WeatherData }) {
|
|
|
187
187
|
style={{
|
|
188
188
|
background: 'rgba(255, 255, 255, 0.12)',
|
|
189
189
|
backdropFilter: 'blur(4px)',
|
|
190
|
-
borderRadius: '8px',
|
|
190
|
+
borderRadius: 'var(--radius-sm, 8px)',
|
|
191
191
|
padding: '8px 10px',
|
|
192
192
|
}}
|
|
193
193
|
>
|
|
@@ -199,7 +199,7 @@ export default function WeatherCard({ data }: { data: WeatherData }) {
|
|
|
199
199
|
style={{
|
|
200
200
|
background: 'rgba(255, 255, 255, 0.12)',
|
|
201
201
|
backdropFilter: 'blur(4px)',
|
|
202
|
-
borderRadius: '8px',
|
|
202
|
+
borderRadius: 'var(--radius-sm, 8px)',
|
|
203
203
|
padding: '8px 10px',
|
|
204
204
|
}}
|
|
205
205
|
>
|
|
@@ -211,7 +211,7 @@ export default function WeatherCard({ data }: { data: WeatherData }) {
|
|
|
211
211
|
style={{
|
|
212
212
|
background: 'rgba(255, 255, 255, 0.12)',
|
|
213
213
|
backdropFilter: 'blur(4px)',
|
|
214
|
-
borderRadius: '8px',
|
|
214
|
+
borderRadius: 'var(--radius-sm, 8px)',
|
|
215
215
|
padding: '8px 10px',
|
|
216
216
|
}}
|
|
217
217
|
>
|
|
@@ -21,4 +21,15 @@ describe('skill approval', () => {
|
|
|
21
21
|
expect(html).toContain('Reject')
|
|
22
22
|
expect(html).not.toContain('Always allow for this session')
|
|
23
23
|
})
|
|
24
|
+
|
|
25
|
+
it('renders plan review card with markdown body and approve/deny actions', () => {
|
|
26
|
+
const html = renderToStaticMarkup(<ApprovalCard
|
|
27
|
+
pendingApproval={{ approval: { ExitPlanMode: { plan: '## Implementation Steps\n- [ ] Step 1\n- [x] Step 2' } } }}
|
|
28
|
+
onApproval={() => {}}
|
|
29
|
+
/>)
|
|
30
|
+
expect(html).toContain('Plan Review')
|
|
31
|
+
expect(html).toContain('Approve and proceed')
|
|
32
|
+
expect(html).toContain('Deny (keep planning)')
|
|
33
|
+
expect(html).not.toContain('Always allow for this session')
|
|
34
|
+
})
|
|
24
35
|
})
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import React, { useState, useEffect } from 'react'
|
|
7
7
|
import { renderApprovalDetails, renderDiff } from '../../utils/approval'
|
|
8
|
+
import { FormattedMessage } from '../../utils/markdown'
|
|
8
9
|
import { DiffReviewModal } from './DiffReviewModal'
|
|
9
10
|
|
|
10
11
|
interface Props {
|
|
@@ -32,6 +33,8 @@ export function ApprovalCard({ pendingApproval, onApproval }: Props) {
|
|
|
32
33
|
const targetFilePath = skillWrite?.path || writeFile?.path || applyPatch?.path || 'Code Change'
|
|
33
34
|
const diffText = skillWrite?.diff || writeFile?.diff || applyPatch?.diff
|
|
34
35
|
const isAskUser = !!pendingApproval.approval?.AskUser
|
|
36
|
+
const isExitPlan = !!pendingApproval.approval?.ExitPlanMode
|
|
37
|
+
const isEnterPlan = !!pendingApproval.approval?.EnterPlanMode
|
|
35
38
|
const mcpTool = pendingApproval.approval?.McpTool
|
|
36
39
|
const MCP_ALLOW_ALL_SENTINEL = '__mcp_allow_all__'
|
|
37
40
|
const askOptions: AskUserOption[] = Array.isArray(pendingApproval.approval?.AskUser?.options)
|
|
@@ -58,6 +61,8 @@ export function ApprovalCard({ pendingApproval, onApproval }: Props) {
|
|
|
58
61
|
|
|
59
62
|
// Get badge label based on action type
|
|
60
63
|
const getToolMeta = () => {
|
|
64
|
+
if (isExitPlan) return { badge: 'Plan Review', badgeClass: 'plan' }
|
|
65
|
+
if (isEnterPlan) return { badge: 'Plan Mode', badgeClass: 'plan' }
|
|
61
66
|
if (skillWrite) return { badge: 'Skill Change', badgeClass: 'edit' }
|
|
62
67
|
if (runShell) return { badge: 'Run Command', badgeClass: details.isDangerous ? 'dangerous' : 'command' }
|
|
63
68
|
if (writeFile || applyPatch) return { badge: 'File Edit', badgeClass: 'edit' }
|
|
@@ -95,6 +100,16 @@ export function ApprovalCard({ pendingApproval, onApproval }: Props) {
|
|
|
95
100
|
action: () => onApproval(false),
|
|
96
101
|
},
|
|
97
102
|
]
|
|
103
|
+
: isExitPlan
|
|
104
|
+
? [
|
|
105
|
+
{ key: '1', title: 'Approve and proceed', variant: 'approve', action: () => onApproval(true, false) },
|
|
106
|
+
{ key: '2', title: 'Deny (keep planning)', variant: 'cancel', action: () => onApproval(false) },
|
|
107
|
+
]
|
|
108
|
+
: isEnterPlan
|
|
109
|
+
? [
|
|
110
|
+
{ key: '1', title: 'Enter plan mode', variant: 'approve', action: () => onApproval(true, false) },
|
|
111
|
+
{ key: '2', title: 'Cancel', variant: 'cancel', action: () => onApproval(false) },
|
|
112
|
+
]
|
|
98
113
|
: [
|
|
99
114
|
{
|
|
100
115
|
key: '1',
|
|
@@ -181,7 +196,7 @@ export function ApprovalCard({ pendingApproval, onApproval }: Props) {
|
|
|
181
196
|
gap: 6,
|
|
182
197
|
padding: '4px 10px',
|
|
183
198
|
fontSize: '0.75rem',
|
|
184
|
-
borderRadius: '8px',
|
|
199
|
+
borderRadius: 'var(--radius-sm, 8px)',
|
|
185
200
|
background: 'var(--accent-subtle)',
|
|
186
201
|
border: '1px solid var(--accent-border)',
|
|
187
202
|
color: 'var(--interactive-fg)',
|
|
@@ -193,6 +208,10 @@ export function ApprovalCard({ pendingApproval, onApproval }: Props) {
|
|
|
193
208
|
</div>
|
|
194
209
|
{renderDiff(diffText)}
|
|
195
210
|
</div>
|
|
211
|
+
) : isExitPlan ? (
|
|
212
|
+
<div className="approval-content-box plan-review-content" style={{ maxHeight: '360px', overflowY: 'auto' }}>
|
|
213
|
+
<FormattedMessage text={details.body} />
|
|
214
|
+
</div>
|
|
196
215
|
) : (
|
|
197
216
|
<div className={`approval-content-box ${isAskUser ? 'question-text' : ''}`}>
|
|
198
217
|
{details.body}
|
|
@@ -273,7 +292,7 @@ export function ApprovalCard({ pendingApproval, onApproval }: Props) {
|
|
|
273
292
|
<button
|
|
274
293
|
type="button"
|
|
275
294
|
className="approval-btn approval-btn-approve"
|
|
276
|
-
style={{ whiteSpace: 'nowrap', padding: '9px 16px', borderRadius: '8px' }}
|
|
295
|
+
style={{ whiteSpace: 'nowrap', padding: '9px 16px', borderRadius: 'var(--radius-sm, 8px)' }}
|
|
277
296
|
disabled={isMultiSelect ? selectedOptions.size === 0 && !askAnswer.trim() : !askAnswer.trim()}
|
|
278
297
|
onClick={() =>
|
|
279
298
|
onApproval(true, false, isMultiSelect ? buildMultiSelectAnswer() : askAnswer.trim())
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/// <reference path="../../env.d.ts" />
|
|
2
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
3
|
+
// @ts-ignore react-dom/server lacks types without @types/react-dom
|
|
4
|
+
import { renderToStaticMarkup } from 'react-dom/server'
|
|
5
|
+
import React from 'react'
|
|
6
|
+
import { ArtifactCards, extractArtifacts } from './ArtifactCards'
|
|
7
|
+
|
|
8
|
+
describe('ArtifactCards', () => {
|
|
9
|
+
it('extracts pdf and pptx files explicitly mentioned in aiText and converts to workspace-relative path', () => {
|
|
10
|
+
const aiText = 'ไฟล์สไลด์: `/home/pheem49/vscode/Project/Demo/AI_and_CLI_Presentation.pdf` และ `slides.pptx` รวมถึง `index.html`'
|
|
11
|
+
const artifacts = extractArtifacts([], aiText, '/home/pheem49/vscode/Project/Demo')
|
|
12
|
+
// Only PDF and PPTX, index.html must be ignored
|
|
13
|
+
expect(artifacts.length).toBe(2)
|
|
14
|
+
// AI_and_CLI_Presentation.pdf should have relative path
|
|
15
|
+
const pdf = artifacts.find(a => a.name === 'AI_and_CLI_Presentation.pdf')
|
|
16
|
+
expect(pdf).toBeDefined()
|
|
17
|
+
expect(pdf?.path).toBe('AI_and_CLI_Presentation.pdf')
|
|
18
|
+
expect(pdf?.type).toBe('pdf')
|
|
19
|
+
|
|
20
|
+
const pptx = artifacts.find(a => a.name === 'slides.pptx')
|
|
21
|
+
expect(pptx).toBeDefined()
|
|
22
|
+
expect(pptx?.type).toBe('presentation')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('does not extract random files from terminal ls or shell output', () => {
|
|
26
|
+
const progress: any[] = [
|
|
27
|
+
{
|
|
28
|
+
type: 'ToolEnd',
|
|
29
|
+
data: {
|
|
30
|
+
action: 'run_shell',
|
|
31
|
+
input: { command: 'ls -la' },
|
|
32
|
+
result: 'file1.pdf file2.pdf old_presentation.pdf',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
]
|
|
36
|
+
// If aiText doesn't mention them, no cards are created
|
|
37
|
+
const artifacts = extractArtifacts(progress, 'ฉันได้ตรวจสอบโฟลเดอร์เรียบร้อยแล้วค่ะ', '/home/user')
|
|
38
|
+
expect(artifacts.length).toBe(0)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('renders card with relative file path and Open in Side Panel button', () => {
|
|
42
|
+
const onOpenArtifact = vi.fn()
|
|
43
|
+
const aiText = 'สร้างไฟล์เสร็จแล้ว: `/home/user/workspace/presentation.pdf`'
|
|
44
|
+
const html = renderToStaticMarkup(
|
|
45
|
+
<ArtifactCards
|
|
46
|
+
aiText={aiText}
|
|
47
|
+
workspacePath="/home/user/workspace"
|
|
48
|
+
onOpenArtifact={onOpenArtifact}
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
expect(html).toContain('presentation.pdf')
|
|
53
|
+
expect(html).toContain('PDF')
|
|
54
|
+
expect(html).toContain('Open in Side Panel')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('renders cards with draggable attribute so users can drag into chat', () => {
|
|
58
|
+
const aiText = 'ไฟล์สไลด์: `presentation.pdf`'
|
|
59
|
+
const html = renderToStaticMarkup(
|
|
60
|
+
<ArtifactCards
|
|
61
|
+
aiText={aiText}
|
|
62
|
+
workspacePath="/home/user/workspace"
|
|
63
|
+
onOpenArtifact={() => {}}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
expect(html).toMatch(/class="chat-artifact-card[^"]*"[^>]*draggable="true"/)
|
|
67
|
+
expect(html).toContain('width:100%')
|
|
68
|
+
})
|
|
69
|
+
})
|