@pheem49/mint 1.15.0 → 1.16.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 +1012 -69
- package/Cargo.toml +5 -2
- package/LICENSE +21 -654
- package/README.md +92 -817
- package/Release_Note.md +53 -560
- package/apps/mint-companion/src-tauri/Cargo.toml +20 -0
- package/apps/mint-companion/src-tauri/build.rs +3 -0
- package/apps/mint-companion/src-tauri/src/main.rs +468 -0
- package/apps/mint-companion/tsconfig.json +20 -0
- package/apps/mint-companion/vite.config.ts +3 -0
- package/components.json +19 -0
- package/crates/mint-cli/Cargo.toml +6 -0
- package/crates/mint-cli/src/agent/live_status.rs +187 -39
- package/crates/mint-cli/src/agent.rs +323 -95
- package/crates/mint-cli/src/commands/agent.rs +69 -55
- package/crates/mint-cli/src/commands/integrations.rs +7 -0
- package/crates/mint-cli/src/commands/knowledge.rs +12 -32
- package/crates/mint-cli/src/commands/mod.rs +44 -0
- package/crates/mint-cli/src/image.rs +31 -33
- package/crates/mint-cli/src/interactive/chat_tui.rs +3594 -483
- package/crates/mint-cli/src/interactive/input_box.rs +56 -6
- package/crates/mint-cli/src/interactive/slash_commands.rs +208 -56
- package/crates/mint-cli/src/interactive/tool_activity.rs +328 -0
- package/crates/mint-cli/src/interactive.rs +64 -40
- package/crates/mint-cli/src/main.rs +13 -7
- package/crates/mint-cli/src/mcp.rs +5 -0
- package/crates/mint-cli/src/mod_host.rs +6 -0
- package/crates/mint-cli/src/mods_cli.rs +62 -0
- package/crates/mint-cli/src/mods_ui.rs +187 -0
- package/crates/mint-cli/src/onboard.rs +5 -31
- package/crates/mint-cli/src/terminal_theme.rs +3 -1
- package/crates/mint-cli/src/updater.rs +56 -2
- package/crates/mint-cli/tests/library_intake.rs +77 -0
- package/crates/mint-cli/tests/mods_testing.rs +133 -0
- package/crates/mint-companion-protocol/Cargo.toml +10 -0
- package/crates/mint-companion-protocol/src/lib.rs +163 -0
- package/crates/mint-core/Cargo.toml +6 -3
- package/crates/mint-core/build.rs +26 -0
- package/crates/mint-core/src/agent/chat.rs +167 -39
- package/crates/mint-core/src/agent/code_tools.rs +15 -0
- package/crates/mint-core/src/agent/memory/sources.rs +240 -0
- package/crates/mint-core/src/agent/memory.rs +147 -13
- package/crates/mint-core/src/agent/skill_inventory.rs +325 -0
- package/crates/mint-core/src/agent/skills.rs +437 -90
- package/crates/mint-core/src/agent.rs +1 -0
- package/crates/mint-core/src/api_server/routes/background_jobs.rs +310 -0
- package/crates/mint-core/src/api_server/routes/chat.rs +216 -199
- package/crates/mint-core/src/api_server/routes/html_preview.rs +77 -0
- package/crates/mint-core/src/api_server/routes/library.rs +97 -0
- package/crates/mint-core/src/api_server/routes/media_gen.rs +10 -57
- package/crates/mint-core/src/api_server/routes/misc.rs +104 -107
- package/crates/mint-core/src/api_server/routes/mod.rs +6 -0
- package/crates/mint-core/src/api_server/routes/mods.rs +31 -0
- package/crates/mint-core/src/api_server/routes/sessions.rs +41 -0
- package/crates/mint-core/src/api_server/routes/skills_subagents.rs +12 -42
- package/crates/mint-core/src/api_server/routes/slash.rs +50 -1
- package/crates/mint-core/src/api_server/routes/sources.rs +101 -0
- package/crates/mint-core/src/api_server.rs +118 -9
- package/crates/mint-core/src/avatar_bridge.rs +11 -2
- package/crates/mint-core/src/browser/session.rs +52 -0
- package/crates/mint-core/src/companion.rs +716 -0
- package/crates/mint-core/src/cron/scheduler.rs +34 -2
- package/crates/mint-core/src/integrations/channels.rs +87 -345
- package/crates/mint-core/src/integrations/mcp.rs +397 -50
- package/crates/mint-core/src/integrations/mcp_calls.rs +823 -0
- package/crates/mint-core/src/integrations/mcp_catalog.rs +267 -0
- package/crates/mint-core/src/integrations/mcp_device.rs +319 -0
- package/crates/mint-core/src/integrations/mcp_result.rs +356 -0
- package/crates/mint-core/src/integrations/webhooks.rs +539 -0
- package/crates/mint-core/src/integrations.rs +2 -0
- package/crates/mint-core/src/lib.rs +85 -26
- package/crates/mint-core/src/media/gemini_live.rs +134 -14
- package/crates/mint-core/src/media/image_models.rs +3 -27
- package/crates/mint-core/src/media/image_workflow.rs +216 -0
- package/crates/mint-core/src/media/library/intake.rs +144 -0
- package/crates/mint-core/src/media/library/migration.rs +56 -0
- package/crates/mint-core/src/media/library/removal.rs +55 -0
- package/crates/mint-core/src/media/library/tests.rs +730 -0
- package/crates/mint-core/src/media/library/thumbnails.rs +72 -0
- package/crates/mint-core/src/media/library.rs +545 -0
- package/crates/mint-core/src/media/model_catalog.rs +375 -0
- package/crates/mint-core/src/media/pictures.rs +79 -222
- package/crates/mint-core/src/media/video_models.rs +3 -22
- package/crates/mint-core/src/media.rs +3 -0
- package/crates/mint-core/src/mods/manager.rs +1124 -0
- package/crates/mint-core/src/mods/mod.rs +569 -0
- package/crates/mint-core/src/mods/operations.rs +204 -0
- package/crates/mint-core/src/mods/session.rs +146 -0
- package/crates/mint-core/src/mods/slash.rs +59 -0
- package/crates/mint-core/src/mods/telemetry.rs +306 -0
- package/crates/mint-core/src/orchestration/approvals.rs +344 -0
- package/crates/mint-core/src/orchestration/context_render.rs +104 -0
- package/crates/mint-core/src/orchestration/mcp_review.rs +153 -0
- package/crates/mint-core/src/orchestration/memory_skill.rs +104 -32
- package/crates/mint-core/src/orchestration/mod.rs +2139 -244
- package/crates/mint-core/src/orchestration/mod_authoring_regressions.rs +209 -0
- package/crates/mint-core/src/orchestration/progress_clock.rs +80 -0
- package/crates/mint-core/src/orchestration/repeated_failures.rs +116 -0
- package/crates/mint-core/src/orchestration/review_regressions.rs +449 -0
- package/crates/mint-core/src/orchestration/run_control.rs +196 -0
- package/crates/mint-core/src/orchestration/tools/files.rs +161 -14
- package/crates/mint-core/src/orchestration/tools/media.rs +37 -41
- package/crates/mint-core/src/orchestration/tools/misc.rs +3 -2
- package/crates/mint-core/src/orchestration/tools/mod.rs +2 -0
- package/crates/mint-core/src/orchestration/tools/mods.rs +161 -0
- package/crates/mint-core/src/orchestration/tools/plugins_mcp.rs +303 -71
- package/crates/mint-core/src/orchestration/tools/shell.rs +95 -2
- package/crates/mint-core/src/orchestration/workspace_helpers.rs +4 -1
- package/crates/mint-core/src/prompts/agent.rs +17 -2
- package/crates/mint-core/src/prompts/tool_catalog.rs +28 -2
- package/crates/mint-core/src/search/knowledge.rs +7 -1
- package/crates/mint-core/src/search/linked_folders/index.rs +177 -13
- package/crates/mint-core/src/search/linked_folders.rs +83 -2
- package/crates/mint-core/src/slash/catalog.rs +1 -1
- package/crates/mint-core/src/slash/mod.rs +174 -11
- package/crates/mint-core/src/slash/mods.rs +155 -0
- package/crates/mint-core/src/system/bg_shell.rs +1129 -95
- package/crates/mint-core/src/system/config.rs +5 -10
- package/crates/mint-core/src/system/html_preview.rs +398 -0
- package/crates/mint-core/src/system/mint_web.rs +164 -0
- package/crates/mint-core/src/system/release_notes.rs +18 -0
- package/crates/mint-core/src/system/shell.rs +21 -6
- package/crates/mint-core/src/system/workspace.rs +72 -8
- package/crates/mint-core/src/system/workspace_history.rs +604 -0
- package/crates/mint-core/src/system.rs +4 -0
- package/crates/mint-core/tests/background_retention.rs +34 -0
- package/crates/mint-core/tests/background_shutdown.rs +24 -0
- package/crates/mint-core/tests/library_http.rs +209 -0
- package/crates/mint-core/tests/mcp_contract.rs +283 -0
- package/crates/mint-core/tests/mcp_stdio.rs +11 -10
- package/crates/mint-core/tests/media_model_catalog_http.rs +403 -0
- package/crates/mint-core/tests/mods_http.rs +215 -0
- package/crates/mint-core/tests/terminal_shutdown.rs +109 -0
- package/crates/mint-mod-runtime/Cargo.toml +18 -0
- package/crates/mint-mod-runtime/src/lib.rs +507 -0
- package/crates/mint-mod-runtime/src/sdk.js +56 -0
- package/crates/mint-mod-runtime/src/test_sdk.js +32 -0
- package/crates/mint-mod-runtime/src/testing.rs +94 -0
- package/crates/mint-mod-runtime/tests/runtime.rs +156 -0
- package/docs/mods/AUTHORING.md +61 -0
- package/docs/mods/README.md +139 -0
- package/docs/mods/TESTING.md +56 -0
- package/docs/mods/mint-mods.d.ts +66 -0
- package/examples/device-mcp/README.md +22 -0
- package/examples/device-mcp/contract.md +49 -0
- package/examples/device-mcp/mock-device.mjs +66 -0
- package/examples/device-mcp/server.mjs +48 -0
- package/examples/device-mcp/server.test.mjs +78 -0
- package/examples/mods/task-checklist/README.md +1 -0
- package/examples/mods/task-checklist/main.ts +17 -0
- package/examples/mods/task-checklist/manifest.json +1 -0
- package/examples/mods/task-checklist/tests/checklist.test.ts +15 -0
- package/examples/mods/token-meter/README.md +1 -0
- package/examples/mods/token-meter/main.ts +8 -0
- package/examples/mods/token-meter/manifest.json +1 -0
- package/examples/mods/tool-guard/README.md +1 -0
- package/examples/mods/tool-guard/main.ts +9 -0
- package/examples/mods/tool-guard/manifest.json +1 -0
- package/out/web/assets/CliSessionsView-CtzUJpK_.css +1 -0
- package/out/web/assets/CliSessionsView-D7hw0Mgj.js +1 -0
- package/out/web/assets/CodeReviewPage-C7bEOJfd.js +4 -0
- package/out/web/assets/CodeReviewPage-Dte9uLiL.css +1 -0
- package/out/web/assets/CommandPalette-0RrF-AOT.js +1 -0
- package/out/web/assets/ImageStudioPanel-CdxkAf_r.js +1 -0
- package/out/web/assets/LibraryPage--Qfisp6D.js +2 -0
- package/out/web/assets/LibraryPage-DAxUTAg7.css +1 -0
- package/out/web/assets/LinkedFoldersView-2nfZbDgN.js +1 -0
- package/out/web/assets/McpRegistryPicker-h9uS8_wT.js +1 -0
- package/out/web/assets/McpServersView-slfQJzNB.js +1 -0
- package/out/web/assets/MintDashboard-BSR5XpXh.js +25 -0
- package/out/web/assets/MintDashboard-CWUcCGhd.css +1 -0
- package/out/web/assets/PluginsView-l7LSm503.js +1 -0
- package/out/web/assets/ScheduledTasksView-CttmLbq1.js +1 -0
- package/out/web/assets/SettingsWindow-BCMLYvEV.js +4 -0
- package/out/web/assets/SettingsWindow-DcMVmU9u.css +1 -0
- package/out/web/assets/SkillsView-rNs1qr_U.js +2 -0
- package/out/web/assets/ToolSurfacePage-B9DzEPWN.js +37 -0
- package/out/web/assets/ToolSurfacePage-CTfgggF2.css +1 -0
- package/out/web/assets/VeoStudioPanel-DiJs_Cg2.js +4 -0
- package/out/web/assets/WorkspaceSelector-B2xIp04D.js +1 -0
- package/out/web/assets/WorkspaceSelector-Ca8uJOsS.css +1 -0
- package/out/web/assets/{abnfDiagram-VCTEODGH-ByMyfanq.js → abnfDiagram-VCTEODGH-CD0CjoGl.js} +1 -1
- package/out/web/assets/{architecture-7GRP2DOG-CLq2kEOB.js → architecture-7GRP2DOG-RKV83OeZ.js} +1 -1
- package/out/web/assets/{architectureDiagram-5GKGNRK7-6PoVSmNG.js → architectureDiagram-5GKGNRK7-nN_HAFct.js} +1 -1
- package/out/web/assets/{blockDiagram-NRAW4CY4-cKw9mAKi.js → blockDiagram-NRAW4CY4-BrrqzHW5.js} +1 -1
- package/out/web/assets/{c4Diagram-UCG6FXSJ-Cqy8N5Ge.js → c4Diagram-UCG6FXSJ-DTdV8_zE.js} +1 -1
- package/out/web/assets/{chunk-75Z2AOVW-3qybijF5.js → chunk-75Z2AOVW-_M0z5olV.js} +1 -1
- package/out/web/assets/chunk-CKBBP62Z-BpQEgeHF.js +2 -0
- package/out/web/assets/{chunk-CLGD4ZFX-CndDQkww.js → chunk-CLGD4ZFX-D54yGvGS.js} +1 -1
- package/out/web/assets/{chunk-DSNCTWBM-Cc4NxvgD.js → chunk-DSNCTWBM-C-gvT2ru.js} +1 -1
- package/out/web/assets/{chunk-DU6HZSFF-drzh6GsU.js → chunk-DU6HZSFF-CnFngIhW.js} +1 -1
- package/out/web/assets/{chunk-F27PBJKO-FiY35l4v.js → chunk-F27PBJKO-BqtWrnEO.js} +1 -1
- package/out/web/assets/{chunk-G27WJ6UU-Bjt9Il4A.js → chunk-G27WJ6UU-Ckoq5mi2.js} +1 -1
- package/out/web/assets/{chunk-GMAD6QVW-Bppi3Ctd.js → chunk-GMAD6QVW-BuhEcgHq.js} +1 -1
- package/out/web/assets/{chunk-JQ64N6SF-DGg5kcEV.js → chunk-JQ64N6SF-CF8T7GiZ.js} +1 -1
- package/out/web/assets/{chunk-LCL6LL3I-CCYcjd7p.js → chunk-LCL6LL3I-BhXV9zyH.js} +1 -1
- package/out/web/assets/{chunk-OBVCFTLP-DJeNil5M.js → chunk-OBVCFTLP-CRIkunUB.js} +1 -1
- package/out/web/assets/{chunk-P2QGCYS3-lRzkRjBB.js → chunk-P2QGCYS3-UFEU6BxZ.js} +1 -1
- package/out/web/assets/{chunk-POPQ4Y6H-DouASMBW.js → chunk-POPQ4Y6H-CQcrNbjr.js} +1 -1
- package/out/web/assets/{chunk-PWAF6VOD-DMmD1vVf.js → chunk-PWAF6VOD-Cc2uVDsG.js} +1 -1
- package/out/web/assets/{chunk-R7TYR2AO-CYLA5UC5.js → chunk-R7TYR2AO-DiCxzdAY.js} +1 -1
- package/out/web/assets/{chunk-RHFEMEQ7-BiXwEcUT.js → chunk-RHFEMEQ7-b7hnPmrR.js} +1 -1
- package/out/web/assets/{chunk-SVP7TREG-BV-zPslF.js → chunk-SVP7TREG-Bu_yYb-V.js} +1 -1
- package/out/web/assets/{chunk-TEH6E4GO-B2RGEohZ.js → chunk-TEH6E4GO-G4Cdlyrt.js} +1 -1
- package/out/web/assets/classDiagram-DTDB5LWJ-RnC2mYO4.js +1 -0
- package/out/web/assets/classDiagram-v2-JRS7N3AN-RnC2mYO4.js +1 -0
- package/out/web/assets/config-CnvCChUM.js +2 -0
- package/out/web/assets/config-DM6oIVO3.css +1 -0
- package/out/web/assets/core-DsKkQ7ig.js +1 -0
- package/out/web/assets/{cynefin-OW5HDTMX-Cas4csHM.js → cynefin-OW5HDTMX-CnzQfOGp.js} +1 -1
- package/out/web/assets/{cynefinDiagram-5FMLGOSQ-Bbpj66Y3.js → cynefinDiagram-5FMLGOSQ-DVtQnfpm.js} +1 -1
- package/out/web/assets/{dagre-3AP2YEHR-B0-2RDEd.js → dagre-3AP2YEHR-DG76_k5_.js} +1 -1
- package/out/web/assets/{diagram-S7CK7UJ4-BdzEjUyH.js → diagram-S7CK7UJ4-CaouUoze.js} +1 -1
- package/out/web/assets/{diagram-UQ7AKVKN-CJDwyPxF.js → diagram-UQ7AKVKN-B4bEc26B.js} +1 -1
- package/out/web/assets/{diagram-VSXAHHWV-BxaG1r_B.js → diagram-VSXAHHWV-BJ86Ov2Y.js} +1 -1
- package/out/web/assets/{diagram-VX7I27RA-BMmUqm8f.js → diagram-VX7I27RA-7hH5IPYf.js} +1 -1
- package/out/web/assets/{diagram-Z3DM3KII-CFtd03eE.js → diagram-Z3DM3KII-CCM4clo8.js} +1 -1
- package/out/web/assets/dist-js-BkYNznHX.js +1 -0
- package/out/web/assets/{ebnfDiagram-PWID7BFC-DwAen1hO.js → ebnfDiagram-PWID7BFC-Da7WAM3k.js} +1 -1
- package/out/web/assets/{erDiagram-SSCWMZ5O-BCZSHACj.js → erDiagram-SSCWMZ5O-CzzmnZWT.js} +1 -1
- package/out/web/assets/{event-ChBVpRy0.js → event-Cdt7Byyj.js} +1 -1
- package/out/web/assets/{eventmodeling-NTZA5JFV-XHStE4E_.js → eventmodeling-NTZA5JFV-xcfsA0XD.js} +1 -1
- package/out/web/assets/flowDiagram-A5DVABFB-JdtH1673.js +1 -0
- package/out/web/assets/{ganttDiagram-EL5Y4UJY-BAEu1Cql.js → ganttDiagram-EL5Y4UJY-B3ClFGmL.js} +1 -1
- package/out/web/assets/{gitGraph-4MIJSDKK-r32Vyper.js → gitGraph-4MIJSDKK-BZ_y_cDU.js} +1 -1
- package/out/web/assets/{gitGraphDiagram-WWUBYQGX-z9o9qt6V.js → gitGraphDiagram-WWUBYQGX-drhRSYm3.js} +1 -1
- package/out/web/assets/index-BZ9xgmMP.css +1 -0
- package/out/web/assets/index-Ca8cCS4h.js +168 -0
- package/out/web/assets/{info-A6RAGUB7-BvLaC2cw.js → info-A6RAGUB7-B7I3K0F1.js} +1 -1
- package/out/web/assets/{infoDiagram-RXCK75RN-Be6WAXXw.js → infoDiagram-RXCK75RN-deX_1MPh.js} +1 -1
- package/out/web/assets/{ishikawaDiagram-5VMMS53U-DZjoHJHC.js → ishikawaDiagram-5VMMS53U-s38yo28y.js} +1 -1
- package/out/web/assets/{journeyDiagram-EYS64GPL-CtVkjkGm.js → journeyDiagram-EYS64GPL-CZn2kB8b.js} +1 -1
- package/out/web/assets/jsx-runtime-DN4NhQUK.js +1 -0
- package/out/web/assets/{kanban-definition-3QL26DDD-CW5FMv1w.js → kanban-definition-3QL26DDD-DodjgySL.js} +1 -1
- package/out/web/assets/markdown-CMhYIcWB.js +39 -0
- package/out/web/assets/{mermaid-parser.core-aUgCqsZ5.js → mermaid-parser.core-Whu2rlJC.js} +3 -3
- package/out/web/assets/{mermaid.core-D57sEiSL.js → mermaid.core-CKyPo8VH.js} +4 -4
- package/out/web/assets/{mindmap-definition-FBJOCRG2-DAmSpM3a.js → mindmap-definition-FBJOCRG2-260WBDxZ.js} +1 -1
- package/out/web/assets/modelManager-CUaGWMWu.js +2 -0
- package/out/web/assets/{oauthManager-9jxicDWJ.js → oauthManager-DlNhXJr6.js} +1 -1
- package/out/web/assets/{packet-AYTQ26CC-DJ27iIoJ.js → packet-AYTQ26CC-CEeIRKRG.js} +1 -1
- package/out/web/assets/{pegDiagram-XKGWAZYB-Bj3ii-gS.js → pegDiagram-XKGWAZYB-BYadI-KO.js} +1 -1
- package/out/web/assets/{pie-WAS4IAKB-DG5mCUbc.js → pie-WAS4IAKB-D8uf4dh5.js} +1 -1
- package/out/web/assets/{pieDiagram-E7YTZNPT-BrJLPnDA.js → pieDiagram-E7YTZNPT-CjSDy4hO.js} +1 -1
- package/out/web/assets/{quadrantDiagram-AXDQQJYC-3x_TmF3j.js → quadrantDiagram-AXDQQJYC-B8D3gU5d.js} +1 -1
- package/out/web/assets/{radar-RG4KPBEZ-CrXaTTuV.js → radar-RG4KPBEZ-DZJxnokY.js} +1 -1
- package/out/web/assets/{railroad-74A4TZTK-BpqMH9BE.js → railroad-74A4TZTK-DBysUiUi.js} +1 -1
- package/out/web/assets/{railroad-abnf-HS5TGJTU-DHI0uLlV.js → railroad-abnf-HS5TGJTU-CHWxoJYg.js} +1 -1
- package/out/web/assets/{railroad-ebnf-LZEXJU2U-CQCb316y.js → railroad-ebnf-LZEXJU2U-DDv7X6bY.js} +1 -1
- package/out/web/assets/{railroad-peg-WCYAUIDC-Ph1giKkH.js → railroad-peg-WCYAUIDC-DpfcYYNJ.js} +1 -1
- package/out/web/assets/{railroadDiagram-O6MQD6OU-BRq6wIxx.js → railroadDiagram-O6MQD6OU-CYtyv0t3.js} +1 -1
- package/out/web/assets/{requirementDiagram-EFPCY7ZU-DIJj6G1g.js → requirementDiagram-EFPCY7ZU-D2X-Ewik.js} +1 -1
- package/out/web/assets/{sankeyDiagram-P5KCCOFB-DZajSryq.js → sankeyDiagram-P5KCCOFB-Bn2x6C4Y.js} +1 -1
- package/out/web/assets/{sequenceDiagram-WJ2MYXX4-DxJCWyZS.js → sequenceDiagram-WJ2MYXX4-BvFLKtPd.js} +1 -1
- package/out/web/assets/{stateDiagram-HBIQ2CUA-k6voi8Vf.js → stateDiagram-HBIQ2CUA-Bx0GWeaY.js} +1 -1
- package/out/web/assets/stateDiagram-v2-4QOOHH4V--hol1yg_.js +1 -0
- package/out/web/assets/{swimlanes-XN3QIQJK-igYhTjXB.js → swimlanes-XN3QIQJK-CCma0T7L.js} +1 -1
- package/out/web/assets/swimlanesDiagram-VK2B7HYN-BkohoVsU.js +8 -0
- package/out/web/assets/{timeline-definition-24CTP7MA-Dke2p93p.js → timeline-definition-24CTP7MA-iCRhhJ7C.js} +1 -1
- package/out/web/assets/{treeView-Q6P3EWNA-hNELnXUs.js → treeView-Q6P3EWNA-DZ-y08qp.js} +1 -1
- package/out/web/assets/{treemap-WGGIJYW6-D2B6wDsx.js → treemap-WGGIJYW6-De0CxzMx.js} +1 -1
- package/out/web/assets/{vennDiagram-4TSXK5OY-CDkW7rUP.js → vennDiagram-4TSXK5OY-w_7aZ6xe.js} +1 -1
- package/out/web/assets/{wardley-WFR3VGLG-BECdXETi.js → wardley-WFR3VGLG-DT0y0xJ4.js} +1 -1
- package/out/web/assets/{wardleyDiagram-VM6X3IG4-B5BycpQ4.js → wardleyDiagram-VM6X3IG4-DAdXELbQ.js} +1 -1
- package/out/web/assets/window-BJCVtyET.js +1 -0
- package/out/web/assets/{xychartDiagram-S5SC5T6Z-CtJS3b--.js → xychartDiagram-S5SC5T6Z-IZIXf3Vo.js} +1 -1
- package/out/web/index-web.html +3 -2
- package/out/web/index.html +3 -2
- package/package.json +71 -22
- package/shared-modules/.github/workflows/ci.yml +120 -0
- package/shared-modules/.github/workflows/update.yaml +28 -0
- package/slash-commands.json +7 -2
- package/src/bin/auto-build.js +66 -0
- package/src/bin/desktop.js +113 -0
- package/src/bin/desktop.test.js +113 -0
- package/src/bin/index.js +18 -25
- package/src/bin/index.test.js +89 -0
- package/src/bin/measure-effects.mjs +53 -0
- package/src/bin/package.test.js +28 -0
- package/src/bin/release-notes.test.js +84 -0
- package/src/bin/styles.test.js +20 -0
- package/src/bin/web.js +5 -0
- package/src/bin/web.test.js +39 -0
- package/src/renderer/index.html +0 -2
- package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/src/renderer/shared/agentProgress.ts +33 -0
- package/src/renderer/shared/components/AgentActivityDrawer.tsx +3 -2
- package/src/renderer/shared/components/AgentActivityTable.tsx +1 -1
- package/src/renderer/shared/components/ApprovalCard.test.tsx +24 -0
- package/src/renderer/shared/components/ApprovalCard.tsx +10 -3
- package/src/renderer/shared/components/ArtifactPreviewPanel.tsx +88 -37
- package/src/renderer/shared/components/AuthGate.tsx +75 -39
- package/src/renderer/shared/components/BackgroundTerminals.tsx +181 -0
- package/src/renderer/shared/components/ChatCodeBlock.tsx +8 -4
- package/src/renderer/shared/components/ChatMessageItem.test.tsx +68 -0
- package/src/renderer/shared/components/ChatMessageItem.tsx +36 -16
- package/src/renderer/shared/components/ChatPanel.test.tsx +21 -0
- package/src/renderer/shared/components/ChatPanel.tsx +294 -272
- package/src/renderer/shared/components/ChunkErrorBoundary.tsx +4 -102
- package/src/renderer/shared/components/CliSessionsView.test.tsx +125 -0
- package/src/renderer/shared/components/CliSessionsView.tsx +61 -13
- package/src/renderer/shared/components/CodeReviewPage.tsx +111 -8
- package/src/renderer/shared/components/CollapsiblePasteInput.tsx +90 -0
- package/src/renderer/shared/components/ContextCompactionStatus.tsx +17 -0
- package/src/renderer/shared/components/DashboardSidebar.tsx +15 -128
- package/src/renderer/shared/components/DesktopTitlebar.tsx +45 -19
- package/src/renderer/shared/components/ErrorNotice.tsx +29 -0
- package/src/renderer/shared/components/FormattedMessage.tsx +11 -0
- package/src/renderer/shared/components/GeminiLiveOverlay.css +86 -0
- package/src/renderer/shared/components/GeminiLiveOverlay.test.tsx +24 -0
- package/src/renderer/shared/components/GeminiLiveOverlay.tsx +85 -101
- package/src/renderer/shared/components/GlideSelect.css +138 -0
- package/src/renderer/shared/components/GlideSelect.d.ts +31 -0
- package/src/renderer/shared/components/GlideSelect.jsx +266 -0
- package/src/renderer/shared/components/ImageSearchCard.tsx +46 -56
- package/src/renderer/shared/components/ImageStudioPanel.tsx +9 -8
- package/src/renderer/shared/components/LibraryItemCard.tsx +72 -0
- package/src/renderer/shared/components/LibraryPage.tsx +165 -0
- package/src/renderer/shared/components/LibraryPreview.tsx +59 -0
- package/src/renderer/shared/components/McpServersView.tsx +27 -8
- package/src/renderer/shared/components/McpToolAllowlist.tsx +2 -4
- package/src/renderer/shared/components/McpToolResults.tsx +99 -0
- package/src/renderer/shared/components/MintDashboard.tsx +308 -770
- package/src/renderer/shared/components/ModSessionControls.tsx +8 -0
- package/src/renderer/shared/components/ModUi.test.tsx +65 -0
- package/src/renderer/shared/components/ModUi.tsx +26 -0
- package/src/renderer/shared/components/ModelSelectorPopover.tsx +14 -7
- package/src/renderer/shared/components/ModsPanel.tsx +156 -0
- package/src/renderer/shared/components/ProgressActivity.tsx +17 -0
- package/src/renderer/shared/components/ReviewHistory.tsx +42 -0
- package/src/renderer/shared/components/RewindModal.tsx +5 -12
- package/src/renderer/shared/components/RunSummaryDashboard.tsx +6 -12
- package/src/renderer/shared/components/ScheduledTasksView.tsx +7 -6
- package/src/renderer/shared/components/SelectField.test.tsx +27 -0
- package/src/renderer/shared/components/SelectField.tsx +38 -0
- package/src/renderer/shared/components/SessionSources.tsx +48 -0
- package/src/renderer/shared/components/SessionSourcesPopover.tsx +61 -0
- package/src/renderer/shared/components/Settings/AgentsTab.tsx +7 -6
- package/src/renderer/shared/components/Settings/AudioTab.tsx +8 -7
- package/src/renderer/shared/components/Settings/AutomationTab.tsx +2 -2
- package/src/renderer/shared/components/Settings/GeneralTab.tsx +33 -32
- package/src/renderer/shared/components/Settings/MemoryTab.test.tsx +37 -0
- package/src/renderer/shared/components/Settings/MemoryTab.tsx +71 -31
- package/src/renderer/shared/components/Settings/NotificationsTab.test.tsx +15 -0
- package/src/renderer/shared/components/Settings/NotificationsTab.tsx +84 -0
- package/src/renderer/shared/components/Settings/ThemeTab.tsx +19 -11
- package/src/renderer/shared/components/SlashChoicePanel.tsx +88 -0
- package/src/renderer/shared/components/SlashSuggestions.test.tsx +33 -0
- package/src/renderer/shared/components/SlashSuggestions.tsx +38 -10
- package/src/renderer/shared/components/SourcesBlock.tsx +12 -20
- package/src/renderer/shared/components/ToolSurfacePage.test.tsx +32 -0
- package/src/renderer/shared/components/ToolSurfacePage.tsx +59 -11
- package/src/renderer/shared/components/ToolsPanelToggle.tsx +13 -0
- package/src/renderer/shared/components/VeoStudioPanel.tsx +9 -8
- package/src/renderer/shared/components/ViewedImages.tsx +36 -0
- package/src/renderer/shared/components/VirtualChatHistory.tsx +82 -0
- package/src/renderer/shared/components/VoicePill.css +85 -0
- package/src/renderer/shared/components/VoicePill.d.ts +12 -0
- package/src/renderer/shared/components/VoicePill.jsx +190 -0
- package/src/renderer/shared/components/VoicePill.test.tsx +22 -0
- package/src/renderer/shared/components/WorkspaceContextPopover.tsx +20 -15
- package/src/renderer/shared/components/WorkspacePaneResizer.tsx +92 -0
- package/src/renderer/shared/components/WorkspacePreviewActions.test.tsx +44 -0
- package/src/renderer/shared/components/WorkspacePreviewActions.tsx +19 -0
- package/src/renderer/shared/components/WorkspaceSelector.tsx +13 -8
- package/src/renderer/shared/components/background-terminals.css +292 -0
- package/src/renderer/shared/components/ui/README.md +52 -0
- package/src/renderer/shared/components/ui/button.tsx +37 -0
- package/src/renderer/shared/components/ui/demo.tsx +26 -0
- package/src/renderer/shared/components/ui/error-recovery.css +35 -0
- package/src/renderer/shared/components/ui/error-recovery.tsx +35 -0
- package/src/renderer/shared/components/ui/voice-powered-orb.css +6 -0
- package/src/renderer/shared/components/ui/voice-powered-orb.tsx +374 -0
- package/src/renderer/shared/components/workspace-selector.css +248 -0
- package/src/renderer/shared/constants/config.ts +30 -1
- package/src/renderer/shared/constants/slashCommands.ts +1 -1
- package/src/renderer/shared/conversation/lifecycle.test.ts +362 -0
- package/src/renderer/shared/conversation/lifecycle.ts +418 -0
- package/src/renderer/shared/conversation/projectNavigation.test.ts +105 -0
- package/src/renderer/shared/conversation/projectNavigation.ts +39 -0
- package/src/renderer/shared/conversation/sourcesTransport.ts +27 -0
- package/src/renderer/shared/conversation/syncView.test.ts +1 -34
- package/src/renderer/shared/conversation/syncView.ts +0 -37
- package/src/renderer/shared/conversation/transport.test.ts +163 -0
- package/src/renderer/shared/conversation/transport.ts +159 -0
- package/src/renderer/shared/conversation/useConversationCoordinator.ts +30 -72
- package/src/renderer/shared/css/agent-observability.css +20 -21
- package/src/renderer/shared/css/auth-gate.css +112 -13
- package/src/renderer/shared/css/code-review.css +33 -0
- package/src/renderer/shared/css/code-sessions.css +27 -0
- package/src/renderer/shared/css/collapsed-paste.css +35 -0
- package/src/renderer/shared/css/effects.css +15 -0
- package/src/renderer/shared/css/error-notice.css +60 -0
- package/src/renderer/shared/css/library.css +476 -0
- package/src/renderer/shared/css/management-views.css +138 -0
- package/src/renderer/shared/css/mcp-results.css +11 -0
- package/src/renderer/shared/css/model-selector.css +163 -105
- package/src/renderer/shared/css/mods.css +77 -0
- package/src/renderer/shared/css/notification-notice.css +28 -0
- package/src/renderer/shared/css/session-sources-popover.css +9 -0
- package/src/renderer/shared/css/session-sources.css +23 -0
- package/src/renderer/shared/css/settings/memory.css +154 -0
- package/src/renderer/shared/css/settings/notifications.css +11 -0
- package/src/renderer/shared/css/settings/theme.css +5 -0
- package/src/renderer/shared/css/slash-choice.css +95 -0
- package/src/renderer/shared/css/slash-suggestions.css +68 -0
- package/src/renderer/shared/css/sources-block.css +91 -0
- package/src/renderer/shared/css/thinking-status.css +46 -0
- package/src/renderer/shared/css/tools-panel.css +7 -0
- package/src/renderer/shared/css/ui-tailwind.css +19 -0
- package/src/renderer/shared/css/viewed-images.css +15 -0
- package/src/renderer/shared/fonts.css +46 -0
- package/src/renderer/shared/fonts.ts +3 -12
- package/src/renderer/shared/lib/utils.ts +6 -0
- package/src/renderer/shared/library/controller.test.ts +61 -0
- package/src/renderer/shared/library/controller.ts +57 -0
- package/src/renderer/shared/library/transport.test.ts +26 -0
- package/src/renderer/shared/library/transport.ts +60 -0
- package/src/renderer/shared/library/useLibraryFile.ts +38 -0
- package/src/renderer/shared/mods.ts +58 -0
- package/src/renderer/shared/platform.test.ts +57 -1
- package/src/renderer/shared/platform.ts +46 -1
- package/src/renderer/shared/theme/themeManager.test.ts +43 -0
- package/src/renderer/shared/theme/themeManager.ts +17 -4
- package/src/renderer/shared/types.ts +56 -2
- package/src/renderer/shared/utils/agentActivity.test.ts +75 -0
- package/src/renderer/shared/utils/agentActivity.ts +42 -3
- package/src/renderer/shared/utils/approval.tsx +7 -0
- package/src/renderer/shared/utils/artifactBrowser.test.ts +80 -0
- package/src/renderer/shared/utils/artifactBrowser.ts +41 -0
- package/src/renderer/shared/utils/contextCompaction.test.tsx +48 -0
- package/src/renderer/shared/utils/contextCompaction.ts +21 -0
- package/src/renderer/shared/utils/effectVisibility.ts +9 -0
- package/src/renderer/shared/utils/markdown.tsx +3 -3
- package/src/renderer/shared/utils/mcpResults.test.tsx +91 -0
- package/src/renderer/shared/utils/modViewport.ts +7 -0
- package/src/renderer/shared/utils/nativeRecordingSession.test.ts +61 -0
- package/src/renderer/shared/utils/nativeRecordingSession.ts +46 -0
- package/src/renderer/shared/utils/notificationSettings.test.ts +14 -0
- package/src/renderer/shared/utils/notificationSettings.ts +23 -0
- package/src/renderer/shared/utils/notifications.test.ts +51 -0
- package/src/renderer/shared/utils/notifications.ts +54 -0
- package/src/renderer/shared/utils/pastedText.test.ts +20 -0
- package/src/renderer/shared/utils/pastedText.ts +13 -0
- package/src/renderer/shared/utils/progressCache.test.ts +32 -0
- package/src/renderer/shared/utils/sessionSources.test.ts +31 -0
- package/src/renderer/shared/utils/sessionSources.ts +34 -0
- package/src/renderer/shared/utils/slashCommandProcessor.ts +1 -1
- package/src/renderer/shared/utils/sourceAttachments.ts +28 -0
- package/src/renderer/shared/utils/speech.ts +51 -9
- package/src/renderer/shared/utils/syntaxHighlight.test.tsx +22 -0
- package/src/renderer/shared/utils/syntaxHighlight.tsx +26 -0
- package/src/renderer/shared/utils/useGeminiLiveVoice.ts +49 -5
- package/src/renderer/shared/utils/useLatestCallback.ts +9 -0
- package/src/renderer/shared/utils/useNativeVoiceInput.ts +80 -72
- package/src/renderer/shared/utils/useSessionSources.ts +33 -0
- package/src/renderer/shared/utils/viewedImages.ts +26 -0
- package/src/renderer/shared/utils/workspacePane.test.ts +33 -0
- package/src/renderer/shared/utils/workspacePane.ts +20 -0
- package/src/renderer/shared/utils/workspacePreview.test.ts +24 -0
- package/src/renderer/shared/utils/workspacePreview.ts +16 -0
- package/src/renderer/shared/utils/workspaceSnapshot.test.ts +49 -0
- package/src/renderer/shared/utils/workspaceSnapshot.ts +26 -0
- package/src/renderer/shared/utils/workspaces.ts +10 -0
- package/src/renderer/shared/workspaceUndo.ts +88 -0
- package/src/renderer/src/App.tsx +9 -1
- package/src/renderer/src/components/LiveTranslateControls.tsx +65 -0
- package/src/renderer/src/components/PicturesLibrary.tsx +2 -288
- package/src/renderer/src/components/ScreenPicker.css +67 -30
- package/src/renderer/src/components/ScreenPicker.tsx +201 -60
- package/src/renderer/src/components/SettingsWindow.tsx +10 -5
- package/src/renderer/src/components/WorkspacePanel.tsx +222 -32
- package/src/renderer/src/components/browser-shell.css +1 -1
- package/src/renderer/src/components/browser-suggestions-popup.css +1 -1
- package/src/renderer/src/components/liveTranslateFrames.test.ts +26 -5
- package/src/renderer/src/components/liveTranslateFrames.ts +18 -7
- package/src/renderer/src/components/liveTranslateLanguage.ts +6 -0
- package/src/renderer/src/css/app-shell.css +52 -137
- package/src/renderer/src/css/chat.css +21 -495
- package/src/renderer/src/css/desktop-tools.css +199 -1
- package/src/renderer/src/css/misc.css +0 -52
- package/src/renderer/src/css/pictures.css +2 -415
- package/src/renderer/src/css/settings/base.css +50 -47
- package/src/renderer/src/css/sidebar-workspace.css +151 -94
- package/src/renderer/src/css/tool-surfaces.css +65 -9
- package/src/renderer/src/css/widget.css +1 -1
- package/src/renderer/src/env.d.ts +1 -9
- package/src/renderer/src/index.css +1 -1
- package/src/renderer/src/main.tsx +2 -1
- package/src/renderer/src/proactiveSuggestions.ts +29 -0
- package/src/renderer/src/tauri.ts +122 -330
- package/src/renderer/src/voiceInput.ts +2 -1
- package/src/renderer/src-web/components/PicturesLibrary.tsx +2 -285
- package/src/renderer/src-web/components/PullToRefresh.tsx +1 -1
- package/src/renderer/src-web/components/SettingsWindow.tsx +10 -5
- package/src/renderer/src-web/css/app-shell.css +24 -121
- package/src/renderer/src-web/css/chat.css +21 -495
- package/src/renderer/src-web/css/misc.css +0 -52
- package/src/renderer/src-web/css/mobile.css +15 -14
- package/src/renderer/src-web/css/pictures.css +2 -462
- package/src/renderer/src-web/css/settings/base.css +50 -47
- package/src/renderer/src-web/css/sidebar-workspace.css +9 -95
- package/src/renderer/src-web/css/widget.css +1 -1
- package/src/renderer/src-web/env.d.ts +1 -12
- package/src/renderer/src-web/index.css +1 -1
- package/src/renderer/src-web/main.tsx +2 -1
- package/src/renderer/src-web/proactiveSuggestions.ts +3 -0
- package/src/renderer/src-web/tauri.ts +129 -354
- package/src/renderer/tests/backgroundTerminals.browser.html +81 -0
- package/src/renderer/tests/chatPanelFixture.ts +23 -0
- package/src/renderer/tests/chatPerformance.browser.html +71 -0
- package/src/renderer/tests/cliSessions.browser.html +82 -0
- package/src/renderer/tests/collapsedPaste.browser.html +70 -0
- package/src/renderer/tests/composerMenus.browser.html +116 -0
- package/src/renderer/tests/contextCompaction.browser.html +17 -0
- package/src/renderer/tests/conversationLifecycle.browser.html +70 -0
- package/src/renderer/tests/effectsPerformance.browser.html +13 -0
- package/src/renderer/tests/errorRecovery.browser.html +21 -0
- package/src/renderer/tests/glideSelect.browser.html +71 -0
- package/src/renderer/tests/glideSelect.preview.html +27 -0
- package/src/renderer/tests/library.browser.html +1 -0
- package/src/renderer/tests/library.browser.tsx +78 -0
- package/src/renderer/tests/liveOrb.browser.html +49 -0
- package/src/renderer/tests/liveVoice.browser.html +29 -0
- package/src/renderer/tests/modInput.browser.html +22 -0
- package/src/renderer/tests/sessionSources.browser.html +1 -0
- package/src/renderer/tests/sessionSources.browser.tsx +107 -0
- package/src/renderer/tests/skills.browser.html +24 -0
- package/src/renderer/tests/toolsPanel.browser.html +1 -0
- package/src/renderer/tests/toolsPanel.browser.tsx +113 -0
- package/src/renderer/tests/viewedImages.browser.html +1 -0
- package/src/renderer/tests/viewedImages.browser.tsx +93 -0
- package/src/renderer/tests/voicePill.browser.html +80 -0
- package/src/renderer/tests/voicePill.preview.html +34 -0
- package/src/renderer/tests/webSources.browser.html +1 -0
- package/src/renderer/tests/webSources.browser.tsx +98 -0
- package/src/renderer/tests/workspaceUndo.browser.html +92 -0
- package/src-tauri/Cargo.toml +40 -0
- package/src-tauri/build.rs +3 -0
- package/src-tauri/src/app/lifecycle.rs +277 -0
- package/src-tauri/src/app/mod.rs +4 -0
- package/src-tauri/src/app/shortcuts.rs +40 -0
- package/src-tauri/src/app/tray.rs +52 -0
- package/src-tauri/src/background/events.rs +70 -0
- package/src-tauri/src/background/headless.rs +230 -0
- package/src-tauri/src/background/mod.rs +4 -0
- package/src-tauri/src/background/proactive.rs +262 -0
- package/src-tauri/src/commands/approvals.rs +20 -0
- package/src-tauri/src/commands/auth.rs +127 -0
- package/src-tauri/src/commands/conversation.rs +642 -0
- package/src-tauri/src/commands/integrations.rs +157 -0
- package/src-tauri/src/commands/media.rs +179 -0
- package/src-tauri/src/commands/mod.rs +11 -0
- package/src-tauri/src/commands/mods.rs +6 -0
- package/src-tauri/src/commands/settings.rs +141 -0
- package/src-tauri/src/commands/voice.rs +153 -0
- package/src-tauri/src/commands/workspace.rs +501 -0
- package/src-tauri/src/lib.rs +10 -0
- package/src-tauri/src/main.rs +3 -0
- package/src-tauri/src/native/actions.rs +206 -0
- package/src-tauri/src/native/browser.rs +252 -0
- package/src-tauri/src/native/capture.rs +695 -0
- package/src-tauri/src/native/discord_rpc.rs +99 -0
- package/src-tauri/src/native/integrations.rs +126 -0
- package/src-tauri/src/native/mod.rs +12 -0
- package/src-tauri/src/native/notifications.rs +51 -0
- package/src-tauri/src/native/plugins.rs +14 -0
- package/src-tauri/src/native/system.rs +250 -0
- package/src-tauri/src/native/terminal.rs +201 -0
- package/src-tauri/src/native/updater.rs +148 -0
- package/src-tauri/src/native/windows.rs +143 -0
- package/tsconfig.json +2 -0
- package/vite.config.ts +4 -1
- package/vite.config.web.ts +4 -0
- package/.cargo/config.toml +0 -13
- package/.claude/settings.local.json +0 -182
- package/.codex +0 -0
- package/CLAUDE.md +0 -102
- package/ROADMAP.md +0 -30
- package/mint-presentation-demo.mp4 +0 -0
- package/out/web/Live2DCubismCore.js +0 -9
- package/out/web/assets/CliSessionsView-BxUVWEEL.js +0 -1
- package/out/web/assets/CliSessionsView-CBDTXuQv.css +0 -1
- package/out/web/assets/CodeReviewPage-DkMgfcos.css +0 -1
- package/out/web/assets/CodeReviewPage-jKlmLJwT.js +0 -3
- package/out/web/assets/CommandPalette-DnwPA5hy.js +0 -1
- package/out/web/assets/ImageStudioPanel-BR1XFwhR.js +0 -1
- package/out/web/assets/LinkedFoldersView-bi-CWQ-I.js +0 -1
- package/out/web/assets/McpRegistryPicker-D5tEFnyq.js +0 -1
- package/out/web/assets/McpServersView-BGG1dhFM.js +0 -1
- package/out/web/assets/MintDashboard-BIglDEWX.js +0 -20
- package/out/web/assets/MintDashboard-DSMywSgs.css +0 -1
- package/out/web/assets/ModelPanel-CbJ1PFoZ.js +0 -1
- package/out/web/assets/PicturesLibrary-CQP0fLP1.css +0 -1
- package/out/web/assets/PicturesLibrary-DoYN7T1p.js +0 -1
- package/out/web/assets/PluginsView-CU1HWXGk.js +0 -1
- package/out/web/assets/ScheduledTasksView-Bnl36y2N.js +0 -1
- package/out/web/assets/SettingsWindow-DhWLAn9T.css +0 -1
- package/out/web/assets/SettingsWindow-Dw8L01pw.js +0 -2
- package/out/web/assets/SkillsView-cnl8aY5p.js +0 -2
- package/out/web/assets/ToolSurfacePage-CgsQw6l5.css +0 -1
- package/out/web/assets/ToolSurfacePage-Cz2VJAPZ.js +0 -37
- package/out/web/assets/VeoStudioPanel-D4JnERWR.js +0 -4
- package/out/web/assets/chunk-CKBBP62Z-cIrXq6jN.js +0 -2
- package/out/web/assets/classDiagram-DTDB5LWJ-Dq0smRWk.js +0 -1
- package/out/web/assets/classDiagram-v2-JRS7N3AN-Dq0smRWk.js +0 -1
- package/out/web/assets/config-C-ZFtipU.css +0 -1
- package/out/web/assets/config-eEDngJXO.js +0 -1
- package/out/web/assets/core-hQ2VA9Ti.js +0 -1
- package/out/web/assets/dist-js-Bf2bhoku.js +0 -1
- package/out/web/assets/flowDiagram-A5DVABFB-BLg7nEcd.js +0 -1
- package/out/web/assets/index-Btsf4L8M.css +0 -1
- package/out/web/assets/index-D8D9MeRA.js +0 -11
- package/out/web/assets/lucide-react-Ip3L6Jtn.js +0 -1
- package/out/web/assets/markdown-BSeeUbJH.js +0 -38
- package/out/web/assets/modelManager-tMVmJVAW.js +0 -2
- package/out/web/assets/prompt-latin-400-normal-BQ9zjSN8.woff2 +0 -0
- package/out/web/assets/prompt-latin-400-normal-CxU4ec_r.woff +0 -0
- package/out/web/assets/prompt-latin-500-normal-B1edBDQ9.woff +0 -0
- package/out/web/assets/prompt-latin-500-normal-CxzxEHZc.woff2 +0 -0
- package/out/web/assets/prompt-latin-600-normal-CSDDLorv.woff +0 -0
- package/out/web/assets/prompt-latin-600-normal-hKZWXsc1.woff2 +0 -0
- package/out/web/assets/prompt-latin-700-normal-BfbftDSq.woff +0 -0
- package/out/web/assets/prompt-latin-700-normal-I2gc831J.woff2 +0 -0
- package/out/web/assets/prompt-thai-400-normal-BrkKv8cO.woff2 +0 -0
- package/out/web/assets/prompt-thai-400-normal-DJypnfr3.woff +0 -0
- package/out/web/assets/prompt-thai-500-normal-C18pDUoL.woff2 +0 -0
- package/out/web/assets/prompt-thai-500-normal-D7YNqUJD.woff +0 -0
- package/out/web/assets/prompt-thai-600-normal-CYPViXds.woff +0 -0
- package/out/web/assets/prompt-thai-600-normal-MrdfU7zR.woff2 +0 -0
- package/out/web/assets/prompt-thai-700-normal-Cb5ilR-c.woff +0 -0
- package/out/web/assets/prompt-thai-700-normal-Cg4aQ0Nn.woff2 +0 -0
- package/out/web/assets/stateDiagram-v2-4QOOHH4V-DeEc0lGZ.js +0 -1
- package/out/web/assets/swimlanesDiagram-VK2B7HYN-DpVik9v7.js +0 -8
- package/out/web/assets/window-5qYXKoW7.js +0 -1
- package/skills-lock.json +0 -77
- package/src/renderer/public/Live2DCubismCore.js +0 -9
- package/src/renderer/src/companionWidget.ts +0 -95
- package/src/renderer/src/components/Live2DStage.tsx +0 -412
- package/src/renderer/src/components/ModelPanel.tsx +0 -155
- package/src/renderer/src/css/model.css +0 -628
- package/src/renderer/src-web/companionWidget.ts +0 -37
- package/src/renderer/src-web/components/ModelPanel.tsx +0 -12
- package/src/renderer/src-web/css/model.css +0 -628
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createWorkspacePreview } from '../utils/workspacePreview'
|
|
2
|
+
import { shouldNotify } from '../utils/notificationSettings'
|
|
3
|
+
import { deliverNotification, receiveProactiveNotification } from '../utils/notifications'
|
|
4
|
+
import '../css/notification-notice.css'
|
|
5
|
+
import { lazy, Suspense, type ChangeEvent, type CSSProperties, type FormEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
2
6
|
import {
|
|
3
|
-
compactAgentProgressForPersistence,
|
|
4
|
-
mergeActivitySnapshots,
|
|
5
7
|
mergeFileChanges,
|
|
6
8
|
parseFileChangesFromProgress,
|
|
7
9
|
} from '../agentProgress'
|
|
8
|
-
import { catalogPlatform, conversationPlatform, mediaPlatform, runtimePlatform, type SlashResponse } from '../platform'
|
|
9
|
-
import type {
|
|
10
|
+
import { catalogPlatform, conversationPlatform, mediaPlatform, runtimePlatform, workspacePlatform, type SlashResponse } from '../platform'
|
|
11
|
+
import type { ChatSession, DocumentAttachment, RuntimeStatus } from '../types'
|
|
10
12
|
|
|
11
13
|
const {
|
|
12
14
|
clearChatHistory, deleteChatSession, renameChatSession,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
cancelChatMessage, submitToolApproval, listen, readClipboardImage,
|
|
15
|
+
saveSystemInteraction, updateChatSessionWorkspace,
|
|
16
|
+
listen, readClipboardImage,
|
|
16
17
|
} = conversationPlatform
|
|
17
18
|
const { getRuntimeStatus, setActiveModel, selectWorkspaceDirectory, selectLinkedFolderPath, isTauriRuntime } = runtimePlatform
|
|
18
|
-
const {
|
|
19
|
+
const { convertFileSrc } = mediaPlatform
|
|
19
20
|
const {
|
|
20
21
|
listLearnedSkills, addLearnedSkill, deleteLearnedSkill, detectSystemTools, reauthMcpServer,
|
|
21
22
|
listMcpServerTools, setProfileValue, listCronJobs, addCronJob, removeCronJob,
|
|
@@ -27,7 +28,7 @@ import ChatPanel, { type ConversationActions, type ConversationViewModel } from
|
|
|
27
28
|
import ScreenCaptureDialog from './ScreenCaptureDialog'
|
|
28
29
|
import DashboardSidebar, { type DashboardView } from './DashboardSidebar'
|
|
29
30
|
import DesktopTitlebar from './DesktopTitlebar'
|
|
30
|
-
import
|
|
31
|
+
import ErrorNotice from './ErrorNotice'
|
|
31
32
|
import type { ToolSurface } from './ToolSurfacePage'
|
|
32
33
|
import {
|
|
33
34
|
errorMessage,
|
|
@@ -38,29 +39,17 @@ import {
|
|
|
38
39
|
applyThemeStyles,
|
|
39
40
|
parseUtcDate,
|
|
40
41
|
} from '../utils/ui'
|
|
42
|
+
import { workspacePaths } from '../utils/workspaces'
|
|
41
43
|
import { executeSlashCommand } from '../utils/slashCommandProcessor'
|
|
42
44
|
import { captureScreenForChat } from '../utils/screenCapture'
|
|
43
45
|
import { useConversationCoordinator } from '../conversation/useConversationCoordinator'
|
|
44
|
-
import {
|
|
46
|
+
import { isPersistedConversation } from '../conversation/projectNavigation'
|
|
47
|
+
import type { PromptOptions } from '../conversation/lifecycle'
|
|
45
48
|
|
|
46
49
|
|
|
47
|
-
const EXPRESSIONS = [
|
|
48
|
-
"Default",
|
|
49
|
-
"Dumb Cat",
|
|
50
|
-
"Dumb Cat Eye Roll",
|
|
51
|
-
"Take Photo",
|
|
52
|
-
"Poke",
|
|
53
|
-
"Cat Filter",
|
|
54
|
-
]
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"Apron",
|
|
59
|
-
"Glasses",
|
|
60
|
-
"Hold Pen",
|
|
61
|
-
]
|
|
62
|
-
|
|
63
|
-
import { DEFAULT_CONFIG, migrateTypographyScale } from '../constants/config'
|
|
51
|
+
import { DEFAULT_CONFIG, migrateFontFamily, migrateTypographyScale } from '../constants/config'
|
|
52
|
+
import { BackgroundTerminals } from './BackgroundTerminals'
|
|
64
53
|
|
|
65
54
|
const LAST_WORKSPACE_PATH_KEY = 'mint:last-workspace-path'
|
|
66
55
|
const RECENT_WORKSPACE_PATHS_KEY = 'mint:recent-workspace-paths'
|
|
@@ -238,9 +227,8 @@ const MOCK_WELCOME_INTERACTION = {
|
|
|
238
227
|
|
|
239
228
|
|
|
240
229
|
import { isSupportedDocument } from '../utils/documentTypes'
|
|
241
|
-
import {
|
|
230
|
+
import { useProactiveSuggestions } from '@/proactiveSuggestions'
|
|
242
231
|
|
|
243
|
-
const ModelPanel = lazy(() => import('@/components/ModelPanel'))
|
|
244
232
|
const WorkspacePanel = lazy(() => import('@/components/WorkspacePanel'))
|
|
245
233
|
const ToolSurfacePage = lazy(() => import('./ToolSurfacePage'))
|
|
246
234
|
const SkillsView = lazy(() => import('./SkillsView'))
|
|
@@ -249,7 +237,7 @@ const LinkedFoldersView = lazy(() => import('./LinkedFoldersView'))
|
|
|
249
237
|
const McpServersView = lazy(() => import('./McpServersView'))
|
|
250
238
|
const PluginsView = lazy(() => import('./PluginsView'))
|
|
251
239
|
const CliSessionsView = lazy(() => import('./CliSessionsView'))
|
|
252
|
-
const
|
|
240
|
+
const LibraryPage = lazy(() => import('./LibraryPage'))
|
|
253
241
|
const ImageStudioPanel = lazy(() => import('./ImageStudioPanel'))
|
|
254
242
|
const VeoStudioPanel = lazy(() => import('./VeoStudioPanel'))
|
|
255
243
|
const CommandPalette = lazy(() => import('./CommandPalette').then(({ CommandPalette: Component }) => ({ default: Component })))
|
|
@@ -267,7 +255,7 @@ function getInitialViewFromUrl(): DashboardView {
|
|
|
267
255
|
if (target.includes('skills')) return 'skills'
|
|
268
256
|
if (target.includes('mcp')) return 'mcp'
|
|
269
257
|
if (target.includes('plugins')) return 'plugins'
|
|
270
|
-
if (target.includes('picture')) return 'pictures'
|
|
258
|
+
if (target.includes('picture') || target.includes('library')) return 'pictures'
|
|
271
259
|
if (target.includes('image-studio') || target.includes('imagine')) return 'imagine'
|
|
272
260
|
if (target.includes('veo-studio') || target.includes('veo')) return 'veo'
|
|
273
261
|
if (target.includes('code') || target === '/cli' || target === 'cli' || target.includes('cli-sessions')) return 'code'
|
|
@@ -278,7 +266,7 @@ function getCleanPathForView(v: string, activeId?: string): string {
|
|
|
278
266
|
if (v === 'skills') return '/skills'
|
|
279
267
|
if (v === 'mcp') return '/mcp'
|
|
280
268
|
if (v === 'plugins') return '/plugins'
|
|
281
|
-
if (v === 'pictures') return '/
|
|
269
|
+
if (v === 'pictures') return '/library'
|
|
282
270
|
if (v === 'imagine') return '/image-studio'
|
|
283
271
|
if (v === 'veo' || v === 'veo_studio') return '/veo-studio'
|
|
284
272
|
if (v === 'code') return '/code'
|
|
@@ -317,87 +305,56 @@ function describeApproval(payload: any): string {
|
|
|
317
305
|
}
|
|
318
306
|
}
|
|
319
307
|
|
|
320
|
-
/** Fires the same notification mechanism as a finished AI reply, but only
|
|
321
|
-
* while the window is unfocused — reused so both surfaces get identical
|
|
322
|
-
* title/permission/dedupe behavior, just a different body string. */
|
|
323
|
-
function notifyPendingApproval(payload: any) {
|
|
324
|
-
if (document.hidden || !document.hasFocus()) {
|
|
325
|
-
window.api?.notifyAiResponse?.(truncateForNotification(describeApproval(payload)))
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
308
|
export default function MintDashboard() {
|
|
330
309
|
const isDesktopApp = isTauriRuntime()
|
|
331
310
|
const [view, setViewState] = useState<DashboardView>(getInitialViewFromUrl)
|
|
332
|
-
const [
|
|
311
|
+
const [initialConversationId] = useState(activeConversationId)
|
|
333
312
|
// Declared here (not further down with the rest of the workspace-related
|
|
334
313
|
// state) so the URL-change effect below can read it.
|
|
335
314
|
const { conversation, actions: conversationActions } = useConversationCoordinator(
|
|
336
315
|
{
|
|
337
316
|
workspacePath: window.localStorage.getItem(LAST_WORKSPACE_PATH_KEY) || '',
|
|
338
|
-
message: readDraft(
|
|
317
|
+
message: readDraft(initialConversationId),
|
|
339
318
|
},
|
|
340
319
|
{
|
|
341
|
-
conversationId,
|
|
320
|
+
conversationId: initialConversationId,
|
|
342
321
|
draftKeyPrefix: DRAFT_KEY_PREFIX,
|
|
343
322
|
workspaceStorageKey: LAST_WORKSPACE_PATH_KEY,
|
|
323
|
+
historyVisible: view === 'chat',
|
|
324
|
+
onError: reason => setError(errorMessage(reason)),
|
|
325
|
+
onApproval: (payload, chatId) => notifyPendingApproval(payload, chatId),
|
|
326
|
+
onReply: (response, chatId) => {
|
|
327
|
+
if (document.hidden || !document.hasFocus()) return sendNotification(response.text || 'Mint finished your request.', chatId)
|
|
328
|
+
},
|
|
329
|
+
onActivityPersisted: id => {
|
|
330
|
+
const key = String(id)
|
|
331
|
+
setThinkingExpanded(current => ({ ...current,
|
|
332
|
+
...(liveThinkingOpenRef.current ? { [key]: true } : {}),
|
|
333
|
+
...(liveExtendedThinkingOpenRef.current ? { [`extended-${key}`]: true } : {}),
|
|
334
|
+
}))
|
|
335
|
+
},
|
|
336
|
+
onRunCompleted: async () => {
|
|
337
|
+
getRuntimeStatus().then(setStatus).catch(() => {})
|
|
338
|
+
},
|
|
339
|
+
onVisibleRunCompleted: chatId => {
|
|
340
|
+
const pathname = (window.location.pathname || '').replace(/\/+$/, '')
|
|
341
|
+
const hash = (window.location.hash || '').replace(/^#\/?/, '').replace(/\/+$/, '')
|
|
342
|
+
const target = (pathname || hash).toLowerCase()
|
|
343
|
+
if (!target || target === '/chat' || target === 'chat' || target === '/index.html' || target === 'index.html') {
|
|
344
|
+
window.history.replaceState({}, '', `/chat/${encodeURIComponent(chatId)}`)
|
|
345
|
+
}
|
|
346
|
+
},
|
|
344
347
|
},
|
|
345
348
|
)
|
|
346
349
|
const {
|
|
347
|
-
workspacePath, message, imageAttachments, videoAttachments, documentAttachment,
|
|
350
|
+
conversationId, workspacePath, message, imageAttachments, videoAttachments, documentAttachment,
|
|
348
351
|
sending, sendingMessage, sendingImageCount, sendingVideoCount, streamedReply,
|
|
349
|
-
streamedResponse, agentProgress,
|
|
352
|
+
streamedResponse, agentProgress, interactions, hasOlderInteractions,
|
|
353
|
+
streamingConversationId, activeTurnId, agentActivitySnapshots, pendingApprovals,
|
|
354
|
+
sessionAutoApproved, chatSessions,
|
|
350
355
|
} = conversation
|
|
351
|
-
const activeConversationRef = useRef(conversationId)
|
|
352
|
-
const sessionGenerationRef = useRef(0)
|
|
353
|
-
const runGenerationRef = useRef(0)
|
|
354
|
-
const conversationCursorRef = useRef<{ chatId: string; cursor: number } | null>(null)
|
|
355
|
-
const historyLoadSerialRef = useRef(0)
|
|
356
|
-
const [pendingApprovals, setPendingApprovals] = useState<Record<string, { token: string; approval: any }>>({})
|
|
357
|
-
const autoApprovedChatIdRef = useRef<string | null>(null)
|
|
358
|
-
const isCurrentSession = (chatId: string, generation: number) => matchesActiveSession(
|
|
359
|
-
{ chatId, generation },
|
|
360
|
-
{ chatId: activeConversationRef.current, generation: sessionGenerationRef.current },
|
|
361
|
-
)
|
|
362
356
|
const activateConversation = (id: string) => {
|
|
363
|
-
|
|
364
|
-
activeConversationRef.current = id
|
|
365
|
-
sessionGenerationRef.current += 1
|
|
366
|
-
runGenerationRef.current += 1
|
|
367
|
-
conversationCursorRef.current = null
|
|
368
|
-
setInteractions([])
|
|
369
|
-
setHasOlderInteractions(false)
|
|
370
|
-
setAgentActivitySnapshots({})
|
|
371
|
-
setStreamingConversationId(null)
|
|
372
|
-
setActiveTurnId(null)
|
|
373
|
-
}
|
|
374
|
-
setConversationId(id)
|
|
375
|
-
}
|
|
376
|
-
async function loadConversationHistory(chatId: string, generation: number) {
|
|
377
|
-
const serial = ++historyLoadSerialRef.current
|
|
378
|
-
const snapshot = await getConversationSnapshot(chatId, null, 50)
|
|
379
|
-
if (!isCurrentSession(chatId, generation) || serial !== historyLoadSerialRef.current) return
|
|
380
|
-
const currentCursor = conversationCursorRef.current
|
|
381
|
-
if (currentCursor?.chatId === chatId && currentCursor.cursor > snapshot.cursor) return
|
|
382
|
-
conversationCursorRef.current = { chatId, cursor: snapshot.cursor }
|
|
383
|
-
setInteractions((current) => {
|
|
384
|
-
if (!isCurrentSession(chatId, generation) || serial !== historyLoadSerialRef.current) return current
|
|
385
|
-
if (conversationCursorRef.current?.chatId === chatId
|
|
386
|
-
&& conversationCursorRef.current.cursor > snapshot.cursor) return current
|
|
387
|
-
return snapshot.interactions
|
|
388
|
-
})
|
|
389
|
-
setHasOlderInteractions((current) => {
|
|
390
|
-
if (!isCurrentSession(chatId, generation) || serial !== historyLoadSerialRef.current) return current
|
|
391
|
-
if (conversationCursorRef.current?.chatId === chatId
|
|
392
|
-
&& conversationCursorRef.current.cursor > snapshot.cursor) return current
|
|
393
|
-
return snapshot.hasOlder
|
|
394
|
-
})
|
|
395
|
-
setAgentActivitySnapshots((current) => {
|
|
396
|
-
if (!isCurrentSession(chatId, generation) || serial !== historyLoadSerialRef.current) return current
|
|
397
|
-
if (conversationCursorRef.current?.chatId === chatId
|
|
398
|
-
&& conversationCursorRef.current.cursor > snapshot.cursor) return current
|
|
399
|
-
return mergeActivitySnapshots(current, snapshot.interactions)
|
|
400
|
-
})
|
|
357
|
+
conversationActions.activate(id)
|
|
401
358
|
}
|
|
402
359
|
// Web only in practice (desktop's window has no mobile-width breakpoint,
|
|
403
360
|
// so nothing ever sets this true there) — declared unconditionally so
|
|
@@ -416,19 +373,26 @@ export default function MintDashboard() {
|
|
|
416
373
|
const [workspaceRefreshRevision, setWorkspaceRefreshRevision] = useState(0)
|
|
417
374
|
const [recentWorkspacePaths, setRecentWorkspacePaths] = useState<string[]>(readRecentWorkspacePaths)
|
|
418
375
|
|
|
419
|
-
|
|
420
|
-
const
|
|
421
|
-
if (!currentPath) return
|
|
422
|
-
const recent = [currentPath, ...readRecentWorkspacePaths().filter((path) => path !== currentPath)]
|
|
423
|
-
.slice(0, MAX_RECENT_WORKSPACES)
|
|
376
|
+
function rememberWorkspace(path: string) {
|
|
377
|
+
const recent = workspacePaths([path, ...readRecentWorkspacePaths()]).slice(0, MAX_RECENT_WORKSPACES)
|
|
424
378
|
try {
|
|
425
379
|
window.localStorage.setItem(RECENT_WORKSPACE_PATHS_KEY, JSON.stringify(recent))
|
|
426
380
|
} catch {
|
|
427
381
|
/* Keep the in-memory recent list usable when storage is unavailable. */
|
|
428
382
|
}
|
|
429
383
|
setRecentWorkspacePaths(recent)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
useEffect(() => {
|
|
387
|
+
if (workspacePath.trim()) rememberWorkspace(workspacePath)
|
|
430
388
|
}, [workspacePath])
|
|
431
389
|
|
|
390
|
+
async function selectCodeHubFolder() {
|
|
391
|
+
const selected = await selectLinkedFolderPath()
|
|
392
|
+
if (selected) rememberWorkspace(selected)
|
|
393
|
+
return selected
|
|
394
|
+
}
|
|
395
|
+
|
|
432
396
|
const changeView = (newView: any, targetConversationId?: string) => {
|
|
433
397
|
setMobileSidebarOpen(false)
|
|
434
398
|
setViewState((prev) => {
|
|
@@ -443,7 +407,10 @@ export default function MintDashboard() {
|
|
|
443
407
|
}
|
|
444
408
|
return prev
|
|
445
409
|
}
|
|
446
|
-
const
|
|
410
|
+
const requestedView: DashboardView = (next === 'veo_studio' ? 'veo' : next) as DashboardView
|
|
411
|
+
// The Web app can select a project for chat context, but its local file
|
|
412
|
+
// browser is Desktop-only. Keep any Workspace navigation on Web in chat.
|
|
413
|
+
const mappedView: DashboardView = !isDesktopApp && requestedView === 'workspace' ? 'chat' : requestedView
|
|
447
414
|
const targetPath = getCleanPathForView(mappedView, targetConversationId || conversationId)
|
|
448
415
|
if (typeof window !== 'undefined' && window.location.pathname !== targetPath) {
|
|
449
416
|
window.history.pushState({}, '', targetPath)
|
|
@@ -467,16 +434,12 @@ export default function MintDashboard() {
|
|
|
467
434
|
if (urlSessionId && urlSessionId !== conversationId) {
|
|
468
435
|
window.localStorage.setItem(ACTIVE_CONVERSATION_ID_KEY, urlSessionId)
|
|
469
436
|
activateConversation(urlSessionId)
|
|
470
|
-
|
|
471
|
-
loadConversationHistory(urlSessionId, generation).catch((error) => {
|
|
437
|
+
conversationActions.refreshHistory().catch((error) => {
|
|
472
438
|
console.error('Failed to load conversation history:', error)
|
|
473
439
|
})
|
|
474
440
|
} else if (!urlSessionId && isRootOrNewChatRoute()) {
|
|
475
441
|
const next = createConversationId()
|
|
476
442
|
activateConversation(next)
|
|
477
|
-
setInteractions([])
|
|
478
|
-
setAgentActivitySnapshots({})
|
|
479
|
-
conversationActions.switchSession()
|
|
480
443
|
}
|
|
481
444
|
}
|
|
482
445
|
window.addEventListener('popstate', handleUrlChange)
|
|
@@ -501,24 +464,62 @@ export default function MintDashboard() {
|
|
|
501
464
|
}, [])
|
|
502
465
|
const [status, setStatus] = useState<RuntimeStatus | null>(null)
|
|
503
466
|
const [error, setError] = useState('')
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
const
|
|
467
|
+
const [notificationNotice, setNotificationNotice] = useState<{ message: string; chatId?: string; type?: string } | null>(null)
|
|
468
|
+
const notificationNavigationRef = useRef(selectConversation)
|
|
469
|
+
notificationNavigationRef.current = selectConversation
|
|
470
|
+
const sendNotification = (body: string, chatId?: string, kind: 'replies' | 'approvals' | 'system' = 'replies') => deliverNotification(
|
|
471
|
+
() => shouldNotify(notificationConfigRef.current?.notificationSettings, kind, 'os')
|
|
472
|
+
? window.api?.notifyAiResponse?.(truncateForNotification(body), chatId) : undefined,
|
|
473
|
+
setError,
|
|
474
|
+
)
|
|
475
|
+
const notifyPendingApproval = (payload: any, chatId?: string) => {
|
|
476
|
+
if (document.hidden || !document.hasFocus()) {
|
|
477
|
+
void sendNotification(describeApproval(payload), chatId ?? payload.chatId, 'approvals')
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
useEffect(() => {
|
|
481
|
+
let disposed = false
|
|
482
|
+
const cleanups: Array<() => void> = []
|
|
483
|
+
const register = (subscription: Promise<any> | undefined) => {
|
|
484
|
+
subscription?.then(unlisten => {
|
|
485
|
+
if (typeof unlisten !== 'function') return
|
|
486
|
+
if (disposed) unlisten()
|
|
487
|
+
else cleanups.push(unlisten)
|
|
488
|
+
}).catch(reason => { if (!disposed) setError(errorMessage(reason)) })
|
|
489
|
+
}
|
|
490
|
+
const openChat = (chatId?: string) => {
|
|
491
|
+
if (chatId) void notificationNavigationRef.current(chatId).catch(reason => setError(errorMessage(reason)))
|
|
492
|
+
}
|
|
493
|
+
const clicked = (event: Event) => openChat((event as CustomEvent).detail?.chatId)
|
|
494
|
+
window.addEventListener('mint:notification-click', clicked)
|
|
495
|
+
register(listen('notification-clicked', (event: { payload: { chatId?: string } }) => openChat(event.payload?.chatId)))
|
|
496
|
+
register(Promise.resolve(window.api?.onProactiveNotification?.((payload: any) => {
|
|
497
|
+
if (disposed) return
|
|
498
|
+
void receiveProactiveNotification(payload, document.hidden || !document.hasFocus(),
|
|
499
|
+
notice => { if (shouldNotify(notificationConfigRef.current?.notificationSettings, 'system', 'inApp')) setNotificationNotice(notice) },
|
|
500
|
+
(body, chatId) => sendNotification(body, chatId, 'system'))
|
|
501
|
+
.catch(reason => setError(errorMessage(reason)))
|
|
502
|
+
})))
|
|
503
|
+
const visible = () => { if (!document.hidden) window.api?.clearAiNotifications?.() }
|
|
504
|
+
document.addEventListener('visibilitychange', visible)
|
|
505
|
+
return () => {
|
|
506
|
+
disposed = true
|
|
507
|
+
cleanups.forEach(unlisten => unlisten())
|
|
508
|
+
window.removeEventListener('mint:notification-click', clicked)
|
|
509
|
+
document.removeEventListener('visibilitychange', visible)
|
|
510
|
+
}
|
|
511
|
+
}, [])
|
|
512
|
+
|
|
513
513
|
const [thinkingExpanded, setThinkingExpanded] = useState<Record<string, boolean>>({})
|
|
514
514
|
const liveThinkingOpenRef = useRef(true)
|
|
515
515
|
const liveExtendedThinkingOpenRef = useRef(true)
|
|
516
|
-
const [sessionAutoApproved, setSessionAutoApproved] = useState(false)
|
|
517
|
-
const sessionAutoApprovedRef = useRef(false)
|
|
518
516
|
const [sidebarCollapsed, setSidebarCollapsed] = useState(() => window.localStorage.getItem('mint:sidebar-collapsed') === 'true')
|
|
519
517
|
const [toolSurfaces, setToolSurfaces] = useState<ToolSurface[]>([])
|
|
520
518
|
const [activeSurfaceId, setActiveSurfaceId] = useState<string | null>(null)
|
|
521
519
|
const [toolsPanelOpen, setToolsPanelOpen] = useState(false)
|
|
520
|
+
const [modsPanelTarget, setModsPanelTarget] = useState<HTMLDivElement | null>(null)
|
|
521
|
+
const [backgroundPanelTarget, setBackgroundPanelTarget] = useState<HTMLDivElement | null>(null)
|
|
522
|
+
const [backgroundTaskCount, setBackgroundTaskCount] = useState(0)
|
|
522
523
|
const [terminalRightWidth, setTerminalRightWidth] = useState(() => {
|
|
523
524
|
const saved = Number(window.localStorage.getItem('mint:terminal-right-width'))
|
|
524
525
|
return saved >= 280 && saved <= 900 ? saved : 440
|
|
@@ -536,11 +537,6 @@ export default function MintDashboard() {
|
|
|
536
537
|
}),
|
|
537
538
|
parseFileChangesFromProgress(agentProgress),
|
|
538
539
|
])
|
|
539
|
-
const workspaceSourceNames = [
|
|
540
|
-
...imageAttachments.map((attachment) => attachment.name),
|
|
541
|
-
...videoAttachments.map((attachment) => attachment.name),
|
|
542
|
-
documentAttachment?.filename || '',
|
|
543
|
-
]
|
|
544
540
|
|
|
545
541
|
const [agentMode, setAgentMode] = useState(() => window.localStorage.getItem('mint:agent-mode') === 'true')
|
|
546
542
|
const [planMode, setPlanMode] = useState(() => window.localStorage.getItem('mint:plan-mode') === 'true')
|
|
@@ -548,33 +544,19 @@ export default function MintDashboard() {
|
|
|
548
544
|
const [dashboardDataReady, setDashboardDataReady] = useState(false)
|
|
549
545
|
const [startupTimedOut, setStartupTimedOut] = useState(false)
|
|
550
546
|
const [settingsConfig, setSettingsConfig] = useState<any>(null)
|
|
551
|
-
const
|
|
547
|
+
const notificationConfigRef = useRef(settingsConfig)
|
|
548
|
+
notificationConfigRef.current = settingsConfig
|
|
549
|
+
useEffect(() => {
|
|
550
|
+
if (!shouldNotify(settingsConfig?.notificationSettings, 'system', 'inApp')) setNotificationNotice(null)
|
|
551
|
+
if (settingsConfig?.notificationSettings?.enabled === false || settingsConfig?.notificationSettings?.os === false) window.api?.clearAiNotifications?.()
|
|
552
|
+
}, [settingsConfig])
|
|
553
|
+
const availableWorkspacePaths = useMemo(() => workspacePaths(
|
|
554
|
+
recentWorkspacePaths, workspacePath, chatSessions.map(session => session.workspacePath),
|
|
555
|
+
), [recentWorkspacePaths, workspacePath, chatSessions])
|
|
552
556
|
const chatEnd = useRef<HTMLDivElement | null>(null)
|
|
553
557
|
const lastNativePasteTimeRef = useRef(0)
|
|
554
|
-
const {
|
|
555
|
-
|
|
556
|
-
scale,
|
|
557
|
-
interactionEnabled,
|
|
558
|
-
showInteractionGuide,
|
|
559
|
-
isLocked,
|
|
560
|
-
layoutPreset,
|
|
561
|
-
expressionIndex,
|
|
562
|
-
accessoryIndex,
|
|
563
|
-
modelReady,
|
|
564
|
-
proactiveSuggestion,
|
|
565
|
-
setScale,
|
|
566
|
-
setIsLocked,
|
|
567
|
-
setExpressionIndex,
|
|
568
|
-
setAccessoryIndex,
|
|
569
|
-
setModelReady,
|
|
570
|
-
toggleModel,
|
|
571
|
-
changeLayoutPreset,
|
|
572
|
-
updateInteractionEnabled,
|
|
573
|
-
updateInteractionGuide,
|
|
574
|
-
dismissProactiveSuggestion,
|
|
575
|
-
handleProactiveAction,
|
|
576
|
-
} = useCompanionWidget((message) => setError(message))
|
|
577
|
-
const startupReady = (dashboardDataReady && modelReady) || startupTimedOut
|
|
558
|
+
const { proactiveSuggestion, dismissProactiveSuggestion, handleProactiveAction } = useProactiveSuggestions((message) => setError(message))
|
|
559
|
+
const startupReady = dashboardDataReady || startupTimedOut
|
|
578
560
|
|
|
579
561
|
const [mcpName, setMcpName] = useState('')
|
|
580
562
|
const [mcpCmd, setMcpCmd] = useState('')
|
|
@@ -685,118 +667,6 @@ export default function MintDashboard() {
|
|
|
685
667
|
}
|
|
686
668
|
}, [isSearchOpen])
|
|
687
669
|
|
|
688
|
-
// Another process — the CLI's interactive chat, a scheduled task, a
|
|
689
|
-
// messaging bridge — can add messages to this same conversation while
|
|
690
|
-
// this page is open, and nothing here would otherwise notice: Mint's
|
|
691
|
-
// surfaces only share a SQLite file, not a live event bus, so this polls
|
|
692
|
-
// for changes instead of requiring a manual refresh. Kept in a ref rather
|
|
693
|
-
// than the effect's own dependency array so a poll landing doesn't tear
|
|
694
|
-
// down and recreate the interval on every tick.
|
|
695
|
-
const interactionsRef = useRef(interactions)
|
|
696
|
-
const chatPollInFlightRef = useRef<{ chatId: string; generation: number } | null>(null)
|
|
697
|
-
useEffect(() => {
|
|
698
|
-
interactionsRef.current = interactions
|
|
699
|
-
}, [interactions])
|
|
700
|
-
useEffect(() => {
|
|
701
|
-
if (interactions.length === 0) setHasOlderInteractions(false)
|
|
702
|
-
}, [interactions.length])
|
|
703
|
-
|
|
704
|
-
// Load the saved draft whenever the active conversation changes. Declared
|
|
705
|
-
// before the persist effect so it runs first within the same commit. The
|
|
706
|
-
// first run is a no-op: `message`'s initial value already came from the
|
|
707
|
-
// lazy `useState` initializer above.
|
|
708
|
-
useEffect(() => {
|
|
709
|
-
if (view !== 'chat' || !conversationId) return
|
|
710
|
-
let disposed = false
|
|
711
|
-
const generation = sessionGenerationRef.current
|
|
712
|
-
const isCurrent = () => !disposed && isCurrentSession(conversationId, generation)
|
|
713
|
-
const syncHistory = async () => {
|
|
714
|
-
// A shared SQLite database has no cross-process event bus. Refresh as
|
|
715
|
-
// soon as the user returns, but avoid work while hidden or overlapping
|
|
716
|
-
// a slow read with the next polling tick.
|
|
717
|
-
if (
|
|
718
|
-
!isCurrent() ||
|
|
719
|
-
document.visibilityState !== 'visible' ||
|
|
720
|
-
(chatPollInFlightRef.current?.chatId === conversationId
|
|
721
|
-
&& chatPollInFlightRef.current.generation === generation)
|
|
722
|
-
) return
|
|
723
|
-
|
|
724
|
-
const poll = { chatId: conversationId, generation }
|
|
725
|
-
chatPollInFlightRef.current = poll
|
|
726
|
-
try {
|
|
727
|
-
if (conversationCursorRef.current?.chatId !== conversationId) {
|
|
728
|
-
await loadConversationHistory(conversationId, generation)
|
|
729
|
-
return
|
|
730
|
-
}
|
|
731
|
-
let cursor = conversationCursorRef.current.cursor
|
|
732
|
-
let changed = false
|
|
733
|
-
for (let page = 0; page < 10; page++) {
|
|
734
|
-
const batch = await getConversationChanges(conversationId, cursor, 100)
|
|
735
|
-
if (!isCurrent()) return
|
|
736
|
-
if (conversationCursorRef.current?.chatId === conversationId
|
|
737
|
-
&& conversationCursorRef.current.cursor > batch.cursor) return
|
|
738
|
-
cursor = batch.cursor
|
|
739
|
-
if (batch.changes.length > 0) {
|
|
740
|
-
changed = true
|
|
741
|
-
setInteractions((current) => {
|
|
742
|
-
if (!isCurrent()) return current
|
|
743
|
-
if (conversationCursorRef.current?.chatId === conversationId
|
|
744
|
-
&& conversationCursorRef.current.cursor > batch.cursor) return current
|
|
745
|
-
const byId = new Map(current.map((interaction) => [interaction.id, interaction]))
|
|
746
|
-
for (const change of batch.changes) {
|
|
747
|
-
if (change.interaction) byId.set(change.interactionId, change.interaction)
|
|
748
|
-
else byId.delete(change.interactionId)
|
|
749
|
-
}
|
|
750
|
-
return Array.from(byId.values()).sort((a, b) => a.id - b.id)
|
|
751
|
-
})
|
|
752
|
-
setAgentActivitySnapshots((current) => {
|
|
753
|
-
if (!isCurrent()) return current
|
|
754
|
-
if (conversationCursorRef.current?.chatId === conversationId
|
|
755
|
-
&& conversationCursorRef.current.cursor > batch.cursor) return current
|
|
756
|
-
const merged = { ...current }
|
|
757
|
-
for (const change of batch.changes) {
|
|
758
|
-
const key = String(change.interactionId)
|
|
759
|
-
if (change.interaction) {
|
|
760
|
-
if (change.interaction.agentActivity && Array.isArray(change.interaction.agentActivity)) {
|
|
761
|
-
merged[key] = change.interaction.agentActivity
|
|
762
|
-
}
|
|
763
|
-
} else {
|
|
764
|
-
delete merged[key]
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
return merged
|
|
768
|
-
})
|
|
769
|
-
}
|
|
770
|
-
if (!batch.hasMore) break
|
|
771
|
-
}
|
|
772
|
-
if (conversationCursorRef.current?.chatId === conversationId
|
|
773
|
-
&& conversationCursorRef.current.cursor > cursor) return
|
|
774
|
-
conversationCursorRef.current = { chatId: conversationId, cursor }
|
|
775
|
-
if (changed) {
|
|
776
|
-
const sessions = await listChatSessions()
|
|
777
|
-
if (isCurrent()) setChatSessions(sessions)
|
|
778
|
-
}
|
|
779
|
-
} catch {
|
|
780
|
-
// Best-effort — a transient fetch failure just waits for the next tick.
|
|
781
|
-
} finally {
|
|
782
|
-
if (chatPollInFlightRef.current === poll) chatPollInFlightRef.current = null
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
const syncWhenActive = () => { void syncHistory() }
|
|
787
|
-
syncWhenActive()
|
|
788
|
-
window.addEventListener('focus', syncWhenActive)
|
|
789
|
-
document.addEventListener('visibilitychange', syncWhenActive)
|
|
790
|
-
const interval = window.setInterval(syncWhenActive, 1500)
|
|
791
|
-
|
|
792
|
-
return () => {
|
|
793
|
-
disposed = true
|
|
794
|
-
window.clearInterval(interval)
|
|
795
|
-
window.removeEventListener('focus', syncWhenActive)
|
|
796
|
-
document.removeEventListener('visibilitychange', syncWhenActive)
|
|
797
|
-
}
|
|
798
|
-
}, [view, conversationId, workspacePath])
|
|
799
|
-
|
|
800
670
|
const filteredSessions = chatSessions.filter((session) => {
|
|
801
671
|
if (session.kind === 'cli' || session.id === 'conversation-default') return false
|
|
802
672
|
return session.title.toLowerCase().includes(searchQuery.toLowerCase())
|
|
@@ -848,71 +718,31 @@ export default function MintDashboard() {
|
|
|
848
718
|
const groupedSearchSessions = groupSessionsByDate(filteredSessions)
|
|
849
719
|
|
|
850
720
|
|
|
851
|
-
|
|
852
|
-
const chatId = conversationId
|
|
853
|
-
const generation = sessionGenerationRef.current
|
|
854
|
-
await loadConversationHistory(chatId, generation)
|
|
855
|
-
}
|
|
856
|
-
|
|
721
|
+
const refreshHistory = conversationActions.refreshHistory
|
|
857
722
|
const refreshChatSessions = useCallback(async () => {
|
|
858
|
-
try {
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
prev.length === sessions.length &&
|
|
863
|
-
prev.every(
|
|
864
|
-
(s, i) =>
|
|
865
|
-
s.id === sessions[i]?.id &&
|
|
866
|
-
s.updatedAt === sessions[i]?.updatedAt &&
|
|
867
|
-
s.title === sessions[i]?.title &&
|
|
868
|
-
s.messageCount === sessions[i]?.messageCount &&
|
|
869
|
-
s.totalBytes === sessions[i]?.totalBytes
|
|
870
|
-
)
|
|
871
|
-
) {
|
|
872
|
-
return prev
|
|
873
|
-
}
|
|
874
|
-
return sessions
|
|
875
|
-
})
|
|
876
|
-
} catch (e) {
|
|
877
|
-
console.error('Failed to refresh chat sessions:', e)
|
|
878
|
-
}
|
|
879
|
-
}, [])
|
|
880
|
-
|
|
881
|
-
useEffect(() => {
|
|
882
|
-
const refreshVisible = () => {
|
|
883
|
-
if (document.visibilityState === 'visible') void refreshChatSessions()
|
|
884
|
-
}
|
|
885
|
-
const interval = window.setInterval(refreshVisible, 5000)
|
|
886
|
-
window.addEventListener('focus', refreshVisible)
|
|
887
|
-
document.addEventListener('visibilitychange', refreshVisible)
|
|
888
|
-
return () => {
|
|
889
|
-
window.clearInterval(interval)
|
|
890
|
-
window.removeEventListener('focus', refreshVisible)
|
|
891
|
-
document.removeEventListener('visibilitychange', refreshVisible)
|
|
892
|
-
}
|
|
893
|
-
}, [refreshChatSessions])
|
|
894
|
-
|
|
895
|
-
const loadOlderInteractions = useCallback(async () => {
|
|
896
|
-
const generation = sessionGenerationRef.current
|
|
897
|
-
const firstId = interactionsRef.current[0]?.id
|
|
898
|
-
if (firstId == null) return
|
|
899
|
-
const page = await getConversationSnapshot(conversationId, firstId, 50)
|
|
900
|
-
if (!isCurrentSession(conversationId, generation)) return
|
|
901
|
-
setHasOlderInteractions(page.hasOlder)
|
|
902
|
-
if (page.interactions.length === 0) return
|
|
903
|
-
setInteractions((current) => {
|
|
904
|
-
if (!isCurrentSession(conversationId, generation)) return current
|
|
905
|
-
const byId = new Map([...page.interactions, ...current].map((interaction) => [interaction.id, interaction]))
|
|
906
|
-
return Array.from(byId.values()).sort((a, b) => a.id - b.id)
|
|
907
|
-
})
|
|
908
|
-
}, [conversationId])
|
|
723
|
+
try { await conversationActions.refreshSessions() }
|
|
724
|
+
catch (error) { console.error('Failed to refresh chat sessions:', error) }
|
|
725
|
+
}, [conversationActions])
|
|
726
|
+
const loadOlderInteractions = conversationActions.loadOlder
|
|
909
727
|
|
|
728
|
+
const workspaceUpdateQueues = useRef(new Map<string, Promise<void>>())
|
|
910
729
|
const handleUpdateSessionWorkspace = useCallback(async (sessionId: string, targetPath: string | null) => {
|
|
911
|
-
|
|
730
|
+
// Preserve selection order if the user switches folders quickly.
|
|
731
|
+
const previous = workspaceUpdateQueues.current.get(sessionId) ?? Promise.resolve()
|
|
732
|
+
const update = previous.catch(() => {}).then(async () => {
|
|
912
733
|
await updateChatSessionWorkspace(sessionId, targetPath)
|
|
913
734
|
await refreshChatSessions()
|
|
735
|
+
})
|
|
736
|
+
workspaceUpdateQueues.current.set(sessionId, update)
|
|
737
|
+
try {
|
|
738
|
+
await update
|
|
914
739
|
} catch (e) {
|
|
915
740
|
console.error('Failed to update session workspace:', e)
|
|
741
|
+
setError(errorMessage(e))
|
|
742
|
+
} finally {
|
|
743
|
+
if (workspaceUpdateQueues.current.get(sessionId) === update) {
|
|
744
|
+
workspaceUpdateQueues.current.delete(sessionId)
|
|
745
|
+
}
|
|
916
746
|
}
|
|
917
747
|
}, [refreshChatSessions])
|
|
918
748
|
|
|
@@ -925,17 +755,6 @@ export default function MintDashboard() {
|
|
|
925
755
|
}
|
|
926
756
|
}, [])
|
|
927
757
|
|
|
928
|
-
const [picturesRefreshing, setPicturesRefreshing] = useState(false)
|
|
929
|
-
|
|
930
|
-
async function refreshPictures() {
|
|
931
|
-
setPicturesRefreshing(true)
|
|
932
|
-
try {
|
|
933
|
-
setPictures(await listSavedPictures())
|
|
934
|
-
} finally {
|
|
935
|
-
setPicturesRefreshing(false)
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
|
|
939
758
|
useEffect(() => {
|
|
940
759
|
Promise.allSettled([
|
|
941
760
|
getRuntimeStatus().then(setStatus),
|
|
@@ -943,7 +762,7 @@ export default function MintDashboard() {
|
|
|
943
762
|
refreshChatSessions(),
|
|
944
763
|
window.settingsApi?.getSettings()
|
|
945
764
|
.then((loaded: any) => {
|
|
946
|
-
const migrated = migrateTypographyScale(loaded)
|
|
765
|
+
const migrated = migrateFontFamily(migrateTypographyScale(loaded))
|
|
947
766
|
setSettingsConfig(migrated)
|
|
948
767
|
applyThemeStyles({ ...DEFAULT_CONFIG, ...migrated })
|
|
949
768
|
}),
|
|
@@ -956,18 +775,11 @@ export default function MintDashboard() {
|
|
|
956
775
|
changeView('chat')
|
|
957
776
|
conversationActions.compose(query)
|
|
958
777
|
})
|
|
959
|
-
const unlistenVision = window.api.onVisionReady((image) => {
|
|
960
|
-
createTrimmedImagePreview(image)
|
|
961
|
-
.catch(() => image)
|
|
962
|
-
.then((previewDataUri) => {
|
|
963
|
-
conversationActions.attachImage({ dataUri: image, previewDataUri, name: 'Screen capture' })
|
|
964
|
-
})
|
|
965
|
-
})
|
|
966
778
|
const handleWindowFocus = () => {
|
|
967
779
|
getRuntimeStatus().then(setStatus).catch(() => {})
|
|
968
780
|
window.settingsApi?.getSettings?.().then((loaded: any) => {
|
|
969
781
|
if (loaded) {
|
|
970
|
-
const migrated = migrateTypographyScale(loaded)
|
|
782
|
+
const migrated = migrateFontFamily(migrateTypographyScale(loaded))
|
|
971
783
|
setSettingsConfig(migrated)
|
|
972
784
|
applyThemeStyles(migrated)
|
|
973
785
|
}
|
|
@@ -977,7 +789,7 @@ export default function MintDashboard() {
|
|
|
977
789
|
window.addEventListener('focus', handleWindowFocus)
|
|
978
790
|
|
|
979
791
|
window.api?.onSettingsChanged?.((loaded: any) => {
|
|
980
|
-
const migrated = migrateTypographyScale(loaded)
|
|
792
|
+
const migrated = migrateFontFamily(migrateTypographyScale(loaded))
|
|
981
793
|
setSettingsConfig(migrated)
|
|
982
794
|
applyThemeStyles(migrated)
|
|
983
795
|
getRuntimeStatus().then(setStatus).catch(() => {})
|
|
@@ -985,21 +797,12 @@ export default function MintDashboard() {
|
|
|
985
797
|
|
|
986
798
|
const unlistenPromise = listen('tool-approval-requested', (event: { payload: any }) => {
|
|
987
799
|
const chatId = event.payload.chatId as string | undefined
|
|
988
|
-
if (
|
|
989
|
-
if (sessionAutoApprovedRef.current && autoApprovedChatIdRef.current === chatId) {
|
|
990
|
-
submitToolApproval(event.payload.token, true).catch((err) => {
|
|
991
|
-
console.error("Auto approval failed:", err)
|
|
992
|
-
})
|
|
993
|
-
} else {
|
|
994
|
-
setPendingApprovals((current) => ({ ...current, [chatId]: event.payload }))
|
|
995
|
-
notifyPendingApproval(event.payload)
|
|
996
|
-
}
|
|
800
|
+
if (chatId) conversationActions.receiveApproval(chatId, event.payload)
|
|
997
801
|
})
|
|
998
802
|
return () => {
|
|
999
803
|
window.removeEventListener('focus', handleWindowFocus)
|
|
1000
804
|
unlistenPromise?.then?.((unlisten) => unlisten?.())
|
|
1001
805
|
unlistenSpotlight?.then?.((unlisten) => unlisten?.())
|
|
1002
|
-
unlistenVision?.then?.((unlisten) => unlisten?.())
|
|
1003
806
|
}
|
|
1004
807
|
}, [])
|
|
1005
808
|
|
|
@@ -1008,10 +811,6 @@ export default function MintDashboard() {
|
|
|
1008
811
|
return () => window.clearTimeout(timer)
|
|
1009
812
|
}, [])
|
|
1010
813
|
|
|
1011
|
-
useEffect(() => {
|
|
1012
|
-
if (view === 'pictures' || view === 'imagine') refreshPictures().catch((reason: unknown) => setError(errorMessage(reason)))
|
|
1013
|
-
}, [view])
|
|
1014
|
-
|
|
1015
814
|
useEffect(() => {
|
|
1016
815
|
if (view === 'workspace' && !agentMode) updateAgentMode(true)
|
|
1017
816
|
}, [view, agentMode])
|
|
@@ -1021,7 +820,7 @@ export default function MintDashboard() {
|
|
|
1021
820
|
setTimeout(() => setToastMessage((current) => current === nextMessage ? '' : current), 3000)
|
|
1022
821
|
}
|
|
1023
822
|
|
|
1024
|
-
const openMintBrowser = async (url: string) => {
|
|
823
|
+
const openMintBrowser = async (url: string, throwOnError = false) => {
|
|
1025
824
|
if (!isDesktopApp) {
|
|
1026
825
|
window.open(url, '_blank', 'noopener,noreferrer')
|
|
1027
826
|
return
|
|
@@ -1031,10 +830,35 @@ export default function MintDashboard() {
|
|
|
1031
830
|
const { invoke } = await import('@tauri-apps/api/core')
|
|
1032
831
|
await invoke('open_mint_browser', { url })
|
|
1033
832
|
} catch (error) {
|
|
833
|
+
if (throwOnError) throw error
|
|
1034
834
|
showToast(`Could not open browser: ${String(error)}`)
|
|
1035
835
|
}
|
|
1036
836
|
}
|
|
1037
837
|
|
|
838
|
+
const openHtmlFile = async (root: string, relativePath: string, mode: 'external' | 'mint') => {
|
|
839
|
+
if (!isDesktopApp && !['localhost', '127.0.0.1', '[::1]', '::1'].includes(window.location.hostname)) {
|
|
840
|
+
throw new Error('HTML preview requires a browser on the same machine as the Mint backend.')
|
|
841
|
+
}
|
|
842
|
+
const popup = !isDesktopApp && mode === 'external' ? window.open('about:blank', '_blank') : null
|
|
843
|
+
if (popup) popup.opener = null
|
|
844
|
+
try {
|
|
845
|
+
const preview = await workspacePlatform.startHtmlPreview(root, relativePath, !isDesktopApp && mode === 'mint')
|
|
846
|
+
if (mode === 'mint') {
|
|
847
|
+
if (isDesktopApp) await openMintBrowser(preview.url, true)
|
|
848
|
+
} else if (isDesktopApp) {
|
|
849
|
+
const { invoke } = await import('@tauri-apps/api/core')
|
|
850
|
+
await invoke('run_desktop_action', { action: { type: 'open_url', target: preview.url } })
|
|
851
|
+
} else {
|
|
852
|
+
if (!popup) throw new Error('Allow browser popups, then open the HTML file again.')
|
|
853
|
+
popup.location.replace(preview.url)
|
|
854
|
+
}
|
|
855
|
+
showToast('HTML preview is running. Open Tools → Background tasks to view or stop the server.')
|
|
856
|
+
} catch (error) {
|
|
857
|
+
popup?.close()
|
|
858
|
+
throw error
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
1038
862
|
const openTerminalSurface = () => {
|
|
1039
863
|
setToolsPanelOpen(true)
|
|
1040
864
|
const id = `terminal:${Date.now()}:${Math.random().toString(36).slice(2, 7)}`
|
|
@@ -1053,6 +877,17 @@ export default function MintDashboard() {
|
|
|
1053
877
|
})
|
|
1054
878
|
}
|
|
1055
879
|
|
|
880
|
+
const openUtilitySurface = (kind: 'mods' | 'background') => {
|
|
881
|
+
setToolsPanelOpen(true)
|
|
882
|
+
setToolSurfaces(current => current.some(surface => surface.id === kind) ? current : [...current, { id: kind, kind, title: kind === 'mods' ? 'Mods' : 'Background tasks' }])
|
|
883
|
+
setActiveSurfaceId(kind)
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
const closeToolsPanel = () => {
|
|
887
|
+
setToolsPanelOpen(false)
|
|
888
|
+
requestAnimationFrame(() => document.querySelector<HTMLButtonElement>('.tools-panel-toggle')?.focus())
|
|
889
|
+
}
|
|
890
|
+
|
|
1056
891
|
const openNativeBrowser = (url = 'https://www.google.com') => {
|
|
1057
892
|
void openMintBrowser(url)
|
|
1058
893
|
}
|
|
@@ -1061,6 +896,7 @@ export default function MintDashboard() {
|
|
|
1061
896
|
setToolSurfaces((current) => {
|
|
1062
897
|
const source = current.find((surface) => surface.id === id)
|
|
1063
898
|
if (!source) return current
|
|
899
|
+
if (source.kind === 'mods' || source.kind === 'background') return current
|
|
1064
900
|
const duplicateId = `${source.kind}:${Date.now()}:${Math.random().toString(36).slice(2, 7)}`
|
|
1065
901
|
const duplicate = { ...source, id: duplicateId, title: `${source.title} copy` } as ToolSurface
|
|
1066
902
|
setActiveSurfaceId(duplicateId)
|
|
@@ -1106,7 +942,8 @@ export default function MintDashboard() {
|
|
|
1106
942
|
const openArtifactSurface = (artifact: import('./ArtifactPreviewPanel').ArtifactFile) => {
|
|
1107
943
|
setToolsPanelOpen(true)
|
|
1108
944
|
const fileName = artifact.path.replace(/\\/g, '/').split('/').pop() || artifact.path
|
|
1109
|
-
|
|
945
|
+
artifact = { ...artifact, workspacePath: artifact.workspacePath ?? workspacePath }
|
|
946
|
+
const id = `preview:${JSON.stringify([artifact.workspacePath, artifact.path])}`
|
|
1110
947
|
setToolSurfaces((current) => {
|
|
1111
948
|
const next = current.filter((surface) => surface.id !== id)
|
|
1112
949
|
return [...next, { id, kind: 'preview', title: fileName, artifact }]
|
|
@@ -1114,6 +951,14 @@ export default function MintDashboard() {
|
|
|
1114
951
|
setActiveSurfaceId(id)
|
|
1115
952
|
}
|
|
1116
953
|
|
|
954
|
+
const openWorkspacePreview = async (root: string, path: string) => {
|
|
955
|
+
const artifact = await createWorkspacePreview(root, path, {
|
|
956
|
+
readWorkspaceFile: (file, workspace) => runtimePlatform.readWorkspaceFile(file, workspace),
|
|
957
|
+
startHtmlPreview: (workspace, file) => workspacePlatform.startHtmlPreview(workspace, file),
|
|
958
|
+
})
|
|
959
|
+
openArtifactSurface(artifact)
|
|
960
|
+
}
|
|
961
|
+
|
|
1117
962
|
const openReviewSurface = (review: Extract<ToolSurface, { kind: 'review' }>) => {
|
|
1118
963
|
setToolsPanelOpen(true)
|
|
1119
964
|
setToolSurfaces((current) => [...current.filter((surface) => surface.id !== review.id), review])
|
|
@@ -1194,217 +1039,25 @@ export default function MintDashboard() {
|
|
|
1194
1039
|
setPlanMode(enabled)
|
|
1195
1040
|
}
|
|
1196
1041
|
|
|
1197
|
-
const updateWorkspacePath = (path: string) => {
|
|
1042
|
+
const updateWorkspacePath = (path: string, persist = true) => {
|
|
1198
1043
|
const next = path.trim()
|
|
1199
1044
|
conversationActions.selectWorkspace(next)
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
if (!sending) {
|
|
1204
|
-
sessionAutoApprovedRef.current = false
|
|
1205
|
-
autoApprovedChatIdRef.current = null
|
|
1206
|
-
setSessionAutoApproved(false)
|
|
1207
|
-
}
|
|
1208
|
-
}, [sending])
|
|
1209
|
-
|
|
1210
|
-
async function handleApproval(approved: boolean, autoApproveSession = false, answer?: string) {
|
|
1211
|
-
const chatId = conversationId
|
|
1212
|
-
const pendingApproval = pendingApprovals[chatId]
|
|
1213
|
-
if (!pendingApproval) return
|
|
1214
|
-
try {
|
|
1215
|
-
if (autoApproveSession) {
|
|
1216
|
-
sessionAutoApprovedRef.current = true
|
|
1217
|
-
autoApprovedChatIdRef.current = chatId
|
|
1218
|
-
setSessionAutoApproved(true)
|
|
1219
|
-
}
|
|
1220
|
-
await submitToolApproval(pendingApproval.token, approved, answer)
|
|
1221
|
-
setPendingApprovals((current) => {
|
|
1222
|
-
if (current[chatId]?.token !== pendingApproval.token) return current
|
|
1223
|
-
const next = { ...current }
|
|
1224
|
-
delete next[chatId]
|
|
1225
|
-
return next
|
|
1226
|
-
})
|
|
1227
|
-
} catch (reason) {
|
|
1228
|
-
setError(errorMessage(reason))
|
|
1045
|
+
const activeId = conversationActions.getSnapshot().conversationId
|
|
1046
|
+
if (persist && isPersistedConversation(activeId, chatSessions)) {
|
|
1047
|
+
void handleUpdateSessionWorkspace(activeId, next || null)
|
|
1229
1048
|
}
|
|
1230
1049
|
}
|
|
1231
1050
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
runGenerationRef.current += 1
|
|
1235
|
-
try {
|
|
1236
|
-
await conversationActions.executeCancellation(() =>
|
|
1237
|
-
cancelChatMessage(streamingConversationId),
|
|
1238
|
-
)
|
|
1239
|
-
} catch (e) {
|
|
1240
|
-
console.error("Failed to cancel message stream:", e)
|
|
1241
|
-
} finally {
|
|
1242
|
-
setPendingApprovals((current) => {
|
|
1243
|
-
const next = { ...current }
|
|
1244
|
-
delete next[streamingConversationId]
|
|
1245
|
-
return next
|
|
1246
|
-
})
|
|
1247
|
-
setStreamingConversationId(null)
|
|
1248
|
-
setActiveTurnId(null)
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1051
|
+
const handleApproval = conversationActions.resolveApproval
|
|
1052
|
+
const handleCancelMessage = conversationActions.cancel
|
|
1251
1053
|
|
|
1252
|
-
async function sendPrompt(
|
|
1253
|
-
|
|
1254
|
-
options: {
|
|
1255
|
-
imageAttachments?: Array<{ dataUri: string; name: string; previewDataUri?: string }>
|
|
1256
|
-
videoAttachments?: Array<{ dataUri: string; name: string }>
|
|
1257
|
-
audioDataUri?: string | null
|
|
1258
|
-
documentAttachment?: DocumentAttachment | null
|
|
1259
|
-
systemInstruction?: string
|
|
1260
|
-
clearComposer?: boolean
|
|
1261
|
-
pinnedMcpServer?: string
|
|
1262
|
-
forceAgentMode?: boolean
|
|
1263
|
-
} = {},
|
|
1264
|
-
) {
|
|
1265
|
-
if (sending) return
|
|
1266
|
-
const originChatId = conversationId
|
|
1267
|
-
const originWorkspacePath = workspacePath || null
|
|
1268
|
-
const sessionGeneration = sessionGenerationRef.current
|
|
1269
|
-
const runGeneration = ++runGenerationRef.current
|
|
1270
|
-
const originRun = { chatId: originChatId, sessionGeneration, runGeneration }
|
|
1271
|
-
const isCurrentRun = () => matchesActiveRun(originRun, {
|
|
1272
|
-
chatId: activeConversationRef.current,
|
|
1273
|
-
sessionGeneration: sessionGenerationRef.current,
|
|
1274
|
-
runGeneration: runGenerationRef.current,
|
|
1275
|
-
})
|
|
1276
|
-
let turnId: number | null = null
|
|
1277
|
-
const outgoingImages = options.imageAttachments ?? []
|
|
1278
|
-
const outgoingVideos = options.videoAttachments ?? []
|
|
1279
|
-
const outgoingDocument = options.documentAttachment ?? null
|
|
1280
|
-
const shouldUseAgentMode = agentMode || options.forceAgentMode || promptText.toLowerCase().startsWith('search web:')
|
|
1281
|
-
const outgoingImage = outgoingImages.map((img) => img.dataUri).join(' ')
|
|
1282
|
-
const outgoingVideo = outgoingVideos.map((vid) => vid.dataUri).join(' ')
|
|
1283
|
-
const outgoingImageCount = outgoingImages.length
|
|
1284
|
-
conversationActions.startRun(promptText, outgoingImageCount, outgoingVideos.length)
|
|
1285
|
-
setStreamingConversationId(conversationId)
|
|
1286
|
-
setActiveTurnId(null)
|
|
1054
|
+
async function sendPrompt(promptText: string, options: PromptOptions = {}) {
|
|
1055
|
+
if (conversationActions.getSnapshot().sending) return
|
|
1287
1056
|
setError('')
|
|
1288
1057
|
liveThinkingOpenRef.current = true
|
|
1289
1058
|
liveExtendedThinkingOpenRef.current = true
|
|
1290
|
-
setThinkingExpanded(
|
|
1291
|
-
|
|
1292
|
-
let pendingProgress: AgentProgress[] = []
|
|
1293
|
-
let progressFlushTimer: ReturnType<typeof setTimeout> | null = null
|
|
1294
|
-
const flushPendingProgress = () => {
|
|
1295
|
-
if (progressFlushTimer) {
|
|
1296
|
-
clearTimeout(progressFlushTimer)
|
|
1297
|
-
progressFlushTimer = null
|
|
1298
|
-
}
|
|
1299
|
-
if (pendingProgress.length === 0) return
|
|
1300
|
-
const batch = pendingProgress
|
|
1301
|
-
pendingProgress = []
|
|
1302
|
-
if (isCurrentRun()) conversationActions.receiveProgress(batch)
|
|
1303
|
-
}
|
|
1304
|
-
const queueProgress = (progress: AgentProgress) => {
|
|
1305
|
-
pendingProgress.push(progress)
|
|
1306
|
-
if (progress.type !== 'ThinkingDelta') {
|
|
1307
|
-
flushPendingProgress()
|
|
1308
|
-
} else if (!progressFlushTimer) {
|
|
1309
|
-
progressFlushTimer = setTimeout(flushPendingProgress, 75)
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
if (options.clearComposer) {
|
|
1313
|
-
conversationActions.clearComposer()
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
try {
|
|
1317
|
-
const response = await conversationActions.executeStream((onChunk) => streamChatMessage(
|
|
1318
|
-
shouldUseAgentMode ? promptText : `/chat ${promptText}`,
|
|
1319
|
-
onChunk,
|
|
1320
|
-
outgoingImage,
|
|
1321
|
-
options.audioDataUri ?? null,
|
|
1322
|
-
outgoingVideo,
|
|
1323
|
-
options.systemInstruction ?? '',
|
|
1324
|
-
(progress) => {
|
|
1325
|
-
progressSnapshot.push(progress)
|
|
1326
|
-
queueProgress(progress)
|
|
1327
|
-
},
|
|
1328
|
-
outgoingDocument,
|
|
1329
|
-
originWorkspacePath,
|
|
1330
|
-
originChatId,
|
|
1331
|
-
undefined,
|
|
1332
|
-
shouldUseAgentMode ? planMode : false,
|
|
1333
|
-
options.pinnedMcpServer ?? null,
|
|
1334
|
-
(payload) => {
|
|
1335
|
-
if (sessionAutoApprovedRef.current && autoApprovedChatIdRef.current === originChatId) {
|
|
1336
|
-
submitToolApproval(payload.token, true).catch((err) => {
|
|
1337
|
-
console.error("Auto approval failed:", err)
|
|
1338
|
-
})
|
|
1339
|
-
} else {
|
|
1340
|
-
setPendingApprovals((current) => ({ ...current, [originChatId]: payload }))
|
|
1341
|
-
notifyPendingApproval(payload)
|
|
1342
|
-
}
|
|
1343
|
-
},
|
|
1344
|
-
(id) => {
|
|
1345
|
-
turnId = id
|
|
1346
|
-
if (isCurrentRun()) setActiveTurnId(id)
|
|
1347
|
-
},
|
|
1348
|
-
), isCurrentRun)
|
|
1349
|
-
flushPendingProgress()
|
|
1350
|
-
if (document.hidden || !document.hasFocus()) {
|
|
1351
|
-
window.api?.notifyAiResponse?.(truncateForNotification(response.text))
|
|
1352
|
-
}
|
|
1353
|
-
const persistedProgress = compactAgentProgressForPersistence(progressSnapshot)
|
|
1354
|
-
if (persistedProgress.length > 0) {
|
|
1355
|
-
if (turnId != null) {
|
|
1356
|
-
const interactionKey = String(turnId)
|
|
1357
|
-
await saveInteractionAgentActivity(turnId, persistedProgress)
|
|
1358
|
-
if (isCurrentRun()) {
|
|
1359
|
-
setAgentActivitySnapshots((current) => ({
|
|
1360
|
-
...current,
|
|
1361
|
-
[interactionKey]: persistedProgress.slice(),
|
|
1362
|
-
}))
|
|
1363
|
-
setThinkingExpanded((current) => ({
|
|
1364
|
-
...current,
|
|
1365
|
-
...(liveThinkingOpenRef.current ? { [interactionKey]: true } : {}),
|
|
1366
|
-
...(liveExtendedThinkingOpenRef.current ? { [`extended-${interactionKey}`]: true } : {}),
|
|
1367
|
-
}))
|
|
1368
|
-
}
|
|
1369
|
-
} else {
|
|
1370
|
-
console.warn('Agent activity was not saved because the stream did not provide a turn ID')
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
if (isCurrentRun()) {
|
|
1374
|
-
try {
|
|
1375
|
-
await loadConversationHistory(originChatId, sessionGeneration)
|
|
1376
|
-
} catch (error) {
|
|
1377
|
-
console.error('Failed to refresh completed conversation:', error)
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
await refreshChatSessions()
|
|
1381
|
-
await refreshPictures()
|
|
1382
|
-
if (isCurrentRun() && typeof window !== 'undefined') {
|
|
1383
|
-
const pathname = (window.location.pathname || '').replace(/\/+$/, '')
|
|
1384
|
-
const hash = (window.location.hash || '').replace(/^#\/?/, '').replace(/\/+$/, '')
|
|
1385
|
-
const target = (pathname || hash).toLowerCase()
|
|
1386
|
-
if (!target || target === '' || target === '/chat' || target === 'chat' || target === '/index.html' || target === 'index.html') {
|
|
1387
|
-
window.history.replaceState({}, '', `/chat/${encodeURIComponent(originChatId)}`)
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
getRuntimeStatus().then(setStatus).catch(() => {})
|
|
1391
|
-
if (isCurrentRun()) conversationActions.clearStream()
|
|
1392
|
-
} catch (reason) {
|
|
1393
|
-
if (isCurrentRun()) setError(errorMessage(reason))
|
|
1394
|
-
} finally {
|
|
1395
|
-
flushPendingProgress()
|
|
1396
|
-
setPendingApprovals((current) => {
|
|
1397
|
-
if (!current[originChatId]) return current
|
|
1398
|
-
const next = { ...current }
|
|
1399
|
-
delete next[originChatId]
|
|
1400
|
-
return next
|
|
1401
|
-
})
|
|
1402
|
-
if (isCurrentRun()) {
|
|
1403
|
-
conversationActions.finishRun()
|
|
1404
|
-
setStreamingConversationId(null)
|
|
1405
|
-
setActiveTurnId(null)
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1059
|
+
setThinkingExpanded(current => ({ ...current, live: true, 'live-extended': true }))
|
|
1060
|
+
await conversationActions.sendPrompt(promptText, { ...options, agentMode, planMode })
|
|
1408
1061
|
}
|
|
1409
1062
|
|
|
1410
1063
|
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
|
@@ -1421,7 +1074,7 @@ export default function MintDashboard() {
|
|
|
1421
1074
|
// comes back as `not_handled` and falls through to the TS processor below.
|
|
1422
1075
|
let engineResp: SlashResponse | null = null
|
|
1423
1076
|
try {
|
|
1424
|
-
engineResp = await runSlashCommand(trimmed, workspacePath || null)
|
|
1077
|
+
engineResp = await runSlashCommand(trimmed, workspacePath || null, conversationId)
|
|
1425
1078
|
} catch {
|
|
1426
1079
|
engineResp = null
|
|
1427
1080
|
}
|
|
@@ -1464,7 +1117,7 @@ export default function MintDashboard() {
|
|
|
1464
1117
|
provider: 'system',
|
|
1465
1118
|
model: 'mint-cli',
|
|
1466
1119
|
}
|
|
1467
|
-
|
|
1120
|
+
conversationActions.appendInteraction(systemMsg)
|
|
1468
1121
|
} else {
|
|
1469
1122
|
const systemMsg = {
|
|
1470
1123
|
id: Date.now(),
|
|
@@ -1474,7 +1127,7 @@ export default function MintDashboard() {
|
|
|
1474
1127
|
provider: 'system',
|
|
1475
1128
|
model: 'mint-cli',
|
|
1476
1129
|
}
|
|
1477
|
-
|
|
1130
|
+
conversationActions.appendInteraction(systemMsg)
|
|
1478
1131
|
}
|
|
1479
1132
|
return
|
|
1480
1133
|
}
|
|
@@ -1488,7 +1141,7 @@ export default function MintDashboard() {
|
|
|
1488
1141
|
provider: 'system',
|
|
1489
1142
|
model: 'mint-cli',
|
|
1490
1143
|
}
|
|
1491
|
-
|
|
1144
|
+
conversationActions.appendInteraction(systemMsg)
|
|
1492
1145
|
saveSystemInteraction(conversationId, trimmed, slashResult.systemText || '', 'system', 'mint-cli').catch(() => {})
|
|
1493
1146
|
}
|
|
1494
1147
|
return
|
|
@@ -1657,16 +1310,16 @@ export default function MintDashboard() {
|
|
|
1657
1310
|
conversationActions.compose(message.trim() ? `Search web: ${message.trim()}` : 'Search web: ')
|
|
1658
1311
|
}
|
|
1659
1312
|
|
|
1660
|
-
async function selectWorkspace(path?: string) {
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1313
|
+
async function selectWorkspace(path?: string, showWorkspace = false) {
|
|
1314
|
+
const targetView = isDesktopApp && (showWorkspace || view === 'workspace') ? 'workspace' : 'chat'
|
|
1315
|
+
await conversationActions.selectProject(
|
|
1316
|
+
async () => path || await selectLinkedFolderPath(),
|
|
1317
|
+
{
|
|
1318
|
+
openSession: (session, nextView) => selectConversation(session.id, session, nextView),
|
|
1319
|
+
newChat: (targetPath, nextView) => clearHistory('New chat', targetPath, nextView),
|
|
1320
|
+
showCurrentView: nextView => changeView(nextView, conversationActions.getSnapshot().conversationId),
|
|
1321
|
+
}, targetView,
|
|
1322
|
+
)
|
|
1670
1323
|
}
|
|
1671
1324
|
|
|
1672
1325
|
function captureScreen() {
|
|
@@ -1692,27 +1345,17 @@ export default function MintDashboard() {
|
|
|
1692
1345
|
})
|
|
1693
1346
|
}
|
|
1694
1347
|
|
|
1695
|
-
async function clearHistory(action: 'New chat' | 'Clear history', targetWorkspacePath?: string | null) {
|
|
1696
|
-
const originChatId = conversationId
|
|
1697
|
-
const generation = sessionGenerationRef.current
|
|
1348
|
+
async function clearHistory(action: 'New chat' | 'Clear history', targetWorkspacePath?: string | null, targetView: 'chat' | 'workspace' = 'chat') {
|
|
1698
1349
|
try {
|
|
1699
1350
|
if (action === 'New chat') {
|
|
1700
1351
|
const next = createConversationId()
|
|
1701
1352
|
activateConversation(next)
|
|
1702
|
-
|
|
1703
|
-
setAgentActivitySnapshots({})
|
|
1704
|
-
conversationActions.switchSession()
|
|
1705
|
-
setViewState('chat')
|
|
1353
|
+
setViewState(targetView)
|
|
1706
1354
|
|
|
1707
1355
|
if (targetWorkspacePath !== undefined) {
|
|
1708
1356
|
updateWorkspacePath(targetWorkspacePath || '')
|
|
1709
1357
|
} else {
|
|
1710
|
-
|
|
1711
|
-
if (!currentSession || !currentSession.workspacePath) {
|
|
1712
|
-
updateWorkspacePath('')
|
|
1713
|
-
} else {
|
|
1714
|
-
updateWorkspacePath(currentSession.workspacePath)
|
|
1715
|
-
}
|
|
1358
|
+
updateWorkspacePath(workspacePath)
|
|
1716
1359
|
}
|
|
1717
1360
|
|
|
1718
1361
|
if (typeof window !== 'undefined') {
|
|
@@ -1724,12 +1367,8 @@ export default function MintDashboard() {
|
|
|
1724
1367
|
return
|
|
1725
1368
|
} else {
|
|
1726
1369
|
if (!window.confirm(`${action} will clear the current conversation history. Continue?`)) return
|
|
1727
|
-
await
|
|
1370
|
+
await conversationActions.clearHistory()
|
|
1728
1371
|
}
|
|
1729
|
-
if (!isCurrentSession(originChatId, generation)) return
|
|
1730
|
-
setInteractions([])
|
|
1731
|
-
setAgentActivitySnapshots({})
|
|
1732
|
-
conversationActions.switchSession()
|
|
1733
1372
|
} catch (reason) {
|
|
1734
1373
|
setError(errorMessage(reason))
|
|
1735
1374
|
}
|
|
@@ -1747,7 +1386,7 @@ export default function MintDashboard() {
|
|
|
1747
1386
|
provider: 'system',
|
|
1748
1387
|
model: 'mint-cli',
|
|
1749
1388
|
}
|
|
1750
|
-
|
|
1389
|
+
conversationActions.appendInteraction(systemMsg)
|
|
1751
1390
|
saveSystemInteraction(conversationId, userText, aiText, 'system', 'mint-cli').catch(() => {})
|
|
1752
1391
|
}
|
|
1753
1392
|
|
|
@@ -1775,13 +1414,19 @@ export default function MintDashboard() {
|
|
|
1775
1414
|
async function handleEngineSlashResponse(userText: string, resp: SlashResponse) {
|
|
1776
1415
|
switch (resp.kind) {
|
|
1777
1416
|
case 'message':
|
|
1778
|
-
pushSystemMessage(userText, resp.markdown)
|
|
1417
|
+
pushSystemMessage(userText.startsWith('/mods set ') ? '/mods' : userText, resp.markdown)
|
|
1418
|
+
if (userText.startsWith('/mods set ')) {
|
|
1419
|
+
requestAnimationFrame(() => document.getElementById('chat-input')?.focus())
|
|
1420
|
+
}
|
|
1779
1421
|
break
|
|
1780
1422
|
case 'applied': {
|
|
1781
1423
|
const wsChange = resp.effects.find((e) => e.kind === 'workspace_changed') as
|
|
1782
1424
|
| { kind: 'workspace_changed'; path: string }
|
|
1783
1425
|
| undefined
|
|
1784
|
-
if (wsChange)
|
|
1426
|
+
if (wsChange) updateWorkspacePath(wsChange.path)
|
|
1427
|
+
if (resp.effects.some((effect) => effect.kind === 'workspace_files_changed')) {
|
|
1428
|
+
setWorkspaceRefreshRevision((revision) => revision + 1)
|
|
1429
|
+
}
|
|
1785
1430
|
const planModeChange = resp.effects.find((e) => e.kind === 'plan_mode_changed') as
|
|
1786
1431
|
| { kind: 'plan_mode_changed'; enabled: boolean }
|
|
1787
1432
|
| undefined
|
|
@@ -1793,25 +1438,17 @@ export default function MintDashboard() {
|
|
|
1793
1438
|
// Render the same "✨ Gemini • model" chip the GUI's own /models shows.
|
|
1794
1439
|
// The engine already logged the `provider_change` row into the shared
|
|
1795
1440
|
// "cli" conversation, so this is just the immediate local echo.
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
model: 'provider_change',
|
|
1805
|
-
},
|
|
1806
|
-
])
|
|
1441
|
+
conversationActions.appendInteraction({
|
|
1442
|
+
id: Date.now(),
|
|
1443
|
+
userText: providerChange.display,
|
|
1444
|
+
aiText: '',
|
|
1445
|
+
createdAt: new Date().toISOString(),
|
|
1446
|
+
provider: 'system',
|
|
1447
|
+
model: 'provider_change',
|
|
1448
|
+
})
|
|
1807
1449
|
}
|
|
1808
1450
|
if (resp.effects.some((e) => e.kind === 'history_cleared')) {
|
|
1809
|
-
|
|
1810
|
-
const generation = sessionGenerationRef.current
|
|
1811
|
-
await clearChatHistory(chatId).catch(() => {})
|
|
1812
|
-
if (isCurrentSession(chatId, generation)) {
|
|
1813
|
-
setInteractions([])
|
|
1814
|
-
}
|
|
1451
|
+
await conversationActions.clearHistory().catch(() => {})
|
|
1815
1452
|
}
|
|
1816
1453
|
if (resp.markdown) pushSystemMessage(userText, resp.markdown)
|
|
1817
1454
|
if (resp.effects.some((e) => e.kind !== 'history_cleared' && e.kind !== 'workspace_changed')) {
|
|
@@ -1844,35 +1481,33 @@ export default function MintDashboard() {
|
|
|
1844
1481
|
setThinkingExpanded((current) => ({ ...current, [key]: open }))
|
|
1845
1482
|
}
|
|
1846
1483
|
|
|
1847
|
-
async function selectConversation(id: string) {
|
|
1484
|
+
async function selectConversation(id: string, selectedSession?: ChatSession, targetView: 'chat' | 'workspace' = 'chat') {
|
|
1848
1485
|
window.localStorage.setItem(ACTIVE_CONVERSATION_ID_KEY, id)
|
|
1849
1486
|
touchActiveTimestamp()
|
|
1850
1487
|
activateConversation(id)
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
conversationActions.switchSession()
|
|
1854
|
-
const session = chatSessions.find((item) => item.id === id)
|
|
1488
|
+
changeView(targetView, id)
|
|
1489
|
+
const session = selectedSession ?? chatSessions.find((item) => item.id === id)
|
|
1855
1490
|
if (session) {
|
|
1856
1491
|
if (session.workspacePath) {
|
|
1857
1492
|
if (session.workspacePath !== workspacePath) {
|
|
1858
|
-
updateWorkspacePath(session.workspacePath)
|
|
1493
|
+
updateWorkspacePath(session.workspacePath, false)
|
|
1859
1494
|
}
|
|
1860
1495
|
} else {
|
|
1861
1496
|
if (workspacePath) {
|
|
1862
|
-
updateWorkspacePath('')
|
|
1497
|
+
updateWorkspacePath('', false)
|
|
1863
1498
|
}
|
|
1864
1499
|
}
|
|
1865
1500
|
}
|
|
1866
1501
|
try {
|
|
1867
|
-
await
|
|
1502
|
+
await conversationActions.refreshHistory()
|
|
1868
1503
|
} catch (reason) {
|
|
1869
|
-
|
|
1504
|
+
setError(errorMessage(reason))
|
|
1870
1505
|
}
|
|
1871
1506
|
}
|
|
1872
1507
|
|
|
1873
|
-
const handleNewChatInProject =
|
|
1874
|
-
clearHistory('New chat', targetPath)
|
|
1875
|
-
}
|
|
1508
|
+
const handleNewChatInProject = (targetPath: string) => {
|
|
1509
|
+
void clearHistory('New chat', targetPath)
|
|
1510
|
+
}
|
|
1876
1511
|
|
|
1877
1512
|
async function deleteConversation(id: string) {
|
|
1878
1513
|
if (id === 'cli') {
|
|
@@ -1894,7 +1529,7 @@ export default function MintDashboard() {
|
|
|
1894
1529
|
try {
|
|
1895
1530
|
await deleteChatSession(id)
|
|
1896
1531
|
const remaining = chatSessions.filter((item) => item.id !== id && item.kind !== 'cli' && !item.id.startsWith('cli') && item.id !== 'conversation-default')
|
|
1897
|
-
const currentChatId =
|
|
1532
|
+
const currentChatId = conversationActions.getSnapshot().conversationId
|
|
1898
1533
|
const nextActive = id === currentChatId
|
|
1899
1534
|
? (remaining[0]?.id ?? createConversationId())
|
|
1900
1535
|
: currentChatId
|
|
@@ -1912,15 +1547,10 @@ export default function MintDashboard() {
|
|
|
1912
1547
|
}
|
|
1913
1548
|
}
|
|
1914
1549
|
activateConversation(nextActive)
|
|
1915
|
-
|
|
1916
|
-
conversationActions.clearProgress()
|
|
1917
|
-
await loadConversationHistory(nextActive, generation)
|
|
1918
|
-
if (!isCurrentSession(nextActive, generation)) return
|
|
1550
|
+
await conversationActions.refreshHistory()
|
|
1919
1551
|
}
|
|
1920
1552
|
|
|
1921
1553
|
await refreshChatSessions()
|
|
1922
|
-
if (id !== currentChatId) return
|
|
1923
|
-
conversationActions.switchSession()
|
|
1924
1554
|
} catch (reason) {
|
|
1925
1555
|
setError(errorMessage(reason))
|
|
1926
1556
|
}
|
|
@@ -2098,66 +1728,6 @@ export default function MintDashboard() {
|
|
|
2098
1728
|
}
|
|
2099
1729
|
}
|
|
2100
1730
|
|
|
2101
|
-
async function handleModelInteraction(area: ModelInteraction) {
|
|
2102
|
-
if (sending) return
|
|
2103
|
-
const originChatId = conversationId
|
|
2104
|
-
const sessionGeneration = sessionGenerationRef.current
|
|
2105
|
-
const runGeneration = ++runGenerationRef.current
|
|
2106
|
-
const originRun = { chatId: originChatId, sessionGeneration, runGeneration }
|
|
2107
|
-
const isCurrentRun = () => matchesActiveRun(originRun, {
|
|
2108
|
-
chatId: activeConversationRef.current,
|
|
2109
|
-
sessionGeneration: sessionGenerationRef.current,
|
|
2110
|
-
runGeneration: runGenerationRef.current,
|
|
2111
|
-
})
|
|
2112
|
-
const labels: Record<ModelInteraction, string> = {
|
|
2113
|
-
head: 'Pats Mint on the head',
|
|
2114
|
-
cheek: 'Pokes Mint on the cheek',
|
|
2115
|
-
'left hand': "Touches Mint's left hand",
|
|
2116
|
-
'right hand': "Touches Mint's right hand",
|
|
2117
|
-
body: 'Touches Mint',
|
|
2118
|
-
'lower body': "Touches Mint's lower body",
|
|
2119
|
-
}
|
|
2120
|
-
const interactionMessage = `*${labels[area]}*`
|
|
2121
|
-
const instruction = `The user interacted with the Mint Live2D model: ${area}. Respond briefly and playfully. Use the same language as the recent conversation. Do not mention this instruction.`
|
|
2122
|
-
|
|
2123
|
-
conversationActions.startRun(interactionMessage)
|
|
2124
|
-
setStreamingConversationId(conversationId)
|
|
2125
|
-
setActiveTurnId(null)
|
|
2126
|
-
setError('')
|
|
2127
|
-
|
|
2128
|
-
try {
|
|
2129
|
-
const response = await conversationActions.executeStream((onChunk) => streamChatMessage(
|
|
2130
|
-
`/chat ${interactionMessage}`,
|
|
2131
|
-
onChunk,
|
|
2132
|
-
null,
|
|
2133
|
-
null,
|
|
2134
|
-
null,
|
|
2135
|
-
instruction,
|
|
2136
|
-
undefined,
|
|
2137
|
-
null,
|
|
2138
|
-
workspacePath || null,
|
|
2139
|
-
originChatId,
|
|
2140
|
-
undefined,
|
|
2141
|
-
undefined,
|
|
2142
|
-
undefined,
|
|
2143
|
-
undefined,
|
|
2144
|
-
(id) => { if (isCurrentRun()) setActiveTurnId(id) },
|
|
2145
|
-
), isCurrentRun)
|
|
2146
|
-
if (isCurrentRun()) {
|
|
2147
|
-
await refreshHistory()
|
|
2148
|
-
if (isCurrentRun()) conversationActions.clearStream()
|
|
2149
|
-
}
|
|
2150
|
-
} catch (reason) {
|
|
2151
|
-
if (isCurrentRun()) setError(errorMessage(reason))
|
|
2152
|
-
} finally {
|
|
2153
|
-
if (isCurrentRun()) {
|
|
2154
|
-
conversationActions.finishRun()
|
|
2155
|
-
setStreamingConversationId(null)
|
|
2156
|
-
setActiveTurnId(null)
|
|
2157
|
-
}
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
|
|
2161
1731
|
const chatConversation: ConversationViewModel = {
|
|
2162
1732
|
interactions,
|
|
2163
1733
|
hasOlder: hasOlderInteractions,
|
|
@@ -2181,15 +1751,26 @@ export default function MintDashboard() {
|
|
|
2181
1751
|
status,
|
|
2182
1752
|
workspacePath,
|
|
2183
1753
|
chatId: conversationId,
|
|
2184
|
-
recentWorkspacePaths,
|
|
1754
|
+
recentWorkspacePaths: availableWorkspacePaths,
|
|
2185
1755
|
chatEnd,
|
|
2186
1756
|
welcomeInteraction: MOCK_WELCOME_INTERACTION,
|
|
2187
1757
|
settingsConfig,
|
|
1758
|
+
slashChoice: pendingSlashChoice,
|
|
2188
1759
|
isCliSession: conversationId.startsWith('cli') || conversationId === 'cli',
|
|
2189
1760
|
cliSessionId: conversationId.startsWith('cli') ? conversationId : undefined,
|
|
2190
1761
|
conversationTitle: chatSessions.find((session) => session.id === conversationId)?.title,
|
|
2191
1762
|
}
|
|
2192
1763
|
const chatActions: ConversationActions = {
|
|
1764
|
+
onSelectSlashChoice: (value) => {
|
|
1765
|
+
if (!pendingSlashChoice) return
|
|
1766
|
+
const next = `${pendingSlashChoice.command} ${value}`
|
|
1767
|
+
setPendingSlashChoice(null)
|
|
1768
|
+
requestAnimationFrame(() => document.getElementById('chat-input')?.focus())
|
|
1769
|
+
runSlashCommand(next, workspacePath || null, conversationId)
|
|
1770
|
+
.then((response) => handleEngineSlashResponse(next, response))
|
|
1771
|
+
.catch(() => {})
|
|
1772
|
+
},
|
|
1773
|
+
onDismissSlashChoice: () => setPendingSlashChoice(null),
|
|
2193
1774
|
onLoadOlder: loadOlderInteractions,
|
|
2194
1775
|
onThinkingExpandedChange: handleThinkingExpandedChange,
|
|
2195
1776
|
onSubmit: handleSubmit,
|
|
@@ -2207,7 +1788,7 @@ export default function MintDashboard() {
|
|
|
2207
1788
|
onSetAgentMode: updateAgentMode,
|
|
2208
1789
|
onSetPlanMode: isDesktopApp ? updatePlanMode : undefined,
|
|
2209
1790
|
onSetProvider: changeProvider,
|
|
2210
|
-
onSelectWorkspace:
|
|
1791
|
+
onSelectWorkspace: selectWorkspace,
|
|
2211
1792
|
onWorkspaceChanged: () => setWorkspaceRefreshRevision((revision) => revision + 1),
|
|
2212
1793
|
onApproval: handleApproval,
|
|
2213
1794
|
onUpdateSettings: (updated) => setSettingsConfig(updated),
|
|
@@ -2237,23 +1818,37 @@ export default function MintDashboard() {
|
|
|
2237
1818
|
sidebarCollapsed={sidebarCollapsed}
|
|
2238
1819
|
onToggleSidebar={toggleSidebar}
|
|
2239
1820
|
onNewChat={() => clearHistory('New chat')}
|
|
2240
|
-
onOpenWorkspace={() => selectWorkspace()}
|
|
1821
|
+
onOpenWorkspace={() => selectWorkspace(undefined, true)}
|
|
2241
1822
|
onOpenTerminal={openTerminalSurface}
|
|
2242
1823
|
onToggleTerminal={toggleTerminalSurface}
|
|
2243
1824
|
onOpenBrowser={() => openNativeBrowser()}
|
|
2244
1825
|
toolsPanelOpen={toolsPanelOpen}
|
|
1826
|
+
backgroundTaskCount={backgroundTaskCount}
|
|
2245
1827
|
onToggleToolsPanel={() => setToolsPanelOpen((open) => !open)}
|
|
2246
1828
|
onOpenSettings={() => changeView('settings')}
|
|
2247
1829
|
onCheckForUpdates={checkForUpdatesFromMenu}
|
|
2248
1830
|
onShowAbout={() => showToast('Mint Agent — AI workspace')}
|
|
2249
1831
|
workspacePath={workspacePath}
|
|
1832
|
+
workspaceActive={view === 'workspace' && !toolsPanelOpen}
|
|
1833
|
+
workspaceRevision={workspaceRefreshRevision}
|
|
1834
|
+
sending={sending}
|
|
1835
|
+
onWorkspaceUndoError={showToast}
|
|
2250
1836
|
terminalCount={toolSurfaces.filter((surface) => surface.kind === 'terminal').length}
|
|
2251
|
-
|
|
1837
|
+
chatId={conversationId}
|
|
1838
|
+
liveProgress={streamingConversationId === conversationId ? agentProgress : []}
|
|
2252
1839
|
recentChanges={recentAgentChanges}
|
|
2253
1840
|
onOpenReview={(changes) => openReviewSurface({ id: `review:workspace:${Date.now()}`, kind: 'review', title: 'Review', reviewTitle: 'Recent agent changes', changes })}
|
|
2254
1841
|
onRefreshWorkspace={() => setWorkspaceRefreshRevision((revision) => revision + 1)}
|
|
2255
1842
|
/>
|
|
2256
1843
|
)}
|
|
1844
|
+
{notificationNotice && (
|
|
1845
|
+
<section className="mint-notification-notice" role="status" data-kind={notificationNotice.type}>
|
|
1846
|
+
<span>{notificationNotice.message}</span>
|
|
1847
|
+
{notificationNotice.chatId && <button type="button" onClick={() => { void notificationNavigationRef.current(notificationNotice.chatId!); setNotificationNotice(null) }}>Open chat</button>}
|
|
1848
|
+
<button type="button" aria-label="Dismiss notification" onClick={() => setNotificationNotice(null)}>×</button>
|
|
1849
|
+
</section>
|
|
1850
|
+
)}
|
|
1851
|
+
{error && <ErrorNotice key={error} message={error} onDismiss={() => setError('')} />}
|
|
2257
1852
|
<div
|
|
2258
1853
|
className={`app-body ${(sidebarCollapsed && window.innerWidth > 760) ? 'sidebar-collapsed' : ''} ${view === 'pictures' ? 'pictures-open' : ''} ${mobileSidebarOpen ? 'mobile-sidebar-open' : ''} ${toolsPanelOpen ? 'tool-surface-active' : ''}`}
|
|
2259
1854
|
style={{
|
|
@@ -2298,17 +1893,11 @@ export default function MintDashboard() {
|
|
|
2298
1893
|
}}
|
|
2299
1894
|
/>
|
|
2300
1895
|
)}
|
|
1896
|
+
{toastMessage && <div role="status" style={{ position: 'fixed', bottom: 22, right: 22, zIndex: 10000, padding: '12px 18px', borderRadius: 10, background: 'var(--bg-surface)', color: 'var(--text-main)', border: '1px solid var(--border-color)' }}>{toastMessage}</div>}
|
|
2301
1897
|
<DashboardSidebar
|
|
2302
1898
|
view={view}
|
|
2303
1899
|
sidebarCollapsed={sidebarCollapsed}
|
|
2304
|
-
modelVisible={modelVisible}
|
|
2305
1900
|
sending={sending}
|
|
2306
|
-
expressionIndex={expressionIndex}
|
|
2307
|
-
accessoryIndex={accessoryIndex}
|
|
2308
|
-
expressions={EXPRESSIONS}
|
|
2309
|
-
accessories={ACCESSORIES}
|
|
2310
|
-
interactionEnabled={interactionEnabled}
|
|
2311
|
-
showInteractionGuide={showInteractionGuide}
|
|
2312
1901
|
onToggleSidebar={toggleSidebar}
|
|
2313
1902
|
onSidebarResize={handleSidebarResize}
|
|
2314
1903
|
onSidebarResizeEnd={handleSidebarResizeEnd}
|
|
@@ -2319,12 +1908,6 @@ export default function MintDashboard() {
|
|
|
2319
1908
|
onDeleteConversation={deleteConversation}
|
|
2320
1909
|
onRenameConversation={renameConversation}
|
|
2321
1910
|
onSetView={changeView}
|
|
2322
|
-
onToggleModel={toggleModel}
|
|
2323
|
-
onSetExpressionIndex={setExpressionIndex}
|
|
2324
|
-
onSetAccessoryIndex={setAccessoryIndex}
|
|
2325
|
-
onSetInteractionEnabled={updateInteractionEnabled}
|
|
2326
|
-
onSetShowInteractionGuide={updateInteractionGuide}
|
|
2327
|
-
onShowToast={showToast}
|
|
2328
1911
|
isSearchOpen={isSearchOpen}
|
|
2329
1912
|
onSetSearchOpen={setIsSearchOpen}
|
|
2330
1913
|
showWorkspaceTab={isDesktopApp}
|
|
@@ -2335,7 +1918,7 @@ export default function MintDashboard() {
|
|
|
2335
1918
|
onUpdateSessionWorkspace={handleUpdateSessionWorkspace}
|
|
2336
1919
|
onNewChatInProject={handleNewChatInProject}
|
|
2337
1920
|
/>
|
|
2338
|
-
<main className={`assistant-workspace ${
|
|
1921
|
+
<main className={`assistant-workspace ${view === 'workspace' ? '' : 'chat-only'} ${view === 'workspace' ? 'workspace-open' : ''}`} style={(view === 'skills' || view === 'mcp' || view === 'plugins' || view === 'cron' || view === 'link' || view === 'pictures' || view === 'imagine' || view === 'veo' || view === 'code') ? { display: 'none' } : undefined}>
|
|
2339
1922
|
{proactiveSuggestion && (
|
|
2340
1923
|
<div className="proactive-bar" style={{ position: 'absolute', top: 0, left: 0, right: 0, zIndex: 100 }}>
|
|
2341
1924
|
<div className="proactive-header">
|
|
@@ -2358,37 +1941,10 @@ export default function MintDashboard() {
|
|
|
2358
1941
|
</div>
|
|
2359
1942
|
</div>
|
|
2360
1943
|
)}
|
|
2361
|
-
{pendingSlashChoice && (
|
|
2362
|
-
<div className="proactive-bar" style={{ position: 'absolute', top: 0, left: 0, right: 0, zIndex: 100 }}>
|
|
2363
|
-
<div className="proactive-header">
|
|
2364
|
-
<span className="proactive-icon">⚡</span>
|
|
2365
|
-
<div className="proactive-message">{pendingSlashChoice.title}</div>
|
|
2366
|
-
<button className="proactive-dismiss-btn" onClick={() => setPendingSlashChoice(null)}>
|
|
2367
|
-
Dismiss
|
|
2368
|
-
</button>
|
|
2369
|
-
</div>
|
|
2370
|
-
<div className="proactive-chips">
|
|
2371
|
-
{pendingSlashChoice.options.map((opt) => (
|
|
2372
|
-
<button
|
|
2373
|
-
key={opt.value}
|
|
2374
|
-
className="suggestion-chip"
|
|
2375
|
-
onClick={() => {
|
|
2376
|
-
const next = `${pendingSlashChoice.command} ${opt.value}`
|
|
2377
|
-
setPendingSlashChoice(null)
|
|
2378
|
-
runSlashCommand(next, workspacePath || null)
|
|
2379
|
-
.then((r) => handleEngineSlashResponse(next, r))
|
|
2380
|
-
.catch(() => {})
|
|
2381
|
-
}}
|
|
2382
|
-
>
|
|
2383
|
-
{opt.label}
|
|
2384
|
-
</button>
|
|
2385
|
-
))}
|
|
2386
|
-
</div>
|
|
2387
|
-
</div>
|
|
2388
|
-
)}
|
|
2389
1944
|
{view === 'workspace' && (
|
|
2390
1945
|
<Suspense fallback={<LazyPanelFallback />}>
|
|
2391
1946
|
<WorkspacePanel
|
|
1947
|
+
key={workspacePath}
|
|
2392
1948
|
agentMode={agentMode}
|
|
2393
1949
|
sending={sending}
|
|
2394
1950
|
workspacePath={workspacePath}
|
|
@@ -2396,38 +1952,29 @@ export default function MintDashboard() {
|
|
|
2396
1952
|
onSetMessage={conversationActions.compose}
|
|
2397
1953
|
onWorkspaceReady={updateWorkspacePath}
|
|
2398
1954
|
refreshRevision={workspaceRefreshRevision}
|
|
1955
|
+
onOpenHtml={openHtmlFile}
|
|
1956
|
+
onOpenPreview={openWorkspacePreview}
|
|
2399
1957
|
/>
|
|
2400
1958
|
</Suspense>
|
|
2401
1959
|
)}
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
isLocked={isLocked}
|
|
2408
|
-
isActive={modelVisible && view !== 'pictures' && view !== 'workspace' && view !== 'imagine' && view !== 'veo' && view !== 'skills' && view !== 'mcp' && view !== 'plugins'}
|
|
2409
|
-
layoutPreset={layoutPreset}
|
|
2410
|
-
sending={sending}
|
|
2411
|
-
interactionEnabled={interactionEnabled}
|
|
2412
|
-
showInteractionGuide={showInteractionGuide}
|
|
2413
|
-
toastMessage={toastMessage}
|
|
2414
|
-
onSetScale={setScale}
|
|
2415
|
-
onSetLocked={setIsLocked}
|
|
2416
|
-
onSetView={changeView}
|
|
2417
|
-
onChangeLayoutPreset={changeLayoutPreset}
|
|
2418
|
-
onDismissToast={() => setToastMessage('')}
|
|
2419
|
-
onInteract={handleModelInteraction}
|
|
2420
|
-
onModelLoadComplete={() => setModelReady(true)}
|
|
2421
|
-
/>
|
|
2422
|
-
</Suspense>
|
|
2423
|
-
<ChatPanel conversation={chatConversation} actions={chatActions} />
|
|
1960
|
+
<ChatPanel conversation={chatConversation} actions={chatActions} showSessionSources={!isDesktopApp} tools={{
|
|
1961
|
+
modsPanelTarget, onOpenMods: () => openUtilitySurface('mods'),
|
|
1962
|
+
open: toolsPanelOpen, backgroundTaskCount,
|
|
1963
|
+
onToggle: isDesktopApp ? undefined : () => setToolsPanelOpen(open => !open),
|
|
1964
|
+
}} />
|
|
2424
1965
|
</main>
|
|
2425
|
-
{
|
|
1966
|
+
{toolsPanelOpen && (
|
|
2426
1967
|
<Suspense fallback={<LazyPanelFallback />}>
|
|
2427
1968
|
<ToolSurfacePage
|
|
2428
1969
|
surfaces={toolSurfaces}
|
|
2429
1970
|
activeSurfaceId={activeSurfaceId}
|
|
2430
1971
|
workspacePath={workspacePath}
|
|
1972
|
+
desktopTools={isDesktopApp}
|
|
1973
|
+
backgroundTaskCount={backgroundTaskCount}
|
|
1974
|
+
onOpenMods={() => openUtilitySurface('mods')}
|
|
1975
|
+
onOpenBackgroundTasks={() => openUtilitySurface('background')}
|
|
1976
|
+
onModsPanelTarget={setModsPanelTarget}
|
|
1977
|
+
onBackgroundPanelTarget={setBackgroundPanelTarget}
|
|
2431
1978
|
terminalSize={terminalRightWidth}
|
|
2432
1979
|
onSelect={setActiveSurfaceId}
|
|
2433
1980
|
onClose={closeToolSurface}
|
|
@@ -2444,7 +1991,7 @@ export default function MintDashboard() {
|
|
|
2444
1991
|
changeView('workspace')
|
|
2445
1992
|
}}
|
|
2446
1993
|
onOpenSideChat={() => { setActiveSurfaceId(null); setToolsPanelOpen(false) }}
|
|
2447
|
-
onClosePanel={
|
|
1994
|
+
onClosePanel={closeToolsPanel}
|
|
2448
1995
|
onResizeTerminal={(size) => {
|
|
2449
1996
|
setTerminalRightWidth(size)
|
|
2450
1997
|
if (terminalSaveTimeoutRef.current) clearTimeout(terminalSaveTimeoutRef.current)
|
|
@@ -2462,6 +2009,7 @@ export default function MintDashboard() {
|
|
|
2462
2009
|
/>
|
|
2463
2010
|
</Suspense>
|
|
2464
2011
|
)}
|
|
2012
|
+
<BackgroundTerminals workspacePath={workspacePath} panelTarget={backgroundPanelTarget} onCountChange={setBackgroundTaskCount} />
|
|
2465
2013
|
{view === 'skills' && (
|
|
2466
2014
|
<div className="web-view-scroll" style={{ flex: 1, overflowY: 'auto', background: 'transparent' }}>
|
|
2467
2015
|
<Suspense fallback={<LazyPanelFallback />}>
|
|
@@ -2550,6 +2098,8 @@ export default function MintDashboard() {
|
|
|
2550
2098
|
chatSessions={chatSessions}
|
|
2551
2099
|
activeConversationId={conversationId}
|
|
2552
2100
|
workspacePath={workspacePath}
|
|
2101
|
+
recentWorkspacePaths={availableWorkspacePaths}
|
|
2102
|
+
onSelectFolder={selectCodeHubFolder}
|
|
2553
2103
|
onSelectSession={(id) => {
|
|
2554
2104
|
selectConversation(id)
|
|
2555
2105
|
}}
|
|
@@ -2563,14 +2113,13 @@ export default function MintDashboard() {
|
|
|
2563
2113
|
)}
|
|
2564
2114
|
{view === 'pictures' && (
|
|
2565
2115
|
<Suspense fallback={<LazyPanelFallback />}>
|
|
2566
|
-
<
|
|
2116
|
+
<LibraryPage chatId={conversationId} onClose={() => changeView('chat')} onOpenConversation={id => { void selectConversation(id) }} />
|
|
2567
2117
|
</Suspense>
|
|
2568
2118
|
)}
|
|
2569
2119
|
{view === 'imagine' && (
|
|
2570
2120
|
<Suspense fallback={<LazyPanelFallback />}>
|
|
2571
2121
|
<ImageStudioPanel
|
|
2572
2122
|
view={view}
|
|
2573
|
-
onRefreshPictures={refreshPictures}
|
|
2574
2123
|
onSendToChat={async (imagePath, imgPrompt) => {
|
|
2575
2124
|
try {
|
|
2576
2125
|
const response = await fetch(convertFileSrc(imagePath))
|
|
@@ -2608,17 +2157,6 @@ export default function MintDashboard() {
|
|
|
2608
2157
|
<div className="startup-loading-text">Loading Mint Agent</div>
|
|
2609
2158
|
</div>
|
|
2610
2159
|
</div>
|
|
2611
|
-
{error && (
|
|
2612
|
-
<div className="mint-error" style={{ position: 'absolute', bottom: '20px', right: '20px', zIndex: 100, margin: 0, boxShadow: '0 8px 24px rgba(0,0,0,0.3)', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
2613
|
-
<span>{error}</span>
|
|
2614
|
-
<button onClick={() => setError('')} style={{ background: 'transparent', border: 0, color: 'white', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', padding: 0 }}>
|
|
2615
|
-
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
|
2616
|
-
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
2617
|
-
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
2618
|
-
</svg>
|
|
2619
|
-
</button>
|
|
2620
|
-
</div>
|
|
2621
|
-
)}
|
|
2622
2160
|
|
|
2623
2161
|
{isSearchOpen && (
|
|
2624
2162
|
<Suspense fallback={null}>
|